From 686e08199c37a7c02cd59dc997af69aa054bff30 Mon Sep 17 00:00:00 2001 From: Bruce Date: Tue, 14 Apr 2026 16:09:13 +0800 Subject: [PATCH] Streamlined the libraries. --- FindWinJS.ps1 | 66 + Used Libraries/codemirror.7z | Bin 0 -> 608214 bytes Used Libraries/readme.txt | 3 + .../winjs/3.0.7z => Used Libraries/winjs.7z | Bin 1200290 -> 1737761 bytes .../150x150Logo.scale-100_contrast-black.png | Bin 1628 -> 0 bytes .../150x150Logo.scale-100_contrast-white.png | Bin 4179 -> 0 bytes .../150x150Logo.scale-140_contrast-black.png | Bin 2546 -> 0 bytes .../150x150Logo.scale-140_contrast-white.png | Bin 5091 -> 0 bytes .../150x150Logo.scale-180_contrast-black.png | Bin 3513 -> 0 bytes .../150x150Logo.scale-180_contrast-white.png | Bin 5988 -> 0 bytes .../150x150Logo.scale-80_contrast-black.png | Bin 1120 -> 0 bytes .../150x150Logo.scale-80_contrast-white.png | Bin 3723 -> 0 bytes .../70x70Logo.scale-100_contrast-black.png | Bin 707 -> 0 bytes .../70x70Logo.scale-100_contrast-white.png | Bin 3313 -> 0 bytes .../70x70Logo.scale-140_contrast-black.png | Bin 707 -> 0 bytes .../70x70Logo.scale-140_contrast-white.png | Bin 3313 -> 0 bytes .../70x70Logo.scale-180_contrast-black.png | Bin 1251 -> 0 bytes .../70x70Logo.scale-180_contrast-white.png | Bin 3847 -> 0 bytes .../70x70Logo.scale-80_contrast-black.png | Bin 570 -> 0 bytes .../70x70Logo.scale-80_contrast-white.png | Bin 3184 -> 0 bytes .../html/libs/codemirror/5.0.0/.gitattributes | 8 - shared/html/libs/codemirror/5.0.0/.gitignore | 8 - shared/html/libs/codemirror/5.0.0/.travis.yml | 3 - .../libs/codemirror/5.0.0/CONTRIBUTING.md | 76 - shared/html/libs/codemirror/5.0.0/README.md | 12 - .../codemirror/5.0.0/addon/dialog/dialog.css | 32 - .../codemirror/5.0.0/addon/dialog/dialog.js | 155 - .../codemirror/5.0.0/addon/merge/merge.css | 112 - .../codemirror/5.0.0/addon/merge/merge.js | 735 - .../codemirror/5.0.0/addon/mode/loadmode.js | 64 - .../codemirror/5.0.0/addon/mode/multiplex.js | 118 - .../5.0.0/addon/mode/multiplex_test.js | 33 - .../codemirror/5.0.0/addon/mode/overlay.js | 85 - .../codemirror/5.0.0/addon/mode/simple.js | 213 - .../5.0.0/addon/runmode/colorize.js | 40 - .../5.0.0/addon/runmode/runmode-standalone.js | 157 - .../codemirror/5.0.0/addon/runmode/runmode.js | 72 - .../5.0.0/addon/runmode/runmode.node.js | 120 - .../5.0.0/addon/scroll/annotatescrollbar.js | 100 - .../5.0.0/addon/scroll/scrollpastend.js | 46 - .../5.0.0/addon/scroll/simplescrollbars.css | 66 - .../5.0.0/addon/scroll/simplescrollbars.js | 141 - .../5.0.0/addon/selection/active-line.js | 71 - .../5.0.0/addon/selection/mark-selection.js | 118 - .../addon/selection/selection-pointer.js | 98 - .../libs/codemirror/5.0.0/addon/tern/tern.css | 86 - .../libs/codemirror/5.0.0/addon/tern/tern.js | 697 - .../codemirror/5.0.0/addon/tern/worker.js | 44 - .../codemirror/5.0.0/addon/wrap/hardwrap.js | 139 - shared/html/libs/codemirror/5.0.0/bower.json | 16 - .../codemirror/5.0.0/demo/activeline.html | 78 - .../codemirror/5.0.0/demo/anywordhint.html | 79 - .../html/libs/codemirror/5.0.0/demo/bidi.html | 74 - .../libs/codemirror/5.0.0/demo/btree.html | 85 - .../libs/codemirror/5.0.0/demo/buffers.html | 109 - .../codemirror/5.0.0/demo/changemode.html | 58 - .../codemirror/5.0.0/demo/closebrackets.html | 52 - .../libs/codemirror/5.0.0/demo/closetag.html | 41 - .../libs/codemirror/5.0.0/demo/complete.html | 79 - .../libs/codemirror/5.0.0/demo/emacs.html | 75 - .../libs/codemirror/5.0.0/demo/folding.html | 95 - .../codemirror/5.0.0/demo/fullscreen.html | 83 - .../libs/codemirror/5.0.0/demo/hardwrap.html | 72 - .../codemirror/5.0.0/demo/html5complete.html | 56 - .../codemirror/5.0.0/demo/indentwrap.html | 59 - .../html/libs/codemirror/5.0.0/demo/lint.html | 171 - .../libs/codemirror/5.0.0/demo/loadmode.html | 72 - .../libs/codemirror/5.0.0/demo/marker.html | 52 - .../codemirror/5.0.0/demo/markselection.html | 52 - .../5.0.0/demo/matchhighlighter.html | 47 - .../libs/codemirror/5.0.0/demo/matchtags.html | 48 - .../libs/codemirror/5.0.0/demo/merge.html | 122 - .../libs/codemirror/5.0.0/demo/multiplex.html | 75 - .../libs/codemirror/5.0.0/demo/mustache.html | 69 - .../libs/codemirror/5.0.0/demo/panel.html | 64 - .../codemirror/5.0.0/demo/placeholder.html | 45 - .../libs/codemirror/5.0.0/demo/preview.html | 87 - .../libs/codemirror/5.0.0/demo/requirejs.html | 52 - .../libs/codemirror/5.0.0/demo/resize.html | 51 - .../libs/codemirror/5.0.0/demo/rulers.html | 49 - .../libs/codemirror/5.0.0/demo/runmode.html | 62 - .../libs/codemirror/5.0.0/demo/search.html | 93 - .../codemirror/5.0.0/demo/simplemode.html | 186 - .../5.0.0/demo/simplescrollbars.html | 82 - .../5.0.0/demo/spanaffectswrapping_shim.html | 85 - .../libs/codemirror/5.0.0/demo/sublime.html | 76 - .../html/libs/codemirror/5.0.0/demo/tern.html | 133 - .../libs/codemirror/5.0.0/demo/theme.html | 132 - .../codemirror/5.0.0/demo/trailingspace.html | 48 - .../codemirror/5.0.0/demo/variableheight.html | 67 - .../html/libs/codemirror/5.0.0/demo/vim.html | 99 - .../codemirror/5.0.0/demo/visibletabs.html | 62 - .../libs/codemirror/5.0.0/demo/widget.html | 85 - .../codemirror/5.0.0/demo/xmlcomplete.html | 119 - .../codemirror/5.0.0/doc/activebookmark.js | 57 - .../libs/codemirror/5.0.0/doc/compress.html | 309 - .../html/libs/codemirror/5.0.0/doc/docs.css | 271 - .../libs/codemirror/5.0.0/doc/internals.html | 503 - .../html/libs/codemirror/5.0.0/doc/logo.png | Bin 9310 -> 0 bytes .../html/libs/codemirror/5.0.0/doc/logo.svg | 181 - .../libs/codemirror/5.0.0/doc/manual.html | 3119 - .../libs/codemirror/5.0.0/doc/realworld.html | 172 - .../libs/codemirror/5.0.0/doc/releases.html | 1049 - .../libs/codemirror/5.0.0/doc/reporting.html | 61 - .../codemirror/5.0.0/doc/upgrade_v2.2.html | 96 - .../libs/codemirror/5.0.0/doc/upgrade_v3.html | 230 - .../libs/codemirror/5.0.0/doc/upgrade_v4.html | 144 - .../libs/codemirror/5.0.0/doc/yinyang.png | Bin 4633 -> 0 bytes shared/html/libs/codemirror/5.0.0/index.html | 196 - .../libs/codemirror/5.0.0/keymap/emacs.js | 412 - .../libs/codemirror/5.0.0/keymap/sublime.js | 540 - .../html/libs/codemirror/5.0.0/keymap/vim.js | 4959 -- .../libs/codemirror/5.0.0/mode/apl/apl.js | 175 - .../libs/codemirror/5.0.0/mode/apl/index.html | 72 - .../5.0.0/mode/asterisk/asterisk.js | 198 - .../codemirror/5.0.0/mode/asterisk/index.html | 154 - .../libs/codemirror/5.0.0/mode/clike/clike.js | 493 - .../codemirror/5.0.0/mode/clike/index.html | 251 - .../codemirror/5.0.0/mode/clike/scala.html | 767 - .../codemirror/5.0.0/mode/clojure/clojure.js | 243 - .../codemirror/5.0.0/mode/clojure/index.html | 88 - .../libs/codemirror/5.0.0/mode/cobol/cobol.js | 255 - .../codemirror/5.0.0/mode/cobol/index.html | 210 - .../5.0.0/mode/coffeescript/coffeescript.js | 369 - .../5.0.0/mode/coffeescript/index.html | 740 - .../5.0.0/mode/commonlisp/commonlisp.js | 122 - .../5.0.0/mode/commonlisp/index.html | 177 - .../libs/codemirror/5.0.0/mode/css/index.html | 75 - .../libs/codemirror/5.0.0/mode/css/less.html | 152 - .../codemirror/5.0.0/mode/css/less_test.js | 51 - .../libs/codemirror/5.0.0/mode/css/scss.html | 157 - .../codemirror/5.0.0/mode/css/scss_test.js | 110 - .../libs/codemirror/5.0.0/mode/css/test.js | 195 - .../codemirror/5.0.0/mode/cypher/cypher.js | 146 - .../codemirror/5.0.0/mode/cypher/index.html | 63 - shared/html/libs/codemirror/5.0.0/mode/d/d.js | 218 - .../libs/codemirror/5.0.0/mode/d/index.html | 273 - .../libs/codemirror/5.0.0/mode/dart/dart.js | 50 - .../codemirror/5.0.0/mode/dart/index.html | 71 - .../libs/codemirror/5.0.0/mode/diff/diff.js | 47 - .../codemirror/5.0.0/mode/diff/index.html | 117 - .../codemirror/5.0.0/mode/django/django.js | 67 - .../codemirror/5.0.0/mode/django/index.html | 63 - .../5.0.0/mode/dockerfile/dockerfile.js | 76 - .../5.0.0/mode/dockerfile/index.html | 73 - .../libs/codemirror/5.0.0/mode/dtd/dtd.js | 142 - .../libs/codemirror/5.0.0/mode/dtd/index.html | 89 - .../libs/codemirror/5.0.0/mode/dylan/dylan.js | 299 - .../codemirror/5.0.0/mode/dylan/index.html | 407 - .../libs/codemirror/5.0.0/mode/ebnf/ebnf.js | 195 - .../codemirror/5.0.0/mode/ebnf/index.html | 102 - .../libs/codemirror/5.0.0/mode/ecl/ecl.js | 207 - .../libs/codemirror/5.0.0/mode/ecl/index.html | 52 - .../codemirror/5.0.0/mode/eiffel/eiffel.js | 162 - .../codemirror/5.0.0/mode/eiffel/index.html | 429 - .../codemirror/5.0.0/mode/erlang/erlang.js | 622 - .../codemirror/5.0.0/mode/erlang/index.html | 76 - .../libs/codemirror/5.0.0/mode/forth/forth.js | 180 - .../codemirror/5.0.0/mode/forth/index.html | 75 - .../codemirror/5.0.0/mode/fortran/fortran.js | 188 - .../codemirror/5.0.0/mode/fortran/index.html | 81 - .../libs/codemirror/5.0.0/mode/gas/gas.js | 345 - .../libs/codemirror/5.0.0/mode/gas/index.html | 68 - .../libs/codemirror/5.0.0/mode/gfm/gfm.js | 123 - .../libs/codemirror/5.0.0/mode/gfm/index.html | 93 - .../libs/codemirror/5.0.0/mode/gfm/test.js | 213 - .../codemirror/5.0.0/mode/gherkin/gherkin.js | 178 - .../codemirror/5.0.0/mode/gherkin/index.html | 48 - .../html/libs/codemirror/5.0.0/mode/go/go.js | 185 - .../libs/codemirror/5.0.0/mode/go/index.html | 85 - .../codemirror/5.0.0/mode/groovy/groovy.js | 226 - .../codemirror/5.0.0/mode/groovy/index.html | 84 - .../libs/codemirror/5.0.0/mode/haml/haml.js | 159 - .../codemirror/5.0.0/mode/haml/index.html | 79 - .../libs/codemirror/5.0.0/mode/haml/test.js | 97 - .../codemirror/5.0.0/mode/haskell/haskell.js | 267 - .../codemirror/5.0.0/mode/haskell/index.html | 73 - .../libs/codemirror/5.0.0/mode/haxe/haxe.js | 518 - .../codemirror/5.0.0/mode/haxe/index.html | 124 - .../5.0.0/mode/htmlembedded/htmlembedded.js | 86 - .../5.0.0/mode/htmlembedded/index.html | 58 - .../5.0.0/mode/htmlmixed/htmlmixed.js | 121 - .../5.0.0/mode/htmlmixed/index.html | 89 - .../libs/codemirror/5.0.0/mode/http/http.js | 113 - .../codemirror/5.0.0/mode/http/index.html | 45 - .../libs/codemirror/5.0.0/mode/idl/idl.js | 290 - .../libs/codemirror/5.0.0/mode/idl/index.html | 64 - .../libs/codemirror/5.0.0/mode/index.html | 134 - .../codemirror/5.0.0/mode/jade/index.html | 70 - .../libs/codemirror/5.0.0/mode/jade/jade.js | 590 - .../5.0.0/mode/javascript/index.html | 114 - .../5.0.0/mode/javascript/javascript.js | 692 - .../5.0.0/mode/javascript/json-ld.html | 72 - .../codemirror/5.0.0/mode/javascript/test.js | 200 - .../5.0.0/mode/javascript/typescript.html | 61 - .../codemirror/5.0.0/mode/jinja2/index.html | 54 - .../codemirror/5.0.0/mode/jinja2/jinja2.js | 142 - .../codemirror/5.0.0/mode/julia/index.html | 195 - .../libs/codemirror/5.0.0/mode/julia/julia.js | 301 - .../codemirror/5.0.0/mode/kotlin/index.html | 89 - .../codemirror/5.0.0/mode/kotlin/kotlin.js | 280 - .../5.0.0/mode/livescript/index.html | 459 - .../5.0.0/mode/livescript/livescript.js | 280 - .../libs/codemirror/5.0.0/mode/lua/index.html | 85 - .../libs/codemirror/5.0.0/mode/lua/lua.js | 159 - .../codemirror/5.0.0/mode/markdown/index.html | 359 - .../5.0.0/mode/markdown/markdown.js | 765 - .../codemirror/5.0.0/mode/markdown/test.js | 754 - .../html/libs/codemirror/5.0.0/mode/meta.js | 177 - .../codemirror/5.0.0/mode/mirc/index.html | 160 - .../libs/codemirror/5.0.0/mode/mirc/mirc.js | 193 - .../codemirror/5.0.0/mode/mllike/index.html | 179 - .../codemirror/5.0.0/mode/mllike/mllike.js | 205 - .../codemirror/5.0.0/mode/modelica/index.html | 67 - .../5.0.0/mode/modelica/modelica.js | 245 - .../codemirror/5.0.0/mode/nginx/index.html | 181 - .../libs/codemirror/5.0.0/mode/nginx/nginx.js | 178 - .../codemirror/5.0.0/mode/ntriples/index.html | 45 - .../5.0.0/mode/ntriples/ntriples.js | 186 - .../codemirror/5.0.0/mode/octave/index.html | 83 - .../codemirror/5.0.0/mode/octave/octave.js | 135 - .../codemirror/5.0.0/mode/pascal/index.html | 61 - .../codemirror/5.0.0/mode/pascal/pascal.js | 109 - .../codemirror/5.0.0/mode/pegjs/index.html | 66 - .../libs/codemirror/5.0.0/mode/pegjs/pegjs.js | 114 - .../codemirror/5.0.0/mode/perl/index.html | 75 - .../libs/codemirror/5.0.0/mode/perl/perl.js | 837 - .../libs/codemirror/5.0.0/mode/php/index.html | 64 - .../libs/codemirror/5.0.0/mode/php/php.js | 226 - .../libs/codemirror/5.0.0/mode/php/test.js | 154 - .../libs/codemirror/5.0.0/mode/pig/index.html | 55 - .../libs/codemirror/5.0.0/mode/pig/pig.js | 188 - .../5.0.0/mode/properties/index.html | 53 - .../5.0.0/mode/properties/properties.js | 78 - .../codemirror/5.0.0/mode/puppet/index.html | 121 - .../codemirror/5.0.0/mode/puppet/puppet.js | 220 - .../codemirror/5.0.0/mode/python/index.html | 198 - .../codemirror/5.0.0/mode/python/python.js | 359 - .../libs/codemirror/5.0.0/mode/q/index.html | 144 - shared/html/libs/codemirror/5.0.0/mode/q/q.js | 139 - .../libs/codemirror/5.0.0/mode/r/index.html | 85 - shared/html/libs/codemirror/5.0.0/mode/r/r.js | 162 - .../5.0.0/mode/rpm/changes/index.html | 66 - .../libs/codemirror/5.0.0/mode/rpm/index.html | 149 - .../libs/codemirror/5.0.0/mode/rpm/rpm.js | 101 - .../libs/codemirror/5.0.0/mode/rst/index.html | 535 - .../libs/codemirror/5.0.0/mode/rst/rst.js | 557 - .../codemirror/5.0.0/mode/ruby/index.html | 183 - .../libs/codemirror/5.0.0/mode/ruby/ruby.js | 285 - .../libs/codemirror/5.0.0/mode/ruby/test.js | 14 - .../codemirror/5.0.0/mode/rust/index.html | 60 - .../libs/codemirror/5.0.0/mode/rust/rust.js | 451 - .../codemirror/5.0.0/mode/sass/index.html | 66 - .../libs/codemirror/5.0.0/mode/sass/sass.js | 414 - .../codemirror/5.0.0/mode/scheme/index.html | 77 - .../codemirror/5.0.0/mode/scheme/scheme.js | 248 - .../codemirror/5.0.0/mode/shell/index.html | 66 - .../libs/codemirror/5.0.0/mode/shell/shell.js | 139 - .../libs/codemirror/5.0.0/mode/shell/test.js | 58 - .../codemirror/5.0.0/mode/sieve/index.html | 93 - .../libs/codemirror/5.0.0/mode/sieve/sieve.js | 193 - .../codemirror/5.0.0/mode/slim/index.html | 96 - .../libs/codemirror/5.0.0/mode/slim/slim.js | 575 - .../libs/codemirror/5.0.0/mode/slim/test.js | 96 - .../5.0.0/mode/smalltalk/index.html | 68 - .../5.0.0/mode/smalltalk/smalltalk.js | 168 - .../codemirror/5.0.0/mode/smarty/index.html | 136 - .../codemirror/5.0.0/mode/smarty/smarty.js | 221 - .../5.0.0/mode/smartymixed/index.html | 114 - .../5.0.0/mode/smartymixed/smartymixed.js | 197 - .../codemirror/5.0.0/mode/solr/index.html | 57 - .../libs/codemirror/5.0.0/mode/solr/solr.js | 104 - .../libs/codemirror/5.0.0/mode/soy/index.html | 68 - .../libs/codemirror/5.0.0/mode/soy/soy.js | 198 - .../codemirror/5.0.0/mode/sparql/index.html | 61 - .../codemirror/5.0.0/mode/sparql/sparql.js | 174 - .../5.0.0/mode/spreadsheet/index.html | 42 - .../5.0.0/mode/spreadsheet/spreadsheet.js | 109 - .../libs/codemirror/5.0.0/mode/sql/index.html | 84 - .../libs/codemirror/5.0.0/mode/sql/sql.js | 391 - .../codemirror/5.0.0/mode/stex/index.html | 110 - .../libs/codemirror/5.0.0/mode/stex/stex.js | 251 - .../libs/codemirror/5.0.0/mode/stex/test.js | 123 - .../codemirror/5.0.0/mode/stylus/index.html | 104 - .../codemirror/5.0.0/mode/stylus/stylus.js | 444 - .../libs/codemirror/5.0.0/mode/tcl/index.html | 142 - .../libs/codemirror/5.0.0/mode/tcl/tcl.js | 147 - .../codemirror/5.0.0/mode/textile/index.html | 191 - .../codemirror/5.0.0/mode/textile/test.js | 417 - .../codemirror/5.0.0/mode/textile/textile.js | 469 - .../5.0.0/mode/tiddlywiki/index.html | 154 - .../5.0.0/mode/tiddlywiki/tiddlywiki.css | 14 - .../5.0.0/mode/tiddlywiki/tiddlywiki.js | 369 - .../codemirror/5.0.0/mode/tiki/index.html | 95 - .../libs/codemirror/5.0.0/mode/tiki/tiki.css | 26 - .../libs/codemirror/5.0.0/mode/tiki/tiki.js | 323 - .../codemirror/5.0.0/mode/toml/index.html | 73 - .../libs/codemirror/5.0.0/mode/toml/toml.js | 88 - .../codemirror/5.0.0/mode/tornado/index.html | 63 - .../codemirror/5.0.0/mode/tornado/tornado.js | 68 - .../codemirror/5.0.0/mode/turtle/index.html | 50 - .../codemirror/5.0.0/mode/turtle/turtle.js | 162 - .../libs/codemirror/5.0.0/mode/vb/index.html | 102 - .../html/libs/codemirror/5.0.0/mode/vb/vb.js | 274 - .../codemirror/5.0.0/mode/vbscript/index.html | 55 - .../5.0.0/mode/vbscript/vbscript.js | 350 - .../codemirror/5.0.0/mode/velocity/index.html | 118 - .../5.0.0/mode/velocity/velocity.js | 201 - .../codemirror/5.0.0/mode/verilog/index.html | 120 - .../codemirror/5.0.0/mode/verilog/test.js | 273 - .../codemirror/5.0.0/mode/verilog/verilog.js | 537 - .../libs/codemirror/5.0.0/mode/xml/index.html | 57 - .../libs/codemirror/5.0.0/mode/xml/test.js | 51 - .../libs/codemirror/5.0.0/mode/xml/xml.js | 384 - .../codemirror/5.0.0/mode/xquery/index.html | 210 - .../libs/codemirror/5.0.0/mode/xquery/test.js | 67 - .../codemirror/5.0.0/mode/xquery/xquery.js | 447 - .../codemirror/5.0.0/mode/yaml/index.html | 80 - .../libs/codemirror/5.0.0/mode/yaml/yaml.js | 117 - .../libs/codemirror/5.0.0/mode/z80/index.html | 52 - .../libs/codemirror/5.0.0/mode/z80/z80.js | 100 - .../html/libs/codemirror/5.0.0/package.json | 21 - .../codemirror/5.0.0/test/comment_test.js | 100 - .../libs/codemirror/5.0.0/test/doc_test.js | 371 - .../html/libs/codemirror/5.0.0/test/driver.js | 138 - .../libs/codemirror/5.0.0/test/emacs_test.js | 141 - .../libs/codemirror/5.0.0/test/index.html | 240 - .../html/libs/codemirror/5.0.0/test/lint.js | 11 - .../libs/codemirror/5.0.0/test/mode_test.css | 23 - .../libs/codemirror/5.0.0/test/mode_test.js | 192 - .../libs/codemirror/5.0.0/test/multi_test.js | 285 - .../codemirror/5.0.0/test/phantom_driver.js | 31 - shared/html/libs/codemirror/5.0.0/test/run.js | 31 - .../libs/codemirror/5.0.0/test/scroll_test.js | 105 - .../libs/codemirror/5.0.0/test/search_test.js | 62 - .../codemirror/5.0.0/test/sql-hint-test.js | 170 - .../codemirror/5.0.0/test/sublime_test.js | 303 - .../html/libs/codemirror/5.0.0/test/test.js | 2112 - .../libs/codemirror/5.0.0/test/vim_test.js | 3773 -- .../libs/codemirror/5.0.0/theme/3024-day.css | 40 - .../codemirror/5.0.0/theme/3024-night.css | 39 - .../5.0.0/theme/ambiance-mobile.css | 5 - .../libs/codemirror/5.0.0/theme/ambiance.css | 75 - .../codemirror/5.0.0/theme/base16-dark.css | 38 - .../codemirror/5.0.0/theme/base16-light.css | 38 - .../codemirror/5.0.0/theme/blackboard.css | 32 - .../libs/codemirror/5.0.0/theme/cobalt.css | 25 - .../codemirror/5.0.0/theme/colorforth.css | 33 - .../libs/codemirror/5.0.0/theme/eclipse.css | 23 - .../libs/codemirror/5.0.0/theme/elegant.css | 13 - .../codemirror/5.0.0/theme/erlang-dark.css | 34 - .../codemirror/5.0.0/theme/lesser-dark.css | 47 - .../html/libs/codemirror/5.0.0/theme/mbo.css | 37 - .../libs/codemirror/5.0.0/theme/mdn-like.css | 46 - .../libs/codemirror/5.0.0/theme/midnight.css | 47 - .../libs/codemirror/5.0.0/theme/monokai.css | 33 - .../html/libs/codemirror/5.0.0/theme/neo.css | 43 - .../libs/codemirror/5.0.0/theme/night.css | 28 - .../codemirror/5.0.0/theme/paraiso-dark.css | 38 - .../codemirror/5.0.0/theme/paraiso-light.css | 38 - .../codemirror/5.0.0/theme/pastel-on-dark.css | 53 - .../libs/codemirror/5.0.0/theme/rubyblue.css | 25 - .../libs/codemirror/5.0.0/theme/solarized.css | 165 - .../codemirror/5.0.0/theme/the-matrix.css | 30 - .../5.0.0/theme/tomorrow-night-bright.css | 35 - .../5.0.0/theme/tomorrow-night-eighties.css | 38 - .../libs/codemirror/5.0.0/theme/twilight.css | 32 - .../codemirror/5.0.0/theme/vibrant-ink.css | 34 - .../libs/codemirror/5.0.0/theme/xq-dark.css | 53 - .../libs/codemirror/5.0.0/theme/xq-light.css | 43 - .../libs/codemirror/5.0.0/theme/zenburn.css | 37 - .../libs/winjs/1.0/js/en-us/base.strings.js | 63 - .../libs/winjs/1.0/js/en-us/ui.strings.js | 300 - shared/html/libs/winjs/2.0/js/base.js | 17047 ------ .../libs/winjs/2.0/js/en-us/base.strings.js | 63 - .../libs/winjs/2.0/js/en-us/ui.strings.js | 530 - shared/html/libs/winjs/2.0/js/ui.js | 49895 ---------------- shared/html/reader.html | 4 +- 378 files changed, 72 insertions(+), 135793 deletions(-) create mode 100644 FindWinJS.ps1 create mode 100644 Used Libraries/codemirror.7z create mode 100644 Used Libraries/readme.txt rename shared/html/libs/winjs/3.0.7z => Used Libraries/winjs.7z (68%) delete mode 100644 shared/Settings.Assets/150x150Logo.scale-100_contrast-black.png delete mode 100644 shared/Settings.Assets/150x150Logo.scale-100_contrast-white.png delete mode 100644 shared/Settings.Assets/150x150Logo.scale-140_contrast-black.png delete mode 100644 shared/Settings.Assets/150x150Logo.scale-140_contrast-white.png delete mode 100644 shared/Settings.Assets/150x150Logo.scale-180_contrast-black.png delete mode 100644 shared/Settings.Assets/150x150Logo.scale-180_contrast-white.png delete mode 100644 shared/Settings.Assets/150x150Logo.scale-80_contrast-black.png delete mode 100644 shared/Settings.Assets/150x150Logo.scale-80_contrast-white.png delete mode 100644 shared/Settings.Assets/70x70Logo.scale-100_contrast-black.png delete mode 100644 shared/Settings.Assets/70x70Logo.scale-100_contrast-white.png delete mode 100644 shared/Settings.Assets/70x70Logo.scale-140_contrast-black.png delete mode 100644 shared/Settings.Assets/70x70Logo.scale-140_contrast-white.png delete mode 100644 shared/Settings.Assets/70x70Logo.scale-180_contrast-black.png delete mode 100644 shared/Settings.Assets/70x70Logo.scale-180_contrast-white.png delete mode 100644 shared/Settings.Assets/70x70Logo.scale-80_contrast-black.png delete mode 100644 shared/Settings.Assets/70x70Logo.scale-80_contrast-white.png delete mode 100644 shared/html/libs/codemirror/5.0.0/.gitattributes delete mode 100644 shared/html/libs/codemirror/5.0.0/.gitignore delete mode 100644 shared/html/libs/codemirror/5.0.0/.travis.yml delete mode 100644 shared/html/libs/codemirror/5.0.0/CONTRIBUTING.md delete mode 100644 shared/html/libs/codemirror/5.0.0/README.md delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/dialog/dialog.css delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/dialog/dialog.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/merge/merge.css delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/merge/merge.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/mode/loadmode.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/mode/multiplex.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/mode/multiplex_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/mode/overlay.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/mode/simple.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/runmode/colorize.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/runmode/runmode-standalone.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/runmode/runmode.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/runmode/runmode.node.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/scroll/annotatescrollbar.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/scroll/scrollpastend.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/scroll/simplescrollbars.css delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/scroll/simplescrollbars.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/selection/active-line.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/selection/mark-selection.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/selection/selection-pointer.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/tern/tern.css delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/tern/tern.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/tern/worker.js delete mode 100644 shared/html/libs/codemirror/5.0.0/addon/wrap/hardwrap.js delete mode 100644 shared/html/libs/codemirror/5.0.0/bower.json delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/activeline.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/anywordhint.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/bidi.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/btree.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/buffers.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/changemode.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/closebrackets.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/closetag.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/complete.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/emacs.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/folding.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/fullscreen.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/hardwrap.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/html5complete.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/indentwrap.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/lint.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/loadmode.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/marker.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/markselection.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/matchhighlighter.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/matchtags.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/merge.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/multiplex.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/mustache.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/panel.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/placeholder.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/preview.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/requirejs.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/resize.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/rulers.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/runmode.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/search.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/simplemode.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/simplescrollbars.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/spanaffectswrapping_shim.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/sublime.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/tern.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/theme.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/trailingspace.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/variableheight.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/vim.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/visibletabs.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/widget.html delete mode 100644 shared/html/libs/codemirror/5.0.0/demo/xmlcomplete.html delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/activebookmark.js delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/compress.html delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/docs.css delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/internals.html delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/logo.png delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/logo.svg delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/manual.html delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/realworld.html delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/releases.html delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/reporting.html delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/upgrade_v2.2.html delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/upgrade_v3.html delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/upgrade_v4.html delete mode 100644 shared/html/libs/codemirror/5.0.0/doc/yinyang.png delete mode 100644 shared/html/libs/codemirror/5.0.0/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/keymap/emacs.js delete mode 100644 shared/html/libs/codemirror/5.0.0/keymap/sublime.js delete mode 100644 shared/html/libs/codemirror/5.0.0/keymap/vim.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/apl/apl.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/apl/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/asterisk/asterisk.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/asterisk/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/clike/clike.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/clike/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/clike/scala.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/clojure/clojure.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/clojure/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/cobol/cobol.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/cobol/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/coffeescript/coffeescript.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/coffeescript/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/commonlisp/commonlisp.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/commonlisp/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/css/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/css/less.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/css/less_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/css/scss.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/css/scss_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/css/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/cypher/cypher.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/cypher/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/d/d.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/d/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/dart/dart.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/dart/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/diff/diff.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/diff/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/django/django.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/django/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/dockerfile/dockerfile.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/dockerfile/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/dtd/dtd.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/dtd/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/dylan/dylan.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/dylan/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/ebnf/ebnf.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/ebnf/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/ecl/ecl.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/ecl/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/eiffel/eiffel.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/eiffel/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/erlang/erlang.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/erlang/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/forth/forth.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/forth/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/fortran/fortran.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/fortran/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/gas/gas.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/gas/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/gfm/gfm.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/gfm/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/gfm/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/gherkin/gherkin.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/gherkin/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/go/go.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/go/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/groovy/groovy.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/groovy/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/haml/haml.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/haml/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/haml/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/haskell/haskell.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/haskell/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/haxe/haxe.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/haxe/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/htmlembedded/htmlembedded.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/htmlembedded/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/htmlmixed/htmlmixed.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/htmlmixed/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/http/http.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/http/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/idl/idl.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/idl/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/jade/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/jade/jade.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/javascript/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/javascript/javascript.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/javascript/json-ld.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/javascript/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/javascript/typescript.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/jinja2/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/jinja2/jinja2.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/julia/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/julia/julia.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/kotlin/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/kotlin/kotlin.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/livescript/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/livescript/livescript.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/lua/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/lua/lua.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/markdown/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/markdown/markdown.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/markdown/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/meta.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/mirc/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/mirc/mirc.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/mllike/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/mllike/mllike.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/modelica/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/modelica/modelica.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/nginx/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/nginx/nginx.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/ntriples/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/ntriples/ntriples.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/octave/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/octave/octave.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/pascal/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/pascal/pascal.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/pegjs/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/pegjs/pegjs.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/perl/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/perl/perl.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/php/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/php/php.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/php/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/pig/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/pig/pig.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/properties/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/properties/properties.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/puppet/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/puppet/puppet.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/python/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/python/python.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/q/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/q/q.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/r/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/r/r.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/rpm/changes/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/rpm/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/rpm/rpm.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/rst/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/rst/rst.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/ruby/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/ruby/ruby.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/ruby/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/rust/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/rust/rust.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/sass/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/sass/sass.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/scheme/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/scheme/scheme.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/shell/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/shell/shell.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/shell/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/sieve/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/sieve/sieve.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/slim/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/slim/slim.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/slim/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/smalltalk/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/smalltalk/smalltalk.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/smarty/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/smarty/smarty.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/smartymixed/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/smartymixed/smartymixed.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/solr/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/solr/solr.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/soy/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/soy/soy.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/sparql/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/sparql/sparql.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/spreadsheet/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/spreadsheet/spreadsheet.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/sql/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/sql/sql.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/stex/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/stex/stex.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/stex/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/stylus/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/stylus/stylus.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/tcl/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/tcl/tcl.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/textile/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/textile/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/textile/textile.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/tiddlywiki.css delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/tiddlywiki.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/tiki/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/tiki/tiki.css delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/tiki/tiki.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/toml/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/toml/toml.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/tornado/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/tornado/tornado.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/turtle/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/turtle/turtle.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/vb/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/vb/vb.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/vbscript/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/vbscript/vbscript.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/velocity/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/velocity/velocity.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/verilog/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/verilog/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/verilog/verilog.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/xml/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/xml/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/xml/xml.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/xquery/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/xquery/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/xquery/xquery.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/yaml/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/yaml/yaml.js delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/z80/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/mode/z80/z80.js delete mode 100644 shared/html/libs/codemirror/5.0.0/package.json delete mode 100644 shared/html/libs/codemirror/5.0.0/test/comment_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/doc_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/driver.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/emacs_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/index.html delete mode 100644 shared/html/libs/codemirror/5.0.0/test/lint.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/mode_test.css delete mode 100644 shared/html/libs/codemirror/5.0.0/test/mode_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/multi_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/phantom_driver.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/run.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/scroll_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/search_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/sql-hint-test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/sublime_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/test/vim_test.js delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/3024-day.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/3024-night.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/ambiance-mobile.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/ambiance.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/base16-dark.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/base16-light.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/blackboard.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/cobalt.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/colorforth.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/eclipse.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/elegant.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/erlang-dark.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/lesser-dark.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/mbo.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/mdn-like.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/midnight.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/monokai.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/neo.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/night.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/paraiso-dark.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/paraiso-light.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/pastel-on-dark.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/rubyblue.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/solarized.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/the-matrix.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/tomorrow-night-bright.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/tomorrow-night-eighties.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/twilight.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/vibrant-ink.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/xq-dark.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/xq-light.css delete mode 100644 shared/html/libs/codemirror/5.0.0/theme/zenburn.css delete mode 100644 shared/html/libs/winjs/1.0/js/en-us/base.strings.js delete mode 100644 shared/html/libs/winjs/1.0/js/en-us/ui.strings.js delete mode 100644 shared/html/libs/winjs/2.0/js/base.js delete mode 100644 shared/html/libs/winjs/2.0/js/en-us/base.strings.js delete mode 100644 shared/html/libs/winjs/2.0/js/en-us/ui.strings.js delete mode 100644 shared/html/libs/winjs/2.0/js/ui.js diff --git a/FindWinJS.ps1 b/FindWinJS.ps1 new file mode 100644 index 0000000..d390607 --- /dev/null +++ b/FindWinJS.ps1 @@ -0,0 +1,66 @@ +<# +.SYNOPSIS + 查找 HTML 文件中引用了 "winjs" 的 link 或 script 标签行。 + +.DESCRIPTION + 递归搜索指定目录下的所有 .html / .htm 文件,输出包含 "winjs" 字符串(不区分大小写) + 的 - - - - - -
-

Active Line Demo

-
- - - -

Styling the current cursor line.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/anywordhint.html b/shared/html/libs/codemirror/5.0.0/demo/anywordhint.html deleted file mode 100644 index 0a7caec..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/anywordhint.html +++ /dev/null @@ -1,79 +0,0 @@ - - -CodeMirror: Any Word Completion Demo - - - - - - - - - - - -
-

Any Word Completion Demo

-
- -

Press ctrl-space to activate autocompletion. The -completion uses -the anyword-hint.js -module, which simply looks at nearby words in the buffer and completes -to those.

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/bidi.html b/shared/html/libs/codemirror/5.0.0/demo/bidi.html deleted file mode 100644 index 6dd73be..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/bidi.html +++ /dev/null @@ -1,74 +0,0 @@ - - -CodeMirror: Bi-directional Text Demo - - - - - - - - - -
-

Bi-directional Text Demo

-
- - - -

Demonstration of bi-directional text support. See - the related - blog post for more background.

- -

Note: There is - a known - bug with cursor motion and mouse clicks in bi-directional lines - that are line wrapped.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/btree.html b/shared/html/libs/codemirror/5.0.0/demo/btree.html deleted file mode 100644 index fc4997f..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/btree.html +++ /dev/null @@ -1,85 +0,0 @@ - - -CodeMirror: B-Tree visualization - - - - - - - - -
-

B-Tree visualization

-
- -
- - - - -

- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/buffers.html b/shared/html/libs/codemirror/5.0.0/demo/buffers.html deleted file mode 100644 index 16ffc7d..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/buffers.html +++ /dev/null @@ -1,109 +0,0 @@ - - -CodeMirror: Multiple Buffer & Split View Demo - - - - - - - - - - -
-

Multiple Buffer & Split View Demo

- - -
-
- Select buffer: -     -
-
-
- Select buffer: -     -
- - - -

Demonstration of - using linked documents - to provide a split view on a document, and - using swapDoc - to use a single editor to display multiple documents.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/changemode.html b/shared/html/libs/codemirror/5.0.0/demo/changemode.html deleted file mode 100644 index 9405932..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/changemode.html +++ /dev/null @@ -1,58 +0,0 @@ - - -CodeMirror: Mode-Changing Demo - - - - - - - - - - -
-

Mode-Changing Demo

-
- -

On changes to the content of the above editor, a (crude) script -tries to auto-detect the language used, and switches the editor to -either JavaScript or Scheme mode based on that.

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/closebrackets.html b/shared/html/libs/codemirror/5.0.0/demo/closebrackets.html deleted file mode 100644 index d702f52..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/closebrackets.html +++ /dev/null @@ -1,52 +0,0 @@ - - -CodeMirror: Closebrackets Demo - - - - - - - - - - -
-

Closebrackets Demo

-
- - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/closetag.html b/shared/html/libs/codemirror/5.0.0/demo/closetag.html deleted file mode 100644 index 79959d2..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/closetag.html +++ /dev/null @@ -1,41 +0,0 @@ - - -CodeMirror: Close-Tag Demo - - - - - - - - - - - - - - -
-

Close-Tag Demo

-
- - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/complete.html b/shared/html/libs/codemirror/5.0.0/demo/complete.html deleted file mode 100644 index cdf49db..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/complete.html +++ /dev/null @@ -1,79 +0,0 @@ - - -CodeMirror: Autocomplete Demo - - - - - - - - - - - - -
-

Autocomplete Demo

-
- -

Press ctrl-space to activate autocompletion. Built -on top of the show-hint -and javascript-hint -addons.

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/emacs.html b/shared/html/libs/codemirror/5.0.0/demo/emacs.html deleted file mode 100644 index c626b8d..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/emacs.html +++ /dev/null @@ -1,75 +0,0 @@ - - -CodeMirror: Emacs bindings demo - - - - - - - - - - - - - - - - -
-

Emacs bindings demo

-
- -

The emacs keybindings are enabled by -including keymap/emacs.js and setting -the keyMap option to "emacs". Because -CodeMirror's internal API is quite different from Emacs, they are only -a loose approximation of actual emacs bindings, though.

- -

Also note that a lot of browsers disallow certain keys from being -captured. For example, Chrome blocks both Ctrl-W and Ctrl-N, with the -result that idiomatic use of Emacs keys will constantly close your tab -or open a new window.

- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/folding.html b/shared/html/libs/codemirror/5.0.0/demo/folding.html deleted file mode 100644 index 81cbf98..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/folding.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - CodeMirror: Code Folding Demo - - - - - - - - - - - - - - - - - - - - - -
-

Code Folding Demo

-
-
JavaScript:
-
-
HTML:
-
-
Markdown:
-
-
- -
- diff --git a/shared/html/libs/codemirror/5.0.0/demo/fullscreen.html b/shared/html/libs/codemirror/5.0.0/demo/fullscreen.html deleted file mode 100644 index 1fbdc48..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/fullscreen.html +++ /dev/null @@ -1,83 +0,0 @@ - - -CodeMirror: Full Screen Editing - - - - - - - - - - - - -
-

Full Screen Editing

-
- - -

Demonstration of - the fullscreen - addon. Press F11 when cursor is in the editor to - toggle full screen editing. Esc can also be used - to exit full screen editing.

-
diff --git a/shared/html/libs/codemirror/5.0.0/demo/hardwrap.html b/shared/html/libs/codemirror/5.0.0/demo/hardwrap.html deleted file mode 100644 index f1a870b..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/hardwrap.html +++ /dev/null @@ -1,72 +0,0 @@ - - -CodeMirror: Hard-wrapping Demo - - - - - - - - - - -
-

Hard-wrapping Demo

-
- -

Demonstration of -the hardwrap addon. -The above editor has its change event hooked up to -the wrapParagraphsInRange method, so that the paragraphs -are reflown as you are typing.

- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/html5complete.html b/shared/html/libs/codemirror/5.0.0/demo/html5complete.html deleted file mode 100644 index 411baae..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/html5complete.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - CodeMirror: HTML completion demo - - - - - - - - - - - - - - - - - - - -
-

HTML completion demo

- -

Shows the XML completer - parameterized with information about the tags in HTML. - Press ctrl-space to activate completion.

- -
- - -
- diff --git a/shared/html/libs/codemirror/5.0.0/demo/indentwrap.html b/shared/html/libs/codemirror/5.0.0/demo/indentwrap.html deleted file mode 100644 index 3d3d0af..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/indentwrap.html +++ /dev/null @@ -1,59 +0,0 @@ - - -CodeMirror: Indented wrapped line demo - - - - - - - - - -
-

Indented wrapped line demo

-
- -

This page uses a hack on top of the "renderLine" - event to make wrapped text line up with the base indentation of - the line.

- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/lint.html b/shared/html/libs/codemirror/5.0.0/demo/lint.html deleted file mode 100644 index 29936a8..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/lint.html +++ /dev/null @@ -1,171 +0,0 @@ - - -CodeMirror: Linter Demo - - - - - - - - - - - - - - - - - - -
-

Linter Demo

- - -

- -

- -

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/loadmode.html b/shared/html/libs/codemirror/5.0.0/demo/loadmode.html deleted file mode 100644 index 809cd90..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/loadmode.html +++ /dev/null @@ -1,72 +0,0 @@ - - -CodeMirror: Lazy Mode Loading Demo - - - - - - - - - - -
-

Lazy Mode Loading Demo

-

Current mode: text/plain

-
-

Filename, mime, or mode name:

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/marker.html b/shared/html/libs/codemirror/5.0.0/demo/marker.html deleted file mode 100644 index 3a8b850..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/marker.html +++ /dev/null @@ -1,52 +0,0 @@ - - -CodeMirror: Breakpoint Demo - - - - - - - - - -
-

Breakpoint Demo

-
- -

Click the line-number gutter to add or remove 'breakpoints'.

- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/markselection.html b/shared/html/libs/codemirror/5.0.0/demo/markselection.html deleted file mode 100644 index d4c8a7a..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/markselection.html +++ /dev/null @@ -1,52 +0,0 @@ - - -CodeMirror: Selection Marking Demo - - - - - - - - - - -
-

Selection Marking Demo

-
- - - -

Simple addon to easily mark (and style) selected text. Docs.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/matchhighlighter.html b/shared/html/libs/codemirror/5.0.0/demo/matchhighlighter.html deleted file mode 100644 index c601090..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/matchhighlighter.html +++ /dev/null @@ -1,47 +0,0 @@ - - -CodeMirror: Match Highlighter Demo - - - - - - - - - - -
-

Match Highlighter Demo

-
- - - -

Search and highlight occurences of the selected text.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/matchtags.html b/shared/html/libs/codemirror/5.0.0/demo/matchtags.html deleted file mode 100644 index 175639a..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/matchtags.html +++ /dev/null @@ -1,48 +0,0 @@ - - -CodeMirror: Tag Matcher Demo - - - - - - - - - - - -
-

Tag Matcher Demo

- - -
- - - -

Put the cursor on or inside a pair of tags to highlight them. - Press Ctrl-J to jump to the tag that matches the one under the - cursor.

-
diff --git a/shared/html/libs/codemirror/5.0.0/demo/merge.html b/shared/html/libs/codemirror/5.0.0/demo/merge.html deleted file mode 100644 index c60e653..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/merge.html +++ /dev/null @@ -1,122 +0,0 @@ - - -CodeMirror: merge view demo - - - - - - - - - - - - - - - -
-

merge view demo

- - -
- -

The merge -addon provides an interface for displaying and merging diffs, -either two-way -or three-way. -The left (or center) pane is editable, and the differences with the -other pane(s) are optionally shown live as you edit -it. In the two-way configuration, there are also options to pad changed -sections to align them, and to collapse unchanged -stretches of text.

- -

This addon depends on -the google-diff-match-patch -library to compute the diffs.

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/multiplex.html b/shared/html/libs/codemirror/5.0.0/demo/multiplex.html deleted file mode 100644 index ca8c80a..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/multiplex.html +++ /dev/null @@ -1,75 +0,0 @@ - - -CodeMirror: Multiplexing Parser Demo - - - - - - - - - - -
-

Multiplexing Parser Demo

-
- - - -

Demonstration of a multiplexing mode, which, at certain - boundary strings, switches to one or more inner modes. The out - (HTML) mode does not get fed the content of the << - >> blocks. See - the manual and - the source for more - information.

- -

- Parsing/Highlighting Tests: - normal, - verbose. -

- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/mustache.html b/shared/html/libs/codemirror/5.0.0/demo/mustache.html deleted file mode 100644 index ae4e6a8..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/mustache.html +++ /dev/null @@ -1,69 +0,0 @@ - - -CodeMirror: Overlay Parser Demo - - - - - - - - - - -
-

Overlay Parser Demo

-
- - - -

Demonstration of a mode that parses HTML, highlighting - the Mustache templating - directives inside of it by using the code - in overlay.js. View - source to see the 15 lines of code needed to accomplish this.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/panel.html b/shared/html/libs/codemirror/5.0.0/demo/panel.html deleted file mode 100644 index 7f4bbef..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/panel.html +++ /dev/null @@ -1,64 +0,0 @@ - - -CodeMirror: Panel Demo - - - - - - - - - - - -
-

Panel Demo

-
- - - -

The panel -addon allows you to display panels above or below an editor. Click the -links in the previous paragraph to add panels to the editor.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/placeholder.html b/shared/html/libs/codemirror/5.0.0/demo/placeholder.html deleted file mode 100644 index 432331a..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/placeholder.html +++ /dev/null @@ -1,45 +0,0 @@ - - -CodeMirror: Placeholder demo - - - - - - - - - -
-

Placeholder demo

-
- -

The placeholder - plug-in adds an option placeholder that can be set to - make text appear in the editor when it is empty and not focused. - If the source textarea has a placeholder attribute, - it will automatically be inherited.

- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/preview.html b/shared/html/libs/codemirror/5.0.0/demo/preview.html deleted file mode 100644 index 19e1530..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/preview.html +++ /dev/null @@ -1,87 +0,0 @@ - - -CodeMirror: HTML5 preview - - - - - - - - - - - - -
-

HTML5 preview

- - - - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/requirejs.html b/shared/html/libs/codemirror/5.0.0/demo/requirejs.html deleted file mode 100644 index f99b779..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/requirejs.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - CodeMirror: HTML completion demo - - - - - - - - - - - - -
-

RequireJS module loading demo

- -

This demo does the same thing as - the HTML5 completion demo, but - loads its dependencies - with Require.js, rather than - explicitly. Press ctrl-space to activate - completion.

- -
- - -
- diff --git a/shared/html/libs/codemirror/5.0.0/demo/resize.html b/shared/html/libs/codemirror/5.0.0/demo/resize.html deleted file mode 100644 index 1c1ef39..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/resize.html +++ /dev/null @@ -1,51 +0,0 @@ - - -CodeMirror: Autoresize Demo - - - - - - - - - -
-

Autoresize Demo

-
- -

By setting an editor's height style -to auto and giving -the viewportMargin -a value of Infinity, CodeMirror can be made to -automatically resize to fit its content.

- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/rulers.html b/shared/html/libs/codemirror/5.0.0/demo/rulers.html deleted file mode 100644 index 2ac4111..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/rulers.html +++ /dev/null @@ -1,49 +0,0 @@ - - -CodeMirror: Ruler Demo - - - - - - - - - -
-

Ruler Demo

- - - -

Demonstration of -the rulers addon, which -displays vertical lines at given column offsets.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/runmode.html b/shared/html/libs/codemirror/5.0.0/demo/runmode.html deleted file mode 100644 index 257f03d..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/runmode.html +++ /dev/null @@ -1,62 +0,0 @@ - - -CodeMirror: Mode Runner Demo - - - - - - - - - -
-

Mode Runner Demo

- - -
- -

-
-    
-
-    

Running a CodeMirror mode outside of the editor. - The CodeMirror.runMode function, defined - in lib/runmode.js takes the following arguments:

- -
-
text (string)
-
The document to run through the highlighter.
-
mode (mode spec)
-
The mode to use (must be loaded as normal).
-
output (function or DOM node)
-
If this is a function, it will be called for each token with - two arguments, the token's text and the token's style class (may - be null for unstyled tokens). If it is a DOM node, - the tokens will be converted to span elements as in - an editor, and inserted into the node - (through innerHTML).
-
- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/search.html b/shared/html/libs/codemirror/5.0.0/demo/search.html deleted file mode 100644 index 04ba7ac..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/search.html +++ /dev/null @@ -1,93 +0,0 @@ - - -CodeMirror: Search/Replace Demo - - - - - - - - - - - - - - - - -
-

Search/Replace Demo

-
- - - -

Demonstration of primitive search/replace functionality. The - keybindings (which can be overridden by custom keymaps) are:

-
-
Ctrl-F / Cmd-F
Start searching
-
Ctrl-G / Cmd-G
Find next
-
Shift-Ctrl-G / Shift-Cmd-G
Find previous
-
Shift-Ctrl-F / Cmd-Option-F
Replace
-
Shift-Ctrl-R / Shift-Cmd-Option-F
Replace all
-
-

Searching is enabled by - including addon/search/search.js - and addon/search/searchcursor.js. - For good-looking input dialogs, you also want to include - addon/dialog/dialog.js - and addon/dialog/dialog.css.

-
diff --git a/shared/html/libs/codemirror/5.0.0/demo/simplemode.html b/shared/html/libs/codemirror/5.0.0/demo/simplemode.html deleted file mode 100644 index 49778ef..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/simplemode.html +++ /dev/null @@ -1,186 +0,0 @@ - - -CodeMirror: Simple Mode Demo - - - - - - - - - - - -
-

Simple Mode Demo

- -

The mode/simple -addon allows CodeMirror modes to be specified using a relatively simple -declarative format. This format is not as powerful as writing code -directly against the mode -interface, but is a lot easier to get started with, and -sufficiently expressive for many simple language modes.

- -

This interface is still in flux. It is unlikely to be scrapped or -overhauled completely, so do start writing code against it, but -details might change as it stabilizes, and you might have to tweak -your code when upgrading.

- -

Simple modes (loosely based on -the Common -JavaScript Syntax Highlighting Specification, which never took -off), are state machines, where each state has a number of rules that -match tokens. A rule describes a type of token that may occur in the -current state, and possibly a transition to another state caused by -that token.

- -

The CodeMirror.defineSimpleMode(name, states) method -takes a mode name and an object that describes the mode's states. The -editor below shows an example of such a mode (and is itself -highlighted by the mode shown in it).

- -
- -

Each state is an array of rules. A rule may have the following properties:

- -
-
regex: string | RegExp
-
The regular expression that matches the token. May be a string - or a regex object. When a regex, the ignoreCase flag - will be taken into account when matching the token. This regex - should only capture groups when the token property is - an array.
-
token: string | null
-
An optional token style. Multiple styles can be specified by - separating them with dots or spaces. When the regex for - this rule captures groups, it must capture all of the - string (since JS provides no way to find out where a group matched), - and this property must hold an array of token styles that has one - style for each matched group.
-
sol: boolean
-
When true, this token will only match at the start of the line. - (The ^ regexp marker doesn't work as you'd expect in - this context because of limitations in JavaScript's RegExp - API.)
-
next: string
-
When a next property is present, the mode will - transfer to the state named by the property when the token is - encountered.
-
push: string
-
Like next, but instead replacing the current state - by the new state, the current state is kept on a stack, and can be - returned to with the pop directive.
-
pop: bool
-
When true, and there is another state on the state stack, will - cause the mode to pop that state off the stack and transition to - it.
-
mode: {spec, end, persistent}
-
Can be used to embed another mode inside a mode. When present, - must hold an object with a spec property that describes - the embedded mode, and an optional end end property - that specifies the regexp that will end the extent of the mode. When - a persistent property is set (and true), the nested - mode's state will be preserved between occurrences of the mode.
-
indent: bool
-
When true, this token changes the indentation to be one unit - more than the current line's indentation.
-
dedent: bool
-
When true, this token will pop one scope off the indentation - stack.
-
dedentIfLineStart: bool
-
If a token has its dedent property set, it will, by - default, cause lines where it appears at the start to be dedented. - Set this property to false to prevent that behavior.
-
- -

The meta property of the states object is special, and -will not be interpreted as a state. Instead, properties set on it will -be set on the mode, which is useful for properties -like lineComment, -which sets the comment style for a mode. The simple mode addon also -recognizes a few such properties:

- -
-
dontIndentStates: array<string>
-
An array of states in which the mode's auto-indentation should - not take effect. Usually used for multi-line comment and string - states.
-
- - - - - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/simplescrollbars.html b/shared/html/libs/codemirror/5.0.0/demo/simplescrollbars.html deleted file mode 100644 index 9d40932..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/simplescrollbars.html +++ /dev/null @@ -1,82 +0,0 @@ - - -CodeMirror: Simple Scrollbar Demo - - - - - - - - - - - - -
-

Simple Scrollbar Demo

-
- -

The simplescrollbars addon defines two -styles of non-native scrollbars: "simple" and "overlay" (click to try), which can be passed to -the scrollbarStyle option. These implement -the scrollbar using DOM elements, allowing more control over -its appearance.

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/spanaffectswrapping_shim.html b/shared/html/libs/codemirror/5.0.0/demo/spanaffectswrapping_shim.html deleted file mode 100644 index 879d99b..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/spanaffectswrapping_shim.html +++ /dev/null @@ -1,85 +0,0 @@ - - -CodeMirror: Automatically derive odd wrapping behavior for your browser - - - - - -
-

Automatically derive odd wrapping behavior for your browser

- - -

This is a hack to automatically derive - a spanAffectsWrapping regexp for a browser. See the - comments above that variable - in lib/codemirror.js - for some more details.

- -
-

-
-    
-  
diff --git a/shared/html/libs/codemirror/5.0.0/demo/sublime.html b/shared/html/libs/codemirror/5.0.0/demo/sublime.html deleted file mode 100644 index b3b5342..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/sublime.html +++ /dev/null @@ -1,76 +0,0 @@ - - -CodeMirror: Sublime Text bindings demo - - - - - - - - - - - - - - - - - - - - - - -
-

Sublime Text bindings demo

- -

The sublime keymap defines many Sublime Text-specific -bindings for CodeMirror. See the code below for an overview.

- -

Enable the keymap by -loading keymap/sublime.js -and setting -the keyMap -option to "sublime".

- -

(A lot of the search functionality is still missing.) - - - -

diff --git a/shared/html/libs/codemirror/5.0.0/demo/tern.html b/shared/html/libs/codemirror/5.0.0/demo/tern.html deleted file mode 100644 index 19135fa..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/tern.html +++ /dev/null @@ -1,133 +0,0 @@ - - -CodeMirror: Tern Demo - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Tern Demo

-

- -

Demonstrates integration of Tern -and CodeMirror. The following keys are bound:

- -
-
Ctrl-Space
Autocomplete
-
Ctrl-O
Find docs for the expression at the cursor
-
Ctrl-I
Find type at cursor
-
Alt-.
Jump to definition (Alt-, to jump back)
-
Ctrl-Q
Rename variable
-
Ctrl-.
Select all occurrences of a variable
-
- -

Documentation is sparse for now. See the top of -the script for a rough API -overview.

- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/theme.html b/shared/html/libs/codemirror/5.0.0/demo/theme.html deleted file mode 100644 index 22b59b7..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/theme.html +++ /dev/null @@ -1,132 +0,0 @@ - - -CodeMirror: Theme Demo - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

Theme Demo

- - -

Select a theme: -

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/trailingspace.html b/shared/html/libs/codemirror/5.0.0/demo/trailingspace.html deleted file mode 100644 index 1992ba3..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/trailingspace.html +++ /dev/null @@ -1,48 +0,0 @@ - - -CodeMirror: Trailing Whitespace Demo - - - - - - - - - -
-

Trailing Whitespace Demo

-
- - - -

Uses -the trailingspace -addon to highlight trailing whitespace.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/variableheight.html b/shared/html/libs/codemirror/5.0.0/demo/variableheight.html deleted file mode 100644 index d499428..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/variableheight.html +++ /dev/null @@ -1,67 +0,0 @@ - - -CodeMirror: Variable Height Demo - - - - - - - - - - -
-

Variable Height Demo

-
- -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/vim.html b/shared/html/libs/codemirror/5.0.0/demo/vim.html deleted file mode 100644 index 6a33a6c..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/vim.html +++ /dev/null @@ -1,99 +0,0 @@ - - -CodeMirror: Vim bindings demo - - - - - - - - - - - - - - -
-

Vim bindings demo

-
-
Key buffer:
- -

The vim keybindings are enabled by -including keymap/vim.js and setting -the vimMode option to true. This will also -automatically change the keyMap option to "vim".

- -

Features

- - - -

Note that while the vim mode tries to emulate the most useful features of -vim as faithfully as possible, it does not strive to become a complete vim -implementation

- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/visibletabs.html b/shared/html/libs/codemirror/5.0.0/demo/visibletabs.html deleted file mode 100644 index 2eec337..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/visibletabs.html +++ /dev/null @@ -1,62 +0,0 @@ - - -CodeMirror: Visible tabs demo - - - - - - - - - -
-

Visible tabs demo

-
- -

Tabs inside the editor are spans with the -class cm-tab, and can be styled.

- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/demo/widget.html b/shared/html/libs/codemirror/5.0.0/demo/widget.html deleted file mode 100644 index da39a92..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/widget.html +++ /dev/null @@ -1,85 +0,0 @@ - - -CodeMirror: Inline Widget Demo - - - - - - - - - - -
-

Inline Widget Demo

- - -
- -

This demo runs JSHint over the code -in the editor (which is the script used on this page), and -inserts line widgets to -display the warnings that JSHint comes up with.

-
diff --git a/shared/html/libs/codemirror/5.0.0/demo/xmlcomplete.html b/shared/html/libs/codemirror/5.0.0/demo/xmlcomplete.html deleted file mode 100644 index bd452e6..0000000 --- a/shared/html/libs/codemirror/5.0.0/demo/xmlcomplete.html +++ /dev/null @@ -1,119 +0,0 @@ - - -CodeMirror: XML Autocomplete Demo - - - - - - - - - - - - -
-

XML Autocomplete Demo

-
- -

Press ctrl-space, or type a '<' character to - activate autocompletion. This demo defines a simple schema that - guides completion. The schema can be customized—see - the manual.

- -

Development of the xml-hint addon was kindly - sponsored - by www.xperiment.mobi.

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/doc/activebookmark.js b/shared/html/libs/codemirror/5.0.0/doc/activebookmark.js deleted file mode 100644 index 407282d..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/activebookmark.js +++ /dev/null @@ -1,57 +0,0 @@ -// Kludge in HTML5 tag recognition in IE8 -document.createElement("section"); -document.createElement("article"); - -(function() { - if (!window.addEventListener) return; - var pending = false, prevVal = null; - - function updateSoon() { - if (!pending) { - pending = true; - setTimeout(update, 250); - } - } - - function update() { - pending = false; - var marks = document.getElementById("nav").getElementsByTagName("a"), found; - for (var i = 0; i < marks.length; ++i) { - var mark = marks[i], m; - if (mark.getAttribute("data-default")) { - if (found == null) found = i; - } else if (m = mark.href.match(/#(.*)/)) { - var ref = document.getElementById(m[1]); - if (ref && ref.getBoundingClientRect().top < 50) - found = i; - } - } - if (found != null && found != prevVal) { - prevVal = found; - var lis = document.getElementById("nav").getElementsByTagName("li"); - for (var i = 0; i < lis.length; ++i) lis[i].className = ""; - for (var i = 0; i < marks.length; ++i) { - if (found == i) { - marks[i].className = "active"; - for (var n = marks[i]; n; n = n.parentNode) - if (n.nodeName == "LI") n.className = "active"; - } else { - marks[i].className = ""; - } - } - } - } - - window.addEventListener("scroll", updateSoon); - window.addEventListener("load", updateSoon); - window.addEventListener("hashchange", function() { - setTimeout(function() { - var hash = document.location.hash, found = null, m; - var marks = document.getElementById("nav").getElementsByTagName("a"); - for (var i = 0; i < marks.length; i++) - if ((m = marks[i].href.match(/(#.*)/)) && m[1] == hash) { found = i; break; } - if (found != null) for (var i = 0; i < marks.length; i++) - marks[i].className = i == found ? "active" : ""; - }, 300); - }); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/doc/compress.html b/shared/html/libs/codemirror/5.0.0/doc/compress.html deleted file mode 100644 index a376c86..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/compress.html +++ /dev/null @@ -1,309 +0,0 @@ - - -CodeMirror: Compression Helper - - - - - - - - -
- -

Script compression helper

- -

To optimize loading CodeMirror, especially when including a - bunch of different modes, it is recommended that you combine and - minify (and preferably also gzip) the scripts. This page makes - those first two steps very easy. Simply select the version and - scripts you need in the form below, and - click Compress to download the minified script - file.

- -
- -

Version:

- - - -

- with UglifyJS -

- -

Custom code to add to the compressed file:

-
- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/doc/docs.css b/shared/html/libs/codemirror/5.0.0/doc/docs.css deleted file mode 100644 index 881d2aa..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/docs.css +++ /dev/null @@ -1,271 +0,0 @@ -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 400; - src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url(//themes.googleusercontent.com/static/fonts/sourcesanspro/v5/ODelI1aHBYDBqgeIAH2zlBM0YzuT7MdOe03otPbuUS0.woff) format('woff'); -} - -body, html { margin: 0; padding: 0; height: 100%; } -section, article { display: block; padding: 0; } - -body { - background: #f8f8f8; - font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; - line-height: 1.5; -} - -p { margin-top: 0; } - -h2, h3, h1 { - font-weight: normal; - margin-bottom: .7em; -} -h1 { font-size: 140%; } -h2 { font-size: 120%; } -h3 { font-size: 110%; } -article > h2:first-child, section:first-child > h2 { margin-top: 0; } - -#nav h1 { - margin-right: 12px; - margin-top: 0; - margin-bottom: 2px; - color: #d30707; - letter-spacing: .5px; -} - -a, a:visited, a:link, .quasilink { - color: #A21313; - text-decoration: none; -} - -em { - padding-right: 2px; -} - -.quasilink { - cursor: pointer; -} - -article { - max-width: 700px; - margin: 0 0 0 160px; - border-left: 2px solid #E30808; - border-right: 1px solid #ddd; - padding: 30px 50px 100px 50px; - background: white; - z-index: 2; - position: relative; - min-height: 100%; - box-sizing: border-box; - -moz-box-sizing: border-box; -} - -#nav { - position: fixed; - padding-top: 30px; - max-height: 100%; - box-sizing: -moz-border-box; - box-sizing: border-box; - overflow-y: auto; - left: 0; right: none; - width: 160px; - text-align: right; - z-index: 1; -} - -@media screen and (min-width: 1000px) { - article { - margin: 0 auto; - } - #nav { - right: 50%; - width: auto; - border-right: 349px solid transparent; - } -} - -#nav ul { - display: block; - margin: 0; padding: 0; - margin-bottom: 32px; -} - -#nav li { - display: block; - margin-bottom: 4px; -} - -#nav li ul { - font-size: 80%; - margin-bottom: 0; - display: none; -} - -#nav li.active ul { - display: block; -} - -#nav li li a { - padding-right: 20px; - display: inline-block; -} - -#nav ul a { - color: black; - padding: 0 7px 1px 11px; -} - -#nav ul a.active, #nav ul a:hover { - border-bottom: 1px solid #E30808; - margin-bottom: -1px; - color: #E30808; -} - -#logo { - border: 0; - margin-right: 12px; - margin-bottom: 25px; -} - -section { - border-top: 1px solid #E30808; - margin: 1.5em 0; -} - -section.first { - border: none; - margin-top: 0; -} - -#demo { - position: relative; -} - -#demolist { - position: absolute; - right: 5px; - top: 5px; - z-index: 25; -} - -.yinyang { - position: absolute; - top: -10px; - left: 0; right: 0; - margin: auto; - display: block; - height: 120px; -} - -.actions { - margin: 1em 0 0; - min-height: 100px; - position: relative; -} - -.actionspicture { - pointer-events: none; - position: absolute; - height: 100px; - top: 0; left: 0; right: 0; -} - -.actionlink { - pointer-events: auto; - font-family: arial; - font-size: 80%; - font-weight: bold; - position: absolute; - top: 0; bottom: 0; - line-height: 1; - height: 1em; - margin: auto; -} - -.actionlink.download { - color: white; - right: 50%; - margin-right: 13px; - text-shadow: -1px 1px 3px #b00, -1px -1px 3px #b00, 1px 0px 3px #b00; -} - -.actionlink.fund { - color: #b00; - left: 50%; - margin-left: 15px; -} - -.actionlink:hover { - text-decoration: underline; -} - -.actionlink a { - color: inherit; -} - -.actionsleft { - float: left; -} - -.actionsright { - float: right; - text-align: right; -} - -@media screen and (max-width: 800px) { - .actions { - padding-top: 120px; - } - .actionsleft, .actionsright { - float: none; - text-align: left; - margin-bottom: 1em; - } -} - -th { - text-decoration: underline; - font-weight: normal; - text-align: left; -} - -#features ul { - list-style: none; - margin: 0 0 1em; - padding: 0 0 0 1.2em; -} - -#features li:before { - content: "-"; - width: 1em; - display: inline-block; - padding: 0; - margin: 0; - margin-left: -1em; -} - -.rel { - margin-bottom: 0; -} -.rel-note { - margin-top: 0; - color: #555; -} - -pre { - padding-left: 15px; - border-left: 2px solid #ddd; -} - -code { - padding: 0 2px; -} - -strong { - text-decoration: underline; - font-weight: normal; -} - -.field { - border: 1px solid #A21313; -} diff --git a/shared/html/libs/codemirror/5.0.0/doc/internals.html b/shared/html/libs/codemirror/5.0.0/doc/internals.html deleted file mode 100644 index e1ed3e9..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/internals.html +++ /dev/null @@ -1,503 +0,0 @@ - - -CodeMirror: Internals - - - - - - - -
- -

(Re-) Implementing A Syntax-Highlighting Editor in JavaScript

- -

- Topic: JavaScript, code editor implementation
- Author: Marijn Haverbeke
- Date: March 2nd 2011 (updated November 13th 2011) -

- -

Caution: this text was written briefly after -version 2 was initially written. It no longer (even including the -update at the bottom) fully represents the current implementation. I'm -leaving it here as a historic document. For more up-to-date -information, look at the entries -tagged cm-internals -on my blog.

- -

This is a followup to -my Brutal Odyssey to the -Dark Side of the DOM Tree story. That one describes the -mind-bending process of implementing (what would become) CodeMirror 1. -This one describes the internals of CodeMirror 2, a complete rewrite -and rethink of the old code base. I wanted to give this piece another -Hunter Thompson copycat subtitle, but somehow that would be out of -place—the process this time around was one of straightforward -engineering, requiring no serious mind-bending whatsoever.

- -

So, what is wrong with CodeMirror 1? I'd estimate, by mailing list -activity and general search-engine presence, that it has been -integrated into about a thousand systems by now. The most prominent -one, since a few weeks, -being Google -code's project hosting. It works, and it's being used widely.

- -

Still, I did not start replacing it because I was bored. CodeMirror -1 was heavily reliant on designMode -or contentEditable (depending on the browser). Neither of -these are well specified (HTML5 tries -to specify -their basics), and, more importantly, they tend to be one of the more -obscure and buggy areas of browser functionality—CodeMirror, by using -this functionality in a non-typical way, was constantly running up -against browser bugs. WebKit wouldn't show an empty line at the end of -the document, and in some releases would suddenly get unbearably slow. -Firefox would show the cursor in the wrong place. Internet Explorer -would insist on linkifying everything that looked like a URL or email -address, a behaviour that can't be turned off. Some bugs I managed to -work around (which was often a frustrating, painful process), others, -such as the Firefox cursor placement, I gave up on, and had to tell -user after user that they were known problems, but not something I -could help.

- -

Also, there is the fact that designMode (which seemed -to be less buggy than contentEditable in Webkit and -Firefox, and was thus used by CodeMirror 1 in those browsers) requires -a frame. Frames are another tricky area. It takes some effort to -prevent getting tripped up by domain restrictions, they don't -initialize synchronously, behave strangely in response to the back -button, and, on several browsers, can't be moved around the DOM -without having them re-initialize. They did provide a very nice way to -namespace the library, though—CodeMirror 1 could freely pollute the -namespace inside the frame.

- -

Finally, working with an editable document means working with -selection in arbitrary DOM structures. Internet Explorer (8 and -before) has an utterly different (and awkward) selection API than all -of the other browsers, and even among the different implementations of -document.selection, details about how exactly a selection -is represented vary quite a bit. Add to that the fact that Opera's -selection support tended to be very buggy until recently, and you can -imagine why CodeMirror 1 contains 700 lines of selection-handling -code.

- -

And that brings us to the main issue with the CodeMirror 1 -code base: The proportion of browser-bug-workarounds to real -application code was getting dangerously high. By building on top of a -few dodgy features, I put the system in a vulnerable position—any -incompatibility and bugginess in these features, I had to paper over -with my own code. Not only did I have to do some serious stunt-work to -get it to work on older browsers (as detailed in the -previous story), things -also kept breaking in newly released versions, requiring me to come up -with new scary hacks in order to keep up. This was starting -to lose its appeal.

- -
-

General Approach

- -

What CodeMirror 2 does is try to sidestep most of the hairy hacks -that came up in version 1. I owe a lot to the -ACE editor for inspiration on how to -approach this.

- -

I absolutely did not want to be completely reliant on key events to -generate my input. Every JavaScript programmer knows that key event -information is horrible and incomplete. Some people (most awesomely -Mihai Bazon with Ymacs) have been able -to build more or less functioning editors by directly reading key -events, but it takes a lot of work (the kind of never-ending, fragile -work I described earlier), and will never be able to properly support -things like multi-keystoke international character -input. [see below for caveat]

- -

So what I do is focus a hidden textarea, and let the browser -believe that the user is typing into that. What we show to the user is -a DOM structure we built to represent his document. If this is updated -quickly enough, and shows some kind of believable cursor, it feels -like a real text-input control.

- -

Another big win is that this DOM representation does not have to -span the whole document. Some CodeMirror 1 users insisted that they -needed to put a 30 thousand line XML document into CodeMirror. Putting -all that into the DOM takes a while, especially since, for some -reason, an editable DOM tree is slower than a normal one on most -browsers. If we have full control over what we show, we must only -ensure that the visible part of the document has been added, and can -do the rest only when needed. (Fortunately, the onscroll -event works almost the same on all browsers, and lends itself well to -displaying things only as they are scrolled into view.)

-
-
-

Input

- -

ACE uses its hidden textarea only as a text input shim, and does -all cursor movement and things like text deletion itself by directly -handling key events. CodeMirror's way is to let the browser do its -thing as much as possible, and not, for example, define its own set of -key bindings. One way to do this would have been to have the whole -document inside the hidden textarea, and after each key event update -the display DOM to reflect what's in that textarea.

- -

That'd be simple, but it is not realistic. For even medium-sized -document the editor would be constantly munging huge strings, and get -terribly slow. What CodeMirror 2 does is put the current selection, -along with an extra line on the top and on the bottom, into the -textarea.

- -

This means that the arrow keys (and their ctrl-variations), home, -end, etcetera, do not have to be handled specially. We just read the -cursor position in the textarea, and update our cursor to match it. -Also, copy and paste work pretty much for free, and people get their -native key bindings, without any special work on my part. For example, -I have emacs key bindings configured for Chrome and Firefox. There is -no way for a script to detect this. [no longer the case]

- -

Of course, since only a small part of the document sits in the -textarea, keys like page up and ctrl-end won't do the right thing. -CodeMirror is catching those events and handling them itself.

-
-
-

Selection

- -

Getting and setting the selection range of a textarea in modern -browsers is trivial—you just use the selectionStart -and selectionEnd properties. On IE you have to do some -insane stuff with temporary ranges and compensating for the fact that -moving the selection by a 'character' will treat \r\n as a single -character, but even there it is possible to build functions that -reliably set and get the selection range.

- -

But consider this typical case: When I'm somewhere in my document, -press shift, and press the up arrow, something gets selected. Then, if -I, still holding shift, press the up arrow again, the top of my -selection is adjusted. The selection remembers where its head -and its anchor are, and moves the head when we shift-move. -This is a generally accepted property of selections, and done right by -every editing component built in the past twenty years.

- -

But not something that the browser selection APIs expose.

- -

Great. So when someone creates an 'upside-down' selection, the next -time CodeMirror has to update the textarea, it'll re-create the -selection as an 'upside-up' selection, with the anchor at the top, and -the next cursor motion will behave in an unexpected way—our second -up-arrow press in the example above will not do anything, since it is -interpreted in exactly the same way as the first.

- -

No problem. We'll just, ehm, detect that the selection is -upside-down (you can tell by the way it was created), and then, when -an upside-down selection is present, and a cursor-moving key is -pressed in combination with shift, we quickly collapse the selection -in the textarea to its start, allow the key to take effect, and then -combine its new head with its old anchor to get the real -selection.

- -

In short, scary hacks could not be avoided entirely in CodeMirror -2.

- -

And, the observant reader might ask, how do you even know that a -key combo is a cursor-moving combo, if you claim you support any -native key bindings? Well, we don't, but we can learn. The editor -keeps a set known cursor-movement combos (initialized to the -predictable defaults), and updates this set when it observes that -pressing a certain key had (only) the effect of moving the cursor. -This, of course, doesn't work if the first time the key is used was -for extending an inverted selection, but it works most of the -time.

-
-
-

Intelligent Updating

- -

One thing that always comes up when you have a complicated internal -state that's reflected in some user-visible external representation -(in this case, the displayed code and the textarea's content) is -keeping the two in sync. The naive way is to just update the display -every time you change your state, but this is not only error prone -(you'll forget), it also easily leads to duplicate work on big, -composite operations. Then you start passing around flags indicating -whether the display should be updated in an attempt to be efficient -again and, well, at that point you might as well give up completely.

- -

I did go down that road, but then switched to a much simpler model: -simply keep track of all the things that have been changed during an -action, and then, only at the end, use this information to update the -user-visible display.

- -

CodeMirror uses a concept of operations, which start by -calling a specific set-up function that clears the state and end by -calling another function that reads this state and does the required -updating. Most event handlers, and all the user-visible methods that -change state are wrapped like this. There's a method -called operation that accepts a function, and returns -another function that wraps the given function as an operation.

- -

It's trivial to extend this (as CodeMirror does) to detect nesting, -and, when an operation is started inside an operation, simply -increment the nesting count, and only do the updating when this count -reaches zero again.

- -

If we have a set of changed ranges and know the currently shown -range, we can (with some awkward code to deal with the fact that -changes can add and remove lines, so we're dealing with a changing -coordinate system) construct a map of the ranges that were left -intact. We can then compare this map with the part of the document -that's currently visible (based on scroll offset and editor height) to -determine whether something needs to be updated.

- -

CodeMirror uses two update algorithms—a full refresh, where it just -discards the whole part of the DOM that contains the edited text and -rebuilds it, and a patch algorithm, where it uses the information -about changed and intact ranges to update only the out-of-date parts -of the DOM. When more than 30 percent (which is the current heuristic, -might change) of the lines need to be updated, the full refresh is -chosen (since it's faster to do than painstakingly finding and -updating all the changed lines), in the other case it does the -patching (so that, if you scroll a line or select another character, -the whole screen doesn't have to be -re-rendered). [the full-refresh -algorithm was dropped, it wasn't really faster than the patching -one]

- -

All updating uses innerHTML rather than direct DOM -manipulation, since that still seems to be by far the fastest way to -build documents. There's a per-line function that combines the -highlighting, marking, and -selection info for that line into a snippet of HTML. The patch updater -uses this to reset individual lines, the refresh updater builds an -HTML chunk for the whole visible document at once, and then uses a -single innerHTML update to do the refresh.

-
-
-

Parsers can be Simple

- -

When I wrote CodeMirror 1, I -thought interruptable -parsers were a hugely scary and complicated thing, and I used a -bunch of heavyweight abstractions to keep this supposed complexity -under control: parsers -were iterators -that consumed input from another iterator, and used funny -closure-resetting tricks to copy and resume themselves.

- -

This made for a rather nice system, in that parsers formed strictly -separate modules, and could be composed in predictable ways. -Unfortunately, it was quite slow (stacking three or four iterators on -top of each other), and extremely intimidating to people not used to a -functional programming style.

- -

With a few small changes, however, we can keep all those -advantages, but simplify the API and make the whole thing less -indirect and inefficient. CodeMirror -2's mode API uses explicit state -objects, and makes the parser/tokenizer a function that simply takes a -state and a character stream abstraction, advances the stream one -token, and returns the way the token should be styled. This state may -be copied, optionally in a mode-defined way, in order to be able to -continue a parse at a given point. Even someone who's never touched a -lambda in his life can understand this approach. Additionally, far -fewer objects are allocated in the course of parsing now.

- -

The biggest speedup comes from the fact that the parsing no longer -has to touch the DOM though. In CodeMirror 1, on an older browser, you -could see the parser work its way through the document, -managing some twenty lines in each 50-millisecond time slice it got. It -was reading its input from the DOM, and updating the DOM as it went -along, which any experienced JavaScript programmer will immediately -spot as a recipe for slowness. In CodeMirror 2, the parser usually -finishes the whole document in a single 100-millisecond time slice—it -manages some 1500 lines during that time on Chrome. All it has to do -is munge strings, so there is no real reason for it to be slow -anymore.

-
-
-

What Gives?

- -

Given all this, what can you expect from CodeMirror 2?

- -
    - -
  • Small. the base library is -some 45k when minified -now, 17k when gzipped. It's smaller than -its own logo.
  • - -
  • Lightweight. CodeMirror 2 initializes very -quickly, and does almost no work when it is not focused. This means -you can treat it almost like a textarea, have multiple instances on a -page without trouble.
  • - -
  • Huge document support. Since highlighting is -really fast, and no DOM structure is being built for non-visible -content, you don't have to worry about locking up your browser when a -user enters a megabyte-sized document.
  • - -
  • Extended API. Some things kept coming up in the -mailing list, such as marking pieces of text or lines, which were -extremely hard to do with CodeMirror 1. The new version has proper -support for these built in.
  • - -
  • Tab support. Tabs inside editable documents were, -for some reason, a no-go. At least six different people announced they -were going to add tab support to CodeMirror 1, none survived (I mean, -none delivered a working version). CodeMirror 2 no longer removes tabs -from your document.
  • - -
  • Sane styling. iframe nodes aren't -really known for respecting document flow. Now that an editor instance -is a plain div element, it is much easier to size it to -fit the surrounding elements. You don't even have to make it scroll if -you do not want to.
  • - -
- -

On the downside, a CodeMirror 2 instance is not a native -editable component. Though it does its best to emulate such a -component as much as possible, there is functionality that browsers -just do not allow us to hook into. Doing select-all from the context -menu, for example, is not currently detected by CodeMirror.

- -

[Updates from November 13th 2011] Recently, I've made -some changes to the codebase that cause some of the text above to no -longer be current. I've left the text intact, but added markers at the -passages that are now inaccurate. The new situation is described -below.

-
-
-

Content Representation

- -

The original implementation of CodeMirror 2 represented the -document as a flat array of line objects. This worked well—splicing -arrays will require the part of the array after the splice to be -moved, but this is basically just a simple memmove of a -bunch of pointers, so it is cheap even for huge documents.

- -

However, I recently added line wrapping and code folding (line -collapsing, basically). Once lines start taking up a non-constant -amount of vertical space, looking up a line by vertical position -(which is needed when someone clicks the document, and to determine -the visible part of the document during scrolling) can only be done -with a linear scan through the whole array, summing up line heights as -you go. Seeing how I've been going out of my way to make big documents -fast, this is not acceptable.

- -

The new representation is based on a B-tree. The leaves of the tree -contain arrays of line objects, with a fixed minimum and maximum size, -and the non-leaf nodes simply hold arrays of child nodes. Each node -stores both the amount of lines that live below them and the vertical -space taken up by these lines. This allows the tree to be indexed both -by line number and by vertical position, and all access has -logarithmic complexity in relation to the document size.

- -

I gave line objects and tree nodes parent pointers, to the node -above them. When a line has to update its height, it can simply walk -these pointers to the top of the tree, adding or subtracting the -difference in height from each node it encounters. The parent pointers -also make it cheaper (in complexity terms, the difference is probably -tiny in normal-sized documents) to find the current line number when -given a line object. In the old approach, the whole document array had -to be searched. Now, we can just walk up the tree and count the sizes -of the nodes coming before us at each level.

- -

I chose B-trees, not regular binary trees, mostly because they -allow for very fast bulk insertions and deletions. When there is a big -change to a document, it typically involves adding, deleting, or -replacing a chunk of subsequent lines. In a regular balanced tree, all -these inserts or deletes would have to be done separately, which could -be really expensive. In a B-tree, to insert a chunk, you just walk -down the tree once to find where it should go, insert them all in one -shot, and then break up the node if needed. This breaking up might -involve breaking up nodes further up, but only requires a single pass -back up the tree. For deletion, I'm somewhat lax in keeping things -balanced—I just collapse nodes into a leaf when their child count goes -below a given number. This means that there are some weird editing -patterns that may result in a seriously unbalanced tree, but even such -an unbalanced tree will perform well, unless you spend a day making -strangely repeating edits to a really big document.

-
-
-

Keymaps

- -

Above, I claimed that directly catching key -events for things like cursor movement is impractical because it -requires some browser-specific kludges. I then proceeded to explain -some awful hacks that were needed to make it -possible for the selection changes to be detected through the -textarea. In fact, the second hack is about as bad as the first.

- -

On top of that, in the presence of user-configurable tab sizes and -collapsed and wrapped lines, lining up cursor movement in the textarea -with what's visible on the screen becomes a nightmare. Thus, I've -decided to move to a model where the textarea's selection is no longer -depended on.

- -

So I moved to a model where all cursor movement is handled by my -own code. This adds support for a goal column, proper interaction of -cursor movement with collapsed lines, and makes it possible for -vertical movement to move through wrapped lines properly, instead of -just treating them like non-wrapped lines.

- -

The key event handlers now translate the key event into a string, -something like Ctrl-Home or Shift-Cmd-R, and -use that string to look up an action to perform. To make keybinding -customizable, this lookup goes through -a table, using a scheme that -allows such tables to be chained together (for example, the default -Mac bindings fall through to a table named 'emacsy', which defines -basic Emacs-style bindings like Ctrl-F, and which is also -used by the custom Emacs bindings).

- -

A new -option extraKeys -allows ad-hoc keybindings to be defined in a much nicer way than what -was possible with the -old onKeyEvent -callback. You simply provide an object mapping key identifiers to -functions, instead of painstakingly looking at raw key events.

- -

Built-in commands map to strings, rather than functions, for -example "goLineUp" is the default action bound to the up -arrow key. This allows new keymaps to refer to them without -duplicating any code. New commands can be defined by assigning to -the CodeMirror.commands object, which maps such commands -to functions.

- -

The hidden textarea now only holds the current selection, with no -extra characters around it. This has a nice advantage: polling for -input becomes much, much faster. If there's a big selection, this text -does not have to be read from the textarea every time—when we poll, -just noticing that something is still selected is enough to tell us -that no new text was typed.

- -

The reason that cheap polling is important is that many browsers do -not fire useful events on IME (input method engine) input, which is -the thing where people inputting a language like Japanese or Chinese -use multiple keystrokes to create a character or sequence of -characters. Most modern browsers fire input when the -composing is finished, but many don't fire anything when the character -is updated during composition. So we poll, whenever the -editor is focused, to provide immediate updates of the display.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/doc/logo.png b/shared/html/libs/codemirror/5.0.0/doc/logo.png deleted file mode 100644 index 9aabda1d709f565bb115fa083cc16b6d52db64cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9310 zcmWk!Wl$VV6g=D|1b25!aEIUyhr7GGTL{5|1$PMU!Gb&FaCaxTyW6*4U2W~w{MehF z_g=s5o{3aZl14)&LC@FTctEwWVDw?~{3&X8ah!PRD9*tQT8757ES=R=O zZIdr2ugtx4l6@a%-%CqPVF44eaQ%2fx0Jpla6f)NKFVjM^Z_h)hKuzjB4sSI@ekEg z@U#NrAp>;|c$0x9hg?WZTdZG(0VD4>#GX6z>|wuiM$CS;G$FUC%`Yu#T3S`2xx9Q% z&L>hk-l%{+T9H<*SA=}sbo%%o@Lho^HR{1J(LU%?j7M6P@vF0Z0pn zRg3c$bb5L^PunUDMRKYs2Bi84p?^h2s-wqmdrz@zp~k4I#jPdj=S+$6^$1(n#c@vV zQV@AYWo0F0iuwG?$(^c;iwoWx)a709!-19&TMi)>)^tO&r)EX+#@$=$u6%0kebYPc zJhdwF-;A+6Nv~cvrd5Mk9vYf~d&?L>K|$|Ad8<9vw25-A3Z(NDgczyq)xxNFX3irt z5&W3H!9k+!9`(QJE||;POE|miR+~Sm6)TtkQ-cj}VANhC(QrgTL%V&q;;Zro-FDY} zLEOj{mjZVGgd>u4m z9zF7e&^@tyDqDe64B@zwmmb{Zn8=9D0EkzmV(u^0Er>Me3Q1W@zsY6$umA0>sVZm? zf(GAr5tO2~04nkJ@wvUbz0JP5-v~N(8$pml|2M|7;cjEJKc2naVlq*V$ErUVu%xCc zfs#1n{*MfE1l}<8>Gn8IRz?OtB`Ikq$e{Y8Acr;iHY83OaqB8@B8#tYMp?M1xTHiN zI7wa+cO)-Jl$p=D%D=t+`FM2=o|c+=mO*=?NKfnSwkBw*RJ8!PBhEop&nIA&$mb;v z`(VuSI$`*;(y|?=VesS!rUgt{Jdt*)`0hZ?G z7usFYr+DK=vmmf4*I#j$aOU?KF(7dFFyg^IqOV_XZ;56L^zPYvdwU(1ez>LJ;p|HN z4VWobRPeX^YQ|=%QMp8X`Hn78u&x4ka1N?5=y}S^Blo>WDpAfA7QE<&X|fPi*P!91 zP1%g!{BoS*|03)2@?Zo#sF~owf;%$sj_3DF)yW$ZALRySHTxJ?p2Ot=fq#BIgX)5|XO;LcR_79G0BHnqmaV{@z-l*0V&*FitQ+$n$GKK~(Sm8!dKL(9qB_GBTi@yf$25rWcs(1P9>X)ru?O`26nlrz=f0 zm@U<-rU~O=l$e1aj>uh@$@ff@7IHbdSS0=;!NwcMhud z53gSK=5Ft3eehCzt=I&`DimK+)jCpbx;}m$z19HbQtn`d)!hQVW?ChL; zbyKo%9MIsH(Q>--r@-OVua@MI!wIa-jBE9Yw#B6Hdl@SfkOB%&hU2fK`1pfgB~cEi z>K7acZUFF41c0jUSTU1(EXAar0TlOu9ixo!E{YZ*$|c}u>+__hBK&*hRIDa8Af}Q; zWDit2MeZN4SZfyUHj}GWt#8A|6Cu@MLU~bqjhe+}#m%DI(CommzwUQ#@%IP8XxgXH zkyN(SV_iLNCzH9TWd7jqj-)r0;Kso}!idX{4~*c?b&}V(1|!o(&NG`&2I&`ADZUIJ|pBJ69gpMjxo{`=IqPIR49;HZJ)o;WIDAx4o8- z1j5nrhNlg>pzELyfsea#kffV~rD%Ax^X=p*GhV+t=9NEE zwGMXJptrZT*>W|aY^89`irs&YC|M#w!f}@{7kC*bUPqjh!Uwy0bsC~_hGjab`^uy} ztltpI_08Dvm(#}fwt2E&myYl$E+P(Q!cUqD3UxVZSM03`xg;(xj3F4~&-sfCMd~A{ zKqcWr3+}cf1UzhoH@&vk(EDzNAZT}ZqK%}mY#-Nj(O&AtR+xan;967_CN{F;l|~|8 zbv4eSqnd;^x`NQ7i^pBJQWXuEPbA(AiyNG_JNvs^k2SQ48Kr?Gew5?MKFwqKY(F(DdQVId#=h;KNtK-Z_T*+|&{hTo_Dmm~TmWj5{v?&Y`#Q-Eb zTz&kT>byP|t@F$QR+V?o4xQ)xp3Ohpq{U`hSM0{j5y}#&wUnJ=k1^XyQfGGV`7zm0 zE56Y;?0&vKmsggnf@JGdGPs5f1=AO!H`mBk5|vl*z}R z*lpQn=>%|W7C2x6OuNW6mFZ4#aq$jO;SZRY@s{oHf#++f@5Odiy7Y#IuOBOL;sdb5rDr#wo^`On0`NwfaORizU;5S`T|a`{+m2KhV!OF2ne zn)5u+*B7c3=iXT%Iyyc+&gM;Z1*+9%ehzt68mX~f`BMd1@9^Uoo+;_u?+Wkg3K|X| zjHx*~QxY;V!iLQ-hH3LW{Wn{t=CjfuRg$i^ESx3gzuNLkZD0E0=BB+uR50L5z2_I@ z0CYH%y42$a@fVdzp$8SB%r$@50Z3+R&bl?>tn~Idgp!Uc6LT~!GE$bg@oDPt9dgA| z)Zx3K0a~`_w(`&$?;ANGV>IlkAOtPLHeJ=_4)Imh6kAU=Ael_$2x%+q9s8$9adapc z@ZR;|^71uWa}qB9aq`j%@do6JI#;g5gO~kkLO@fV9hIo_EwQ|kO+AI6P%VPG$x%=- z@5C!jI64WxmL(<%YY`eDXQg`aZFOF5&|6FJU=Oa3e0$`#p1wY+f@)TXyJT_UFBF@h zm&fbunEXn@wzIX*%ASx7e`1A#zcI}#*00OAaA}0x8_-MYP#IkIi|jhGU7Z~{*Y~X5 z3Bz%wvHe+$Y!UGLy#h-+zuEcix%UM~Ky`&lIGtqNPV4$8-t%@U8wSgDQ_X&PC>YzX z3~E{1JN?fOkI56WeWg6J@KEE%i6B9%?8D(U|25<-TDdbvw=dRGJ=x+Pzw*;ZBPnm%Q1e{g)fvam7XWvnY_ z`y0C)y*qsiC%B2!CtHWE!`L|+|AvSX;yDQyy+nYrR3nwpYQ zJZH@bm2-AR0s{?ADlac$ zkx01)laBkr=%@l^j&DXHo$?;5U6S;#=JU>H{Ll9EfOHzrZG8vU#$Rw({7!P;`l4{N zG@f%v$3a!h-uc>@$S^BZL8p1fpBpb(buJ}6eJJIeClz0mfySxp)sr;X(9p1*+mZQx z!-#)MRuy}>As`~X-m2E~m7g@|Z z=1NnAGf&Ig$rmUc%eOqeCP(*^Mb*c>Os6!yZIt|SaB{C9#pri-&IJgJk7N6HT&Wah z9k2~ZFz|&pG>2etaRG99GsCkF10?k5H=YgX&BM13?U#Rv!fbO-JOx}*c;EOh@qo|r z_Ve35Jynb$;s zfuT&*mrEAvtLK5Y$;_@8VTK)M0G9rk15iwC*`mH_Y zTr=PfTv5ukYR1Rc+8hNU>Mh4i*R!&&r!1IK@N6nQwpM*`S>B?G6*I9&NzcFo9czwO z+kaz5b9qwTtS0c5r3$9l*|Ip zP^-oekWvM_v054$w@z9d+*6_vZd-3KQ%$?{!;VcH9!Kh$%pCUVqFY}MjCIzeeTz#*Hqqwvp81OK z>w5Tar|?+{)Wdf5+Gqw>w8+~-A3=L)=`d4m%3^!p;98rP6--6QoNvdQA%%n&g@t^# zv?^zShDMby`x6Kd;J*Q$ddy?Eu)?a{5OH(kUWM&y!3RQx>x5e!j9k36&nKs)rb*V7 z)*tK&p$qH(8g{oIsgfK-Ay%0yB$zKClk&(7fSgmtC+!^t&zphF<=^r zfXnT$+)%DLg|4o_l^Z!y6#b|*7LCUyC#i}xW~t`$c_3g1#GXpZgxxO^OImgjKMJ^H zmAZ{lZ2Mzgux)N&UT>c(K)z^Lzdzrdn(h5y<8?n!>49^J`K9qU>96{ik|{+vzF)>Z z#*Hte5ISXIWgtS3I$dl)FX)PvKo8v8g{Z+1L5QP@lsBZA%r7c6nV2*yjW2)IH2dD# z<~!6?rt7ymcVe1tTyZeBd7bWLI(1R)b@zOIg1CA1pjg%)K7-GTzPwRW^8`QiMpIqC z#Vxl==J5M0*HfRZ45$P-az3C>LU-ZX`_S*@jr5ER4i3VcFE`rpkes|L)bIQnjfWEVseduN~aJG0f7S$^cFb@LBvA6KZ`~dpI%eGT+_{$sb$t%P3(UDByT#lH|WYvjN*cf z0b`D{*oIX|&b=(W1r zq&JVJ8U?0r+~GQsY#yJAzl%+t2IhB1iR0GGTTlUx9YO?z zAu95t;&6Z;IzQoVSbIa-C^2`YjU#(fc^`)GL!Jug_2mVhllLc(c$sI7RMN53%*;Q0 zuJ>yF_F1QA8YuB;<+S$H+w=aFE1GqWv-6dM6UO1yLjF9Q1{2P1}rE3j*P*0 zIVlSY36*KpkV=K-?D_U7D!(UUVI52t+2xpS%_x^lHTbBJp5JSeUQ@v)0*N}L4*mHE zEvFkP&(fq7i+qxxpM3KNhjh`Db;Og2UM;f0zL5Jv{lsod+@U)^CH#%m&R_y8ta|m2 zYQXBXI=osepS; zW2_+-c5}5$jVv_v1(TM&0^HglgzAQI>w21-jw`3oc#pYtZj@9xB8BCd@u z@Wngwe$o@ezzdf@fR+wc%iNrL0^KVGv%iv?f?{Ib60{b=6IJ>LDz`T#1kV!caeBDQ zuq6u5&^upyC6mKy+de=Tj*`R?) z(kA$|$GF>?bDh)pXFZf_@hSgBP3IFM(Az5wTaX!w1_wuV0ZCD^@G~(H(%;{|8Y@1( z@61ojEV_}wyvM;4Y+aZ3ZZ}I5NCUCswZf24b4epXE?H@-NM zHNT2_@l_*jG#{IUTs~6Q58po2Ea+KWNEtwD{`cLk+VPw^ZgDr9mb2nU0$gU_F$oAF zHTCYOp>Y!<2M2pf0s9NuNtsQvN>3c1!O{9?uBk>E8aep`jd?G0K{BiN&;glP)!{V|1@J_|hJ&i%FZv@t`iu~WCNpYixA@}peMe)$3kJHL zLK-iHvItWVHJ4D#f}vlPOg;AgtJ_9rK&4(=acTBlb{%{z3n-6`y(^8@E*pv&OCoU~ z3wG6*i0|h#`a#7K$5OdY zijMc=q<&g*+<5S+cd<776F!~5CbT=Dqu>?e&lnD! z(G94TE2LprS-{rGMuubO<4ad0;@%55pRTgYx4Dp$|Gzsg{VW=H-K1l*wUSKc0QmqR z$su4@Ia~KBAR8{35!pSMqUt?t(!pb_<Ww zfah;*u-#flq}%R!tb6?#V;`Au<>vt&jL&cYeWmW|TKE5+1eMf}L96O5?Bka@Z1-5M z%sz|(k|&l8L%Z6S@*Yw{bWkRUDO$Cr1DIJ5n>$5UdQq^dlQq%_+?AjMu!Z*UwBlq9 zl*bV7*ek-|+bL)XL9tZwL?~mqanj?w{~O85VyBx`4(h{7=f;Q!d%MLoE?}Y2*Vore zj>FUsVp|cYPD=ceO{DE~)NR5bvBc#M_PsrtVQj#0N$Ep}VdOIkOC=%guEwUbg?=xJ zZ)iu?wW>?Yr3as}M7D&hIz>=JdKt;YuXlUl2B2-aoD+WVMgJya)d}{%IdJ>O&VUZp zu38{fsnhglG_)S*%8!pX6InT`{$|4Vfq$CgNAqLIN-f;nf@I|=qZc!=M4532FAV{$ zN`nVFfH{HE#TnR#sv`E6TM~13zvJVBdXa-Id|maKrVR{MU}&-Px0hmM8!!@SKU+Ch zrB!C_Abonc+*ZgDMGJVV#GJUM$TtIRpd=dS_-4-2BiKwnDn#b5>v&tpX z+AB6&%40nwtEH|!`;R#sFZg_0@pIMA0D>}r1)bRUL!VA1!$C@>_lm3!W%A?-AB&Xm)~uFywT%$n#=8W zSc4QS2PcF5l_!JKZn>6P^~$N%R1aX07$IAdoU(Afnaq1wHX(A^zt&25yg|nd@i)^x zHj23&m@DH#MXhJimqE_F+fQ3gRl1EpTUt>JyWbs29RXB@d2vaxk3JdbvPG)ov0p>@ zk`;cE=mDNSO0@<4=CjTy4Z4oz(F-DN^pc!X`E6C$*dUqLsZ`46@R`5;c8?&~gLSG( z?T#bBLq|kGsSkL%r0a#s!`b1i%B;>GGR;tzg{nk(0iy=v1;-Xa{Z`R*o54ryh)BRaz z5J?M`5b%%LpmMR>W#POLL;o^>KrkEsp9SF0-QH7?$QrD>3h1@?Lt{WyhUvn> z&K{4J$-V9@)oe9ED%EvUmjvdw%!^3)a`!oNO!Dao@JqYcXOdE5 zP~Xs{v8`s31Z?}sq-tuke#*lT#l*Mx?Y7jopM}}thh+oM+9gUPdjWj!@E|D9)8#OZ zV9-*$YhO1(Og11yY8g!l`2PNZbCCNgDjdcb#DR~x&4}1;T(JH-F-s*&5(*#gzyQkF zChYYmC>>VN;NeR5;m7^$ZP7aijQ3U;Ues(tjz~~vo)HYPX+ZQIiu#**o zL!i(O2=(@h-sqdNnYP8gb-?Gx`(yebn_n#fr(qrCD+?ypH)5%_B1HTNeoDv46gar` z<-rTyM`(v@2M>-;KvJP50NSBeP3ojN^&u(7R~!!^O_ISI2^slcx)_YlQCSHxm+$cC zXrbSN@KF#`XZ_8wjuK;H8}<)^djB7KXf{L8ZE{pRp0B#Lpcoq* z)Ltp}I5x)&b@}|y^%qsCX#>M}LqX{=kKOzUY4)T?Lht&pdF>CDJ~wY(Y?2A+HK$%R zeOO_bJ)oH*qsh9;i!$et<0~rJc4Zdx)?nd_0vk>F`S~q*o=!`3MLHo+rTAgpdXm)g z6a}kmYdn(D(kqOcIYiI~B)OzC&F5XjFWsg9IQcOBy-oRgz{&o$WqhRTkk?NFCCr^lDm1lJD@v#Qli~ZnEZ$Xji^p29BteJ3I(;JX2>ye%XjYfT!8qfs zA%}?qr2)g~1wkjqECv7o diff --git a/shared/html/libs/codemirror/5.0.0/doc/logo.svg b/shared/html/libs/codemirror/5.0.0/doc/logo.svg deleted file mode 100644 index 0aa6323..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/logo.svg +++ /dev/null @@ -1,181 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/shared/html/libs/codemirror/5.0.0/doc/manual.html b/shared/html/libs/codemirror/5.0.0/doc/manual.html deleted file mode 100644 index 74a74e2..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/manual.html +++ /dev/null @@ -1,3119 +0,0 @@ - - -CodeMirror: User Manual - - - - - - - - - - - - - - - - -
- -
-

- User manual and reference guide - version 5.0.0 -

- -

CodeMirror is a code-editor component that can be embedded in - Web pages. The core library provides only the editor - component, no accompanying buttons, auto-completion, or other IDE - functionality. It does provide a rich API on top of which such - functionality can be straightforwardly implemented. See - the addons included in the distribution, - and the list - of externally hosted addons, for reusable - implementations of extra features.

- -

CodeMirror works with language-specific modes. Modes are - JavaScript programs that help color (and optionally indent) text - written in a given language. The distribution comes with a number - of modes (see the mode/ - directory), and it isn't hard to write new - ones for other languages.

-
- -
-

Basic Usage

- -

The easiest way to use CodeMirror is to simply load the script - and style sheet found under lib/ in the distribution, - plus a mode script from one of the mode/ directories. - (See the compression helper for an - easy way to combine scripts.) For example:

- -
<script src="lib/codemirror.js"></script>
-<link rel="stylesheet" href="../lib/codemirror.css">
-<script src="mode/javascript/javascript.js"></script>
- -

(Alternatively, use a module loader. More - about that later.)

- -

Having done this, an editor instance can be created like - this:

- -
var myCodeMirror = CodeMirror(document.body);
- -

The editor will be appended to the document body, will start - empty, and will use the mode that we loaded. To have more control - over the new editor, a configuration object can be passed - to CodeMirror as a second - argument:

- -
var myCodeMirror = CodeMirror(document.body, {
-  value: "function myScript(){return 100;}\n",
-  mode:  "javascript"
-});
- -

This will initialize the editor with a piece of code already in - it, and explicitly tell it to use the JavaScript mode (which is - useful when multiple modes are loaded). - See below for a full discussion of the - configuration options that CodeMirror accepts.

- -

In cases where you don't want to append the editor to an - element, and need more control over the way it is inserted, the - first argument to the CodeMirror function can also - be a function that, when given a DOM element, inserts it into the - document somewhere. This could be used to, for example, replace a - textarea with a real editor:

- -
var myCodeMirror = CodeMirror(function(elt) {
-  myTextArea.parentNode.replaceChild(elt, myTextArea);
-}, {value: myTextArea.value});
- -

However, for this use case, which is a common way to use - CodeMirror, the library provides a much more powerful - shortcut:

- -
var myCodeMirror = CodeMirror.fromTextArea(myTextArea);
- -

This will, among other things, ensure that the textarea's value - is updated with the editor's contents when the form (if it is part - of a form) is submitted. See the API - reference for a full description of this method.

- -

Module loaders

- -

The files in the CodeMirror distribution contain shims for - loading them (and their dependencies) in AMD or CommonJS - environments. If the variables exports - and module exist and have type object, CommonJS-style - require will be used. If not, but there is a - function define with an amd property - present, AMD-style (RequireJS) will be used.

- -

It is possible to - use Browserify or similar - tools to statically build modules using CodeMirror. Alternatively, - use RequireJS to dynamically - load dependencies at runtime. Both of these approaches have the - advantage that they don't use the global namespace and can, thus, - do things like load multiple versions of CodeMirror alongside each - other.

- -

Here's a simple example of using RequireJS to load CodeMirror:

- -
require([
-  "cm/lib/codemirror", "cm/mode/htmlmixed/htmlmixed"
-], function(CodeMirror) {
-  CodeMirror.fromTextArea(document.getElementById("code"), {
-    lineNumbers: true,
-    mode: "htmlmixed"
-  });
-});
- -

It will automatically load the modes that the mixed HTML mode - depends on (XML, JavaScript, and CSS).

- -
- -
-

Configuration

- -

Both the CodeMirror - function and its fromTextArea method take as second - (optional) argument an object containing configuration options. - Any option not supplied like this will be taken - from CodeMirror.defaults, an - object containing the default options. You can update this object - to change the defaults on your page.

- -

Options are not checked in any way, so setting bogus option - values is bound to lead to odd errors.

- -

These are the supported options:

- -
-
value: string|CodeMirror.Doc
-
The starting value of the editor. Can be a string, or - a document object.
- -
mode: string|object
-
The mode to use. When not given, this will default to the - first mode that was loaded. It may be a string, which either - simply names the mode or is - a MIME type - associated with the mode. Alternatively, it may be an object - containing configuration options for the mode, with - a name property that names the mode (for - example {name: "javascript", json: true}). The demo - pages for each mode contain information about what configuration - parameters the mode supports. You can ask CodeMirror which modes - and MIME types have been defined by inspecting - the CodeMirror.modes - and CodeMirror.mimeModes objects. The first maps - mode names to their constructors, and the second maps MIME types - to mode specs.
- -
theme: string
-
The theme to style the editor with. You must make sure the - CSS file defining the corresponding .cm-s-[name] - styles is loaded (see - the theme directory in the - distribution). The default is "default", for which - colors are included in codemirror.css. It is - possible to use multiple theming classes at once—for - example "foo bar" will assign both - the cm-s-foo and the cm-s-bar classes - to the editor.
- -
indentUnit: integer
-
How many spaces a block (whatever that means in the edited - language) should be indented. The default is 2.
- -
smartIndent: boolean
-
Whether to use the context-sensitive indentation that the - mode provides (or just indent the same as the line before). - Defaults to true.
- -
tabSize: integer
-
The width of a tab character. Defaults to 4.
- -
indentWithTabs: boolean
-
Whether, when indenting, the first N*tabSize - spaces should be replaced by N tabs. Default is false.
- -
electricChars: boolean
-
Configures whether the editor should re-indent the current - line when a character is typed that might change its proper - indentation (only works if the mode supports indentation). - Default is true.
- -
specialChars: RegExp
-
A regular expression used to determine which characters - should be replaced by a - special placeholder. - Mostly useful for non-printing special characters. The default - is /[\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/.
-
specialCharPlaceholder: function(char) → Element
-
A function that, given a special character identified by - the specialChars - option, produces a DOM node that is used to represent the - character. By default, a red dot () - is shown, with a title tooltip to indicate the character code.
- -
rtlMoveVisually: boolean
-
Determines whether horizontal cursor movement through - right-to-left (Arabic, Hebrew) text is visual (pressing the left - arrow moves the cursor left) or logical (pressing the left arrow - moves to the next lower index in the string, which is visually - right in right-to-left text). The default is false - on Windows, and true on other platforms.
- -
keyMap: string
-
Configures the key map to use. The default - is "default", which is the only key map defined - in codemirror.js itself. Extra key maps are found in - the key map directory. See - the section on key maps for more - information.
- -
extraKeys: object
-
Can be used to specify extra key bindings for the editor, - alongside the ones defined - by keyMap. Should be - either null, or a valid key map value.
- -
lineWrapping: boolean
-
Whether CodeMirror should scroll or wrap for long lines. - Defaults to false (scroll).
- -
lineNumbers: boolean
-
Whether to show line numbers to the left of the editor.
- -
firstLineNumber: integer
-
At which number to start counting lines. Default is 1.
- -
lineNumberFormatter: function(line: integer) → string
-
A function used to format line numbers. The function is - passed the line number, and should return a string that will be - shown in the gutter.
- -
gutters: array<string>
-
Can be used to add extra gutters (beyond or instead of the - line number gutter). Should be an array of CSS class names, each - of which defines a width (and optionally a - background), and which will be used to draw the background of - the gutters. May include - the CodeMirror-linenumbers class, in order to - explicitly set the position of the line number gutter (it will - default to be to the right of all other gutters). These class - names are the keys passed - to setGutterMarker.
- -
fixedGutter: boolean
-
Determines whether the gutter scrolls along with the content - horizontally (false) or whether it stays fixed during horizontal - scrolling (true, the default).
- -
scrollbarStyle: string
-
Chooses a scrollbar implementation. The default - is "native", showing native scrollbars. The core - library also provides the "null" style, which - completely hides the - scrollbars. Addons can - implement additional scrollbar models.
- -
coverGutterNextToScrollbar: boolean
-
When fixedGutter - is on, and there is a horizontal scrollbar, by default the - gutter will be visible to the left of this scrollbar. If this - option is set to true, it will be covered by an element with - class CodeMirror-gutter-filler.
- -
inputStyle: string
-
Selects the way CodeMirror handles input and focus. The core - library defines the "textarea" - and "contenteditable" input models. On mobile - browsers, the default is "contenteditable". On - desktop browsers, the default is "textarea". - Support for IME and screen readers is better in - the "contenteditable" model. The intention is to - make it the default on modern desktop browsers in the - future.
- -
readOnly: boolean|string
-
This disables editing of the editor content by the user. If - the special value "nocursor" is given (instead of - simply true), focusing of the editor is also - disallowed.
- -
showCursorWhenSelecting: boolean
-
Whether the cursor should be drawn when a selection is - active. Defaults to false.
- -
undoDepth: integer
-
The maximum number of undo levels that the editor stores. - Note that this includes selection change events. Defaults to - 200.
- -
historyEventDelay: integer
-
The period of inactivity (in milliseconds) that will cause a - new history event to be started when typing or deleting. - Defaults to 1250.
- -
tabindex: integer
-
The tab - index to assign to the editor. If not given, no tab index - will be assigned.
- -
autofocus: boolean
-
Can be used to make CodeMirror focus itself on - initialization. Defaults to off. - When fromTextArea is - used, and no explicit value is given for this option, it will be - set to true when either the source textarea is focused, or it - has an autofocus attribute and no other element is - focused.
-
- -

Below this a few more specialized, low-level options are - listed. These are only useful in very specific situations, you - might want to skip them the first time you read this manual.

- -
-
dragDrop: boolean
-
Controls whether drag-and-drop is enabled. On by default.
- -
cursorBlinkRate: number
-
Half-period in milliseconds used for cursor blinking. The default blink - rate is 530ms. By setting this to zero, blinking can be disabled. A - negative value hides the cursor entirely.
- -
cursorScrollMargin: number
-
How much extra space to always keep above and below the - cursor when approaching the top or bottom of the visible view in - a scrollable document. Default is 0.
- -
cursorHeight: number
-
Determines the height of the cursor. Default is 1, meaning - it spans the whole height of the line. For some fonts (and by - some tastes) a smaller height (for example 0.85), - which causes the cursor to not reach all the way to the bottom - of the line, looks better
- -
resetSelectionOnContextMenu: boolean
-
Controls whether, when the context menu is opened with a - click outside of the current selection, the cursor is moved to - the point of the click. Defaults to true.
- -
workTime, workDelay: number
-
Highlighting is done by a pseudo background-thread that will - work for workTime milliseconds, and then use - timeout to sleep for workDelay milliseconds. The - defaults are 200 and 300, you can change these options to make - the highlighting more or less aggressive.
- -
pollInterval: number
-
Indicates how quickly CodeMirror should poll its input - textarea for changes (when focused). Most input is captured by - events, but some things, like IME input on some browsers, don't - generate events that allow CodeMirror to properly detect it. - Thus, it polls. Default is 100 milliseconds.
- -
flattenSpans: boolean
-
By default, CodeMirror will combine adjacent tokens into a - single span if they have the same class. This will result in a - simpler DOM tree, and thus perform better. With some kinds of - styling (such as rounded corners), this will change the way the - document looks. You can set this option to false to disable this - behavior.
- -
addModeClass: boolean
-
When enabled (off by default), an extra CSS class will be - added to each token, indicating the - (inner) mode that produced it, prefixed - with "cm-m-". For example, tokens from the XML mode - will get the cm-m-xml class.
- -
maxHighlightLength: number
-
When highlighting long lines, in order to stay responsive, - the editor will give up and simply style the rest of the line as - plain text when it reaches a certain position. The default is - 10 000. You can set this to Infinity to turn off - this behavior.
- -
crudeMeasuringFrom: number
-
When measuring the character positions in long lines, any - line longer than this number (default is 10 000), - when line wrapping - is off, will simply be assumed to consist of - same-sized characters. This means that, on the one hand, - measuring will be inaccurate when characters of varying size, - right-to-left text, markers, or other irregular elements are - present. On the other hand, it means that having such a line - won't freeze the user interface because of the expensiveness of - the measurements.
- -
viewportMargin: integer
-
Specifies the amount of lines that are rendered above and - below the part of the document that's currently scrolled into - view. This affects the amount of updates needed when scrolling, - and the amount of work that such an update does. You should - usually leave it at its default, 10. Can be set - to Infinity to make sure the whole document is - always rendered, and thus the browser's text search works on it. - This will have bad effects on performance of big - documents.
-
-
- -
-

Events

- -

Various CodeMirror-related objects emit events, which allow - client code to react to various situations. Handlers for such - events can be registered with the on - and off methods on the objects - that the event fires on. To fire your own events, - use CodeMirror.signal(target, name, args...), - where target is a non-DOM-node object.

- -

An editor instance fires the following events. - The instance argument always refers to the editor - itself.

- -
-
"change" (instance: CodeMirror, changeObj: object)
-
Fires every time the content of the editor is changed. - The changeObj is a {from, to, text, removed, - origin} object containing information about the changes - that occurred as second argument. from - and to are the positions (in the pre-change - coordinate system) where the change started and ended (for - example, it might be {ch:0, line:18} if the - position is at the beginning of line #19). text is - an array of strings representing the text that replaced the - changed range (split by line). removed is the text - that used to be between from and to, - which is overwritten by this change.
- -
"changes" (instance: CodeMirror, changes: array<object>)
-
Like the "change" - event, but batched per operation, - passing an array containing all the changes that happened in the - operation.
- -
"beforeChange" (instance: CodeMirror, changeObj: object)
-
This event is fired before a change is applied, and its - handler may choose to modify or cancel the change. - The changeObj object - has from, to, and text - properties, as with - the "change" event. It - also has a cancel() method, which can be called to - cancel the change, and, if the change isn't - coming from an undo or redo event, an update(from, to, - text) method, which may be used to modify the change. - Undo or redo changes can't be modified, because they hold some - metainformation for restoring old marked ranges that is only - valid for that specific change. All three arguments - to update are optional, and can be left off to - leave the existing value for that field - intact. Note: you may not do anything from - a "beforeChange" handler that would cause changes - to the document or its visualization. Doing so will, since this - handler is called directly from the bowels of the CodeMirror - implementation, probably cause the editor to become - corrupted.
- -
"cursorActivity" (instance: CodeMirror)
-
Will be fired when the cursor or selection moves, or any - change is made to the editor content.
- -
"keyHandled" (instance: CodeMirror, name: string, event: Event)
-
Fired after a key is handled through a - key map. name is the name of the handled key (for - example "Ctrl-X" or "'q'"), - and event is the DOM keydown - or keypress event.
- -
"inputRead" (instance: CodeMirror, changeObj: object)
-
Fired whenever new input is read from the hidden textarea - (typed or pasted by the user).
- -
"beforeSelectionChange" (instance: CodeMirror, obj: {ranges, update})
-
This event is fired before the selection is moved. Its - handler may inspect the set of selection ranges, present as an - array of {anchor, head} objects in - the ranges property of the obj - argument, and optionally change them by calling - the update method on this object, passing an array - of ranges in the same format. Handlers for this event have the - same restriction - as "beforeChange" - handlers — they should not do anything to directly update the - state of the editor.
- -
"viewportChange" (instance: CodeMirror, from: number, to: number)
-
Fires whenever the view port of - the editor changes (due to scrolling, editing, or any other - factor). The from and to arguments - give the new start and end of the viewport.
- -
"swapDoc" (instance: CodeMirror, oldDoc: Doc)
-
This is signalled when the editor's document is replaced - using the swapDoc - method.
- -
"gutterClick" (instance: CodeMirror, line: integer, gutter: string, clickEvent: Event)
-
Fires when the editor gutter (the line-number area) is - clicked. Will pass the editor instance as first argument, the - (zero-based) number of the line that was clicked as second - argument, the CSS class of the gutter that was clicked as third - argument, and the raw mousedown event object as - fourth argument.
- -
"gutterContextMenu" (instance: CodeMirror, line: integer, gutter: string, contextMenu: Event: Event)
-
Fires when the editor gutter (the line-number area) - receives a contextmenu event. Will pass the editor - instance as first argument, the (zero-based) number of the line - that was clicked as second argument, the CSS class of the - gutter that was clicked as third argument, and the raw - contextmenu mouse event object as fourth argument. - You can preventDefault the event, to signal that - CodeMirror should do no further handling.
- -
"focus" (instance: CodeMirror)
-
Fires whenever the editor is focused.
- -
"blur" (instance: CodeMirror)
-
Fires whenever the editor is unfocused.
- -
"scroll" (instance: CodeMirror)
-
Fires when the editor is scrolled.
- -
"scrollCursorIntoView" (instance: CodeMirror, event: Event)
-
Fires when the editor tries to scroll its cursor into view. - Can be hooked into to take care of additional scrollable - containers around the editor. When the event object has - its preventDefault method called, CodeMirror will - not itself try to scroll the window.
- -
"update" (instance: CodeMirror)
-
Will be fired whenever CodeMirror updates its DOM display.
- -
"renderLine" (instance: CodeMirror, line: LineHandle, element: Element)
-
Fired whenever a line is (re-)rendered to the DOM. Fired - right after the DOM element is built, before it is - added to the document. The handler may mess with the style of - the resulting element, or add event handlers, but - should not try to change the state of the editor.
- -
"mousedown", - "dblclick", "contextmenu", "keydown", "keypress", - "keyup", "dragstart", "dragenter", - "dragover", "drop" - (instance: CodeMirror, event: Event)
-
Fired when CodeMirror is handling a DOM event of this type. - You can preventDefault the event, or give it a - truthy codemirrorIgnore property, to signal that - CodeMirror should do no further handling.
-
- -

Document objects (instances - of CodeMirror.Doc) emit the - following events:

- -
-
"change" (doc: CodeMirror.Doc, changeObj: object)
-
Fired whenever a change occurs to the - document. changeObj has a similar type as the - object passed to the - editor's "change" - event.
- -
"beforeChange" (doc: CodeMirror.Doc, change: object)
-
See the description of the - same event on editor instances.
- -
"cursorActivity" (doc: CodeMirror.Doc)
-
Fired whenever the cursor or selection in this document - changes.
- -
"beforeSelectionChange" (doc: CodeMirror.Doc, selection: {head, anchor})
-
Equivalent to - the event by the same - name as fired on editor instances.
-
- -

Line handles (as returned by, for - example, getLineHandle) - support these events:

- -
-
"delete" ()
-
Will be fired when the line object is deleted. A line object - is associated with the start of the line. Mostly useful - when you need to find out when your gutter - markers on a given line are removed.
-
"change" (line: LineHandle, changeObj: object)
-
Fires when the line's text content is changed in any way - (but the line is not deleted outright). The change - object is similar to the one passed - to change event on the editor - object.
-
- -

Marked range handles (CodeMirror.TextMarker), as returned - by markText - and setBookmark, emit the - following events:

- -
-
"beforeCursorEnter" ()
-
Fired when the cursor enters the marked range. From this - event handler, the editor state may be inspected - but not modified, with the exception that the range on - which the event fires may be cleared.
-
"clear" (from: {line, ch}, to: {line, ch})
-
Fired when the range is cleared, either through cursor - movement in combination - with clearOnEnter - or through a call to its clear() method. Will only - be fired once per handle. Note that deleting the range through - text editing does not fire this event, because an undo action - might bring the range back into existence. from - and to give the part of the document that the range - spanned when it was cleared.
-
"hide" ()
-
Fired when the last part of the marker is removed from the - document by editing operations.
-
"unhide" ()
-
Fired when, after the marker was removed by editing, a undo - operation brought the marker back.
-
- -

Line widgets (CodeMirror.LineWidget), returned - by addLineWidget, fire - these events:

- -
-
"redraw" ()
-
Fired whenever the editor re-adds the widget to the DOM. - This will happen once right after the widget is added (if it is - scrolled into view), and then again whenever it is scrolled out - of view and back in again, or when changes to the editor options - or the line the widget is on require the widget to be - redrawn.
-
-
- -
-

Key Maps

- -

Key maps are ways to associate keys with functionality. A key map - is an object mapping strings that identify the keys to functions - that implement their functionality.

- -

The CodeMirror distributions comes - with Emacs, Vim, - and Sublime Text-style keymaps.

- -

Keys are identified either by name or by character. - The CodeMirror.keyNames object defines names for - common keys and associates them with their key codes. Examples of - names defined here are Enter, F5, - and Q. These can be prefixed - with Shift-, Cmd-, Ctrl-, - and Alt- to specify a modifier. So for - example, Shift-Ctrl-Space would be a valid key - identifier.

- -

Common example: map the Tab key to insert spaces instead of a tab - character.

- -
-editor.setOption("extraKeys", {
-  Tab: function(cm) {
-    var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
-    cm.replaceSelection(spaces);
-  }
-});
- -

Alternatively, a character can be specified directly by - surrounding it in single quotes, for example '$' - or 'q'. Due to limitations in the way browsers fire - key events, these may not be prefixed with modifiers.

- -

Multi-stroke key bindings can be specified - by separating the key names by spaces in the property name, for - example Ctrl-X Ctrl-V. When a map contains - multi-stoke bindings or keys with modifiers that are not specified - in the default order (Shift-Cmd-Ctrl-Alt), you must - call CodeMirror.normalizeKeyMap on it before it can - be used. This function takes a keymap and modifies it to normalize - modifier order and properly recognize multi-stroke bindings. It - will return the keymap itself.

- -

The CodeMirror.keyMap object associates key maps - with names. User code and key map definitions can assign extra - properties to this object. Anywhere where a key map is expected, a - string can be given, which will be looked up in this object. It - also contains the "default" key map holding the - default bindings.

- -

The values of properties in key maps can be either functions of - a single argument (the CodeMirror instance), strings, or - false. Strings refer - to commands, which are described below. If - the property is set to false, CodeMirror leaves - handling of the key up to the browser. A key handler function may - return CodeMirror.Pass to indicate that it has - decided not to handle the key, and other handlers (or the default - behavior) should be given a turn.

- -

Keys mapped to command names that start with the - characters "go" or to functions that have a - truthy motion property (which should be used for - cursor-movement actions) will be fired even when an - extra Shift modifier is present (i.e. "Up": - "goLineUp" matches both up and shift-up). This is used to - easily implement shift-selection.

- -

Key maps can defer to each other by defining - a fallthrough property. This indicates that when a - key is not found in the map itself, one or more other maps should - be searched. It can hold either a single key map or an array of - key maps.

- -

When a key map needs to set something up when it becomes - active, or tear something down when deactivated, it can - contain attach and/or detach properties, - which should hold functions that take the editor instance and the - next or previous keymap. Note that this only works for the - top-level keymap, not for fallthrough - maps or maps added - with extraKeys - or addKeyMap.

-
- -
-

Commands

- -

Commands are parameter-less actions that can be performed on an - editor. Their main use is for key bindings. Commands are defined by - adding properties to the CodeMirror.commands object. - A number of common commands are defined by the library itself, - most of them used by the default key bindings. The value of a - command property must be a function of one argument (an editor - instance).

- -

Some of the commands below are referenced in the default - key map, but not defined by the core library. These are intended to - be defined by user code or addons.

- -

Commands can also be run with - the execCommand - method.

- -
-
selectAllCtrl-A (PC), Cmd-A (Mac)
-
Select the whole content of the editor.
- -
singleSelectionEsc
-
When multiple selections are present, this deselects all but - the primary selection.
- -
killLineCtrl-K (Mac)
-
Emacs-style line killing. Deletes the part of the line after - the cursor. If that consists only of whitespace, the newline at - the end of the line is also deleted.
- -
deleteLineCtrl-D (PC), Cmd-D (Mac)
-
Deletes the whole line under the cursor, including newline at the end.
- -
delLineLeft
-
Delete the part of the line before the cursor.
- -
delWrappedLineLeftCmd-Backspace (Mac)
-
Delete the part of the line from the left side of the visual line the cursor is on to the cursor.
- -
delWrappedLineRightCmd-Delete (Mac)
-
Delete the part of the line from the cursor to the right side of the visual line the cursor is on.
- -
undoCtrl-Z (PC), Cmd-Z (Mac)
-
Undo the last change.
- -
redoCtrl-Y (PC), Shift-Cmd-Z (Mac), Cmd-Y (Mac)
-
Redo the last undone change.
- -
undoSelectionCtrl-U (PC), Cmd-U (Mac)
-
Undo the last change to the selection, or if there are no - selection-only changes at the top of the history, undo the last - change.
- -
redoSelectionAlt-U (PC), Shift-Cmd-U (Mac)
-
Redo the last change to the selection, or the last text change if - no selection changes remain.
- -
goDocStartCtrl-Up (PC), Cmd-Up (Mac), Cmd-Home (Mac)
-
Move the cursor to the start of the document.
- -
goDocEndCtrl-Down (PC), Cmd-End (Mac), Cmd-Down (Mac)
-
Move the cursor to the end of the document.
- -
goLineStartAlt-Left (PC), Ctrl-A (Mac)
-
Move the cursor to the start of the line.
- -
goLineStartSmartHome
-
Move to the start of the text on the line, or if we are - already there, to the actual start of the line (including - whitespace).
- -
goLineEndAlt-Right (PC), Ctrl-E (Mac)
-
Move the cursor to the end of the line.
- -
goLineRightCmd-Right (Mac)
-
Move the cursor to the right side of the visual line it is on.
- -
goLineLeftCmd-Left (Mac)
-
Move the cursor to the left side of the visual line it is on. If - this line is wrapped, that may not be the start of the line.
- -
goLineLeftSmart
-
Move the cursor to the left side of the visual line it is - on. If that takes it to the start of the line, behave - like goLineStartSmart.
- -
goLineUpUp, Ctrl-P (Mac)
-
Move the cursor up one line.
- -
goLineDownDown, Ctrl-N (Mac)
-
Move down one line.
- -
goPageUpPageUp, Shift-Ctrl-V (Mac)
-
Move the cursor up one screen, and scroll up by the same distance.
- -
goPageDownPageDown, Ctrl-V (Mac)
-
Move the cursor down one screen, and scroll down by the same distance.
- -
goCharLeftLeft, Ctrl-B (Mac)
-
Move the cursor one character left, going to the previous line - when hitting the start of line.
- -
goCharRightRight, Ctrl-F (Mac)
-
Move the cursor one character right, going to the next line - when hitting the end of line.
- -
goColumnLeft
-
Move the cursor one character left, but don't cross line boundaries.
- -
goColumnRight
-
Move the cursor one character right, don't cross line boundaries.
- -
goWordLeftAlt-B (Mac)
-
Move the cursor to the start of the previous word.
- -
goWordRightAlt-F (Mac)
-
Move the cursor to the end of the next word.
- -
goGroupLeftCtrl-Left (PC), Alt-Left (Mac)
-
Move to the left of the group before the cursor. A group is - a stretch of word characters, a stretch of punctuation - characters, a newline, or a stretch of more than one - whitespace character.
- -
goGroupRightCtrl-Right (PC), Alt-Right (Mac)
-
Move to the right of the group after the cursor - (see above).
- -
delCharBeforeShift-Backspace, Ctrl-H (Mac)
-
Delete the character before the cursor.
- -
delCharAfterDelete, Ctrl-D (Mac)
-
Delete the character after the cursor.
- -
delWordBeforeAlt-Backspace (Mac)
-
Delete up to the start of the word before the cursor.
- -
delWordAfterAlt-D (Mac)
-
Delete up to the end of the word after the cursor.
- -
delGroupBeforeCtrl-Backspace (PC), Alt-Backspace (Mac)
-
Delete to the left of the group before the cursor.
- -
delGroupAfterCtrl-Delete (PC), Ctrl-Alt-Backspace (Mac), Alt-Delete (Mac)
-
Delete to the start of the group after the cursor.
- -
indentAutoShift-Tab
-
Auto-indent the current line or selection.
- -
indentMoreCtrl-] (PC), Cmd-] (Mac)
-
Indent the current line or selection by one indent unit.
- -
indentLessCtrl-[ (PC), Cmd-[ (Mac)
-
Dedent the current line or selection by one indent unit.
- -
insertTab
-
Insert a tab character at the cursor.
- -
insertSoftTab
-
Insert the amount of spaces that match the width a tab at - the cursor position would have.
- -
defaultTabTab
-
If something is selected, indent it by - one indent unit. If nothing is - selected, insert a tab character.
- -
transposeCharsCtrl-T (Mac)
-
Swap the characters before and after the cursor.
- -
newlineAndIndentEnter
-
Insert a newline and auto-indent the new line.
- -
toggleOverwriteInsert
-
Flip the overwrite flag.
- -
saveCtrl-S (PC), Cmd-S (Mac)
-
Not defined by the core library, only referred to in - key maps. Intended to provide an easy way for user code to define - a save command.
- -
findCtrl-F (PC), Cmd-F (Mac)
-
findNextCtrl-G (PC), Cmd-G (Mac)
-
findPrevShift-Ctrl-G (PC), Shift-Cmd-G (Mac)
-
replaceShift-Ctrl-F (PC), Cmd-Alt-F (Mac)
-
replaceAllShift-Ctrl-R (PC), Shift-Cmd-Alt-F (Mac)
-
Not defined by the core library, but defined in - the search addon (or custom client - addons).
- -
- -
- -
-

Customized Styling

- -

Up to a certain extent, CodeMirror's look can be changed by - modifying style sheet files. The style sheets supplied by modes - simply provide the colors for that mode, and can be adapted in a - very straightforward way. To style the editor itself, it is - possible to alter or override the styles defined - in codemirror.css.

- -

Some care must be taken there, since a lot of the rules in this - file are necessary to have CodeMirror function properly. Adjusting - colors should be safe, of course, and with some care a lot of - other things can be changed as well. The CSS classes defined in - this file serve the following roles:

- -
-
CodeMirror
-
The outer element of the editor. This should be used for the - editor width, height, borders and positioning. Can also be used - to set styles that should hold for everything inside the editor - (such as font and font size), or to set a background. Setting - this class' height style to auto will - make the editor resize to fit its - content (it is recommended to also set - the viewportMargin - option to Infinity when doing this.
- -
CodeMirror-focused
-
Whenever the editor is focused, the top element gets this - class. This is used to hide the cursor and give the selection a - different color when the editor is not focused.
- -
CodeMirror-gutters
-
This is the backdrop for all gutters. Use it to set the - default gutter background color, and optionally add a border on - the right of the gutters.
- -
CodeMirror-linenumbers
-
Use this for giving a background or width to the line number - gutter.
- -
CodeMirror-linenumber
-
Used to style the actual individual line numbers. These - won't be children of the CodeMirror-linenumbers - (plural) element, but rather will be absolutely positioned to - overlay it. Use this to set alignment and text properties for - the line numbers.
- -
CodeMirror-lines
-
The visible lines. This is where you specify vertical - padding for the editor content.
- -
CodeMirror-cursor
-
The cursor is a block element that is absolutely positioned. - You can make it look whichever way you want.
- -
CodeMirror-selected
-
The selection is represented by span elements - with this class.
- -
CodeMirror-matchingbracket, - CodeMirror-nonmatchingbracket
-
These are used to style matched (or unmatched) brackets.
-
- -

If your page's style sheets do funky things to - all div or pre elements (you probably - shouldn't do that), you'll have to define rules to cancel these - effects out again for elements under the CodeMirror - class.

- -

Themes are also simply CSS files, which define colors for - various syntactic elements. See the files in - the theme directory.

-
- -
-

Programming API

- -

A lot of CodeMirror features are only available through its - API. Thus, you need to write code (or - use addons) if you want to expose them to - your users.

- -

Whenever points in the document are represented, the API uses - objects with line and ch properties. - Both are zero-based. CodeMirror makes sure to 'clip' any positions - passed by client code so that they fit inside the document, so you - shouldn't worry too much about sanitizing your coordinates. If you - give ch a value of null, or don't - specify it, it will be replaced with the length of the specified - line.

- -

Methods prefixed with doc. can, unless otherwise - specified, be called both on CodeMirror (editor) - instances and CodeMirror.Doc instances. Methods - prefixed with cm. are only available - on CodeMirror instances.

- -

Constructor

- -

Constructing an editor instance is done with - the CodeMirror(place: Element|fn(Element), - ?option: object) constructor. If the place - argument is a DOM element, the editor will be appended to it. If - it is a function, it will be called, and is expected to place the - editor into the document. options may be an element - mapping option names to values. The options - that it doesn't explicitly specify (or all options, if it is not - passed) will be taken - from CodeMirror.defaults.

- -

Note that the options object passed to the constructor will be - mutated when the instance's options - are changed, so you shouldn't share such - objects between instances.

- -

See CodeMirror.fromTextArea - for another way to construct an editor instance.

- -

Content manipulation methods

- -
-
doc.getValue(?separator: string) → string
-
Get the current editor content. You can pass it an optional - argument to specify the string to be used to separate lines - (defaults to "\n").
-
doc.setValue(content: string)
-
Set the editor content.
- -
doc.getRange(from: {line, ch}, to: {line, ch}, ?separator: string) → string
-
Get the text between the given points in the editor, which - should be {line, ch} objects. An optional third - argument can be given to indicate the line separator string to - use (defaults to "\n").
-
doc.replaceRange(replacement: string, from: {line, ch}, to: {line, ch}, ?origin: string)
-
Replace the part of the document between from - and to with the given string. from - and to must be {line, ch} - objects. to can be left off to simply insert the - string at position from. When origin - is given, it will be passed on - to "change" events, and - its first letter will be used to determine whether this change - can be merged with previous history events, in the way described - for selection origins.
- -
doc.getLine(n: integer) → string
-
Get the content of line n.
- -
doc.lineCount() → integer
-
Get the number of lines in the editor.
-
doc.firstLine() → integer
-
Get the first line of the editor. This will - usually be zero but for linked sub-views, - or documents instantiated with a non-zero - first line, it might return other values.
-
doc.lastLine() → integer
-
Get the last line of the editor. This will - usually be doc.lineCount() - 1, - but for linked sub-views, - it might return other values.
- -
doc.getLineHandle(num: integer) → LineHandle
-
Fetches the line handle for the given line number.
-
doc.getLineNumber(handle: LineHandle) → integer
-
Given a line handle, returns the current position of that - line (or null when it is no longer in the - document).
-
doc.eachLine(f: (line: LineHandle))
-
doc.eachLine(start: integer, end: integer, f: (line: LineHandle))
-
Iterate over the whole document, or if start - and end line numbers are given, the range - from start up to (not including) end, - and call f for each line, passing the line handle. - This is a faster way to visit a range of line handlers than - calling getLineHandle - for each of them. Note that line handles have - a text property containing the line's content (as a - string).
- -
doc.markClean()
-
Set the editor content as 'clean', a flag that it will - retain until it is edited, and which will be set again when such - an edit is undone again. Useful to track whether the content - needs to be saved. This function is deprecated in favor - of changeGeneration, - which allows multiple subsystems to track different notions of - cleanness without interfering.
-
doc.changeGeneration(?closeEvent: boolean) → integer
-
Returns a number that can later be passed - to isClean to test whether - any edits were made (and not undone) in the meantime. - If closeEvent is true, the current history event - will be ‘closed’, meaning it can't be combined with further - changes (rapid typing or deleting events are typically - combined).
-
doc.isClean(?generation: integer) → boolean
-
Returns whether the document is currently clean — not - modified since initialization or the last call - to markClean if no - argument is passed, or since the matching call - to changeGeneration - if a generation value is given.
-
- -

Cursor and selection methods

- -
-
doc.getSelection(?lineSep: string) → string
-
Get the currently selected code. Optionally pass a line - separator to put between the lines in the output. When multiple - selections are present, they are concatenated with instances - of lineSep in between.
-
doc.getSelections(?lineSep: string) → string
-
Returns an array containing a string for each selection, - representing the content of the selections.
- -
doc.replaceSelection(replacement: string, ?select: string)
-
Replace the selection(s) with the given string. By default, - the new selection ends up after the inserted text. The - optional select argument can be used to change - this—passing "around" will cause the new text to be - selected, passing "start" will collapse the - selection to the start of the inserted text.
-
doc.replaceSelections(replacements: array<string>, ?select: string)
-
The length of the given array should be the same as the - number of active selections. Replaces the content of the - selections with the strings in the array. - The select argument works the same as - in replaceSelection.
- -
doc.getCursor(?start: string) → {line, ch}
-
Retrieve one end of the primary - selection. start is a an optional string indicating - which end of the selection to return. It may - be "from", "to", "head" - (the side of the selection that moves when you press - shift+arrow), or "anchor" (the fixed side of the - selection). Omitting the argument is the same as - passing "head". A {line, ch} object - will be returned.
-
doc.listSelections() → array<{anchor, head}>
-
Retrieves a list of all current selections. These will - always be sorted, and never overlap (overlapping selections are - merged). Each object in the array contains anchor - and head properties referring to {line, - ch} objects.
- -
doc.somethingSelected() → boolean
-
Return true if any text is selected.
-
doc.setCursor(pos: {line, ch}|number, ?ch: number, ?options: object)
-
Set the cursor position. You can either pass a - single {line, ch} object, or the line and the - character as two separate parameters. Will replace all - selections with a single, empty selection at the given position. - The supported options are the same as for setSelection.
- -
doc.setSelection(anchor: {line, ch}, ?head: {line, ch}, ?options: object)
-
Set a single selection range. anchor - and head should be {line, ch} - objects. head defaults to anchor when - not given. These options are supported: -
-
scroll: boolean
-
Determines whether the selection head should be scrolled - into view. Defaults to true.
-
origin: string
-
Detemines whether the selection history event may be - merged with the previous one. When an origin starts with the - character +, and the last recorded selection had - the same origin and was similar (close - in time, both - collapsed or both non-collapsed), the new one will replace the - old one. When it starts with *, it will always - replace the previous event (if that had the same origin). - Built-in motion uses the "+move" origin.
-
bias: number
-
Determine the direction into which the selection endpoints - should be adjusted when they fall inside - an atomic range. Can be either -1 - (backward) or 1 (forward). When not given, the bias will be - based on the relative position of the old selection—the editor - will try to move further away from that, to prevent getting - stuck.
-
- -
doc.setSelections(ranges: array<{anchor, head}>, ?primary: integer, ?options: object)
-
Sets a new set of selections. There must be at least one - selection in the given array. When primary is a - number, it determines which selection is the primary one. When - it is not given, the primary index is taken from the previous - selection, or set to the last range if the previous selection - had less ranges than the new one. Supports the same options - as setSelection.
-
doc.addSelection(anchor: {line, ch}, ?head: {line, ch})
-
Adds a new selection to the existing set of selections, and - makes it the primary selection.
- -
doc.extendSelection(from: {line, ch}, ?to: {line, ch}, ?options: object)
-
Similar - to setSelection, but - will, if shift is held or - the extending flag is set, move the - head of the selection while leaving the anchor at its current - place. to is optional, and can be passed to ensure - a region (for example a word or paragraph) will end up selected - (in addition to whatever lies between that region and the - current anchor). When multiple selections are present, all but - the primary selection will be dropped by this method. - Supports the same options as setSelection.
-
doc.extendSelections(heads: array<{line, ch}>, ?options: object)
-
An equivalent - of extendSelection - that acts on all selections at once.
-
doc.extendSelectionsBy(f: function(range: {anchor, head}) → {anchor, head}), ?options: object)
-
Applies the given function to all existing selections, and - calls extendSelections - on the result.
-
doc.setExtending(value: boolean)
-
Sets or clears the 'extending' flag, which acts similar to - the shift key, in that it will cause cursor movement and calls - to extendSelection - to leave the selection anchor in place.
-
doc.getExtending() → boolean
-
Get the value of the 'extending' flag.
- -
cm.hasFocus() → boolean
-
Tells you whether the editor currently has focus.
- -
cm.findPosH(start: {line, ch}, amount: integer, unit: string, visually: boolean) → {line, ch, ?hitSide: boolean}
-
Used to find the target position for horizontal cursor - motion. start is a {line, ch} - object, amount an integer (may be negative), - and unit one of the - string "char", "column", - or "word". Will return a position that is produced - by moving amount times the distance specified - by unit. When visually is true, motion - in right-to-left text will be visual rather than logical. When - the motion was clipped by hitting the end or start of the - document, the returned value will have a hitSide - property set to true.
-
cm.findPosV(start: {line, ch}, amount: integer, unit: string) → {line, ch, ?hitSide: boolean}
-
Similar to findPosH, - but used for vertical motion. unit may - be "line" or "page". The other - arguments and the returned value have the same interpretation as - they have in findPosH.
- -
cm.findWordAt(pos: {line, ch}) → {anchor: {line, ch}, head: {line, ch}}
-
Returns the start and end of the 'word' (the stretch of - letters, whitespace, or punctuation) at the given position.
-
- -

Configuration methods

- -
-
cm.setOption(option: string, value: any)
-
Change the configuration of the editor. option - should the name of an option, - and value should be a valid value for that - option.
-
cm.getOption(option: string) → any
-
Retrieves the current value of the given option for this - editor instance.
- -
cm.addKeyMap(map: object, bottom: boolean)
-
Attach an additional key map to the - editor. This is mostly useful for addons that need to register - some key handlers without trampling on - the extraKeys - option. Maps added in this way have a higher precedence than - the extraKeys - and keyMap options, - and between them, the maps added earlier have a lower precedence - than those added later, unless the bottom argument - was passed, in which case they end up below other key maps added - with this method.
-
cm.removeKeyMap(map: object)
-
Disable a keymap added - with addKeyMap. Either - pass in the key map object itself, or a string, which will be - compared against the name property of the active - key maps.
- -
cm.addOverlay(mode: string|object, ?options: object)
-
Enable a highlighting overlay. This is a stateless mini-mode - that can be used to add extra highlighting. For example, - the search addon uses it to - highlight the term that's currently being - searched. mode can be a mode - spec or a mode object (an object with - a token method). - The options parameter is optional. If given, it - should be an object. Currently, only the opaque - option is recognized. This defaults to off, but can be given to - allow the overlay styling, when not null, to - override the styling of the base mode entirely, instead of the - two being applied together.
-
cm.removeOverlay(mode: string|object)
-
Pass this the exact value passed for the mode - parameter to addOverlay, - or a string that corresponds to the name propery of - that value, to remove an overlay again.
- -
cm.on(type: string, func: (...args))
-
Register an event handler for the given event type (a - string) on the editor instance. There is also - a CodeMirror.on(object, type, func) version - that allows registering of events on any object.
-
cm.off(type: string, func: (...args))
-
Remove an event handler on the editor instance. An - equivalent CodeMirror.off(object, type, - func) also exists.
-
- -

Document management methods

- -

Each editor is associated with an instance - of CodeMirror.Doc, its document. A document - represents the editor content, plus a selection, an undo history, - and a mode. A document can only be - associated with a single editor at a time. You can create new - documents by calling the CodeMirror.Doc(text, mode, - firstLineNumber) constructor. The last two arguments are - optional and can be used to set a mode for the document and make - it start at a line number other than 0, respectively.

- -
-
cm.getDoc() → Doc
-
Retrieve the currently active document from an editor.
-
doc.getEditor() → CodeMirror
-
Retrieve the editor associated with a document. May - return null.
- -
cm.swapDoc(doc: CodeMirror.Doc) → Doc
-
Attach a new document to the editor. Returns the old - document, which is now no longer associated with an editor.
- -
doc.copy(copyHistory: boolean) → Doc
-
Create an identical copy of the given doc. - When copyHistory is true, the history will also be - copied. Can not be called directly on an editor.
- -
doc.linkedDoc(options: object) → Doc
-
Create a new document that's linked to the target document. - Linked documents will stay in sync (changes to one are also - applied to the other) until unlinked. - These are the options that are supported: -
-
sharedHist: boolean
-
When turned on, the linked copy will share an undo - history with the original. Thus, something done in one of - the two can be undone in the other, and vice versa.
-
from: integer
-
to: integer
-
Can be given to make the new document a subview of the - original. Subviews only show a given range of lines. Note - that line coordinates inside the subview will be consistent - with those of the parent, so that for example a subview - starting at line 10 will refer to its first line as line 10, - not 0.
-
mode: string|object
-
By default, the new document inherits the mode of the - parent. This option can be set to - a mode spec to give it a - different mode.
-
-
doc.unlinkDoc(doc: CodeMirror.Doc)
-
Break the link between two documents. After calling this, - changes will no longer propagate between the documents, and, if - they had a shared history, the history will become - separate.
-
doc.iterLinkedDocs(function: (doc: CodeMirror.Doc, sharedHist: boolean))
-
Will call the given function for all documents linked to the - target document. It will be passed two arguments, the linked document - and a boolean indicating whether that document shares history - with the target.
-
- -

History-related methods

- -
-
doc.undo()
-
Undo one edit (if any undo events are stored).
-
doc.redo()
-
Redo one undone edit.
- -
doc.undoSelection()
-
Undo one edit or selection change.
-
doc.redoSelection()
-
Redo one undone edit or selection change.
- -
doc.historySize() → {undo: integer, redo: integer}
-
Returns an object with {undo, redo} properties, - both of which hold integers, indicating the amount of stored - undo and redo operations.
-
doc.clearHistory()
-
Clears the editor's undo history.
-
doc.getHistory() → object
-
Get a (JSON-serializeable) representation of the undo history.
-
doc.setHistory(history: object)
-
Replace the editor's undo history with the one provided, - which must be a value as returned - by getHistory. Note that - this will have entirely undefined results if the editor content - isn't also the same as it was when getHistory was - called.
-
- -

Text-marking methods

- -
-
doc.markText(from: {line, ch}, to: {line, ch}, ?options: object) → TextMarker
-
Can be used to mark a range of text with a specific CSS - class name. from and to should - be {line, ch} objects. The options - parameter is optional. When given, it should be an object that - may contain the following configuration options: -
-
className: string
-
Assigns a CSS class to the marked stretch of text.
-
inclusiveLeft: boolean
-
Determines whether - text inserted on the left of the marker will end up inside - or outside of it.
-
inclusiveRight: boolean
-
Like inclusiveLeft, - but for the right side.
-
atomic: boolean
-
Atomic ranges act as a single unit when cursor movement is - concerned—i.e. it is impossible to place the cursor inside of - them. In atomic ranges, inclusiveLeft - and inclusiveRight have a different meaning—they - will prevent the cursor from being placed respectively - directly before and directly after the range.
-
collapsed: boolean
-
Collapsed ranges do not show up in the display. Setting a - range to be collapsed will automatically make it atomic.
-
clearOnEnter: boolean
-
When enabled, will cause the mark to clear itself whenever - the cursor enters its range. This is mostly useful for - text-replacement widgets that need to 'snap open' when the - user tries to edit them. The - "clear" event - fired on the range handle can be used to be notified when this - happens.
-
clearWhenEmpty: boolean
-
Determines whether the mark is automatically cleared when - it becomes empty. Default is true.
-
replacedWith: Element
-
Use a given node to display this range. Implies both - collapsed and atomic. The given DOM node must be an - inline element (as opposed to a block element).
-
handleMouseEvents: boolean
-
When replacedWith is given, this determines - whether the editor will capture mouse and drag events - occurring in this widget. Default is false—the events will be - left alone for the default browser handler, or specific - handlers on the widget, to capture.
-
readOnly: boolean
-
A read-only span can, as long as it is not cleared, not be - modified except by - calling setValue to reset - the whole document. Note: adding a read-only span - currently clears the undo history of the editor, because - existing undo events being partially nullified by read-only - spans would corrupt the history (in the current - implementation).
-
addToHistory: boolean
-
When set to true (default is false), adding this marker - will create an event in the undo history that can be - individually undone (clearing the marker).
-
startStyle: string
Can be used to specify - an extra CSS class to be applied to the leftmost span that - is part of the marker.
-
endStyle: string
Equivalent - to startStyle, but for the rightmost span.
-
css: string
-
A string of CSS to be applied to the covered text. For example "color: #fe3".
-
title: - string
When given, will give the nodes created - for this span a HTML title attribute with the - given value.
-
shared: boolean
When the - target document is linked to other - documents, you can set shared to true to make the - marker appear in all documents. By default, a marker appears - only in its target document.
-
- The method will return an object that represents the marker - (with constructor CodeMirror.TextMarker), which - exposes three methods: - clear(), to remove the mark, - find(), which returns - a {from, to} object (both holding document - positions), indicating the current position of the marked range, - or undefined if the marker is no longer in the - document, and finally changed(), - which you can call if you've done something that might change - the size of the marker (for example changing the content of - a replacedWith - node), and want to cheaply update the display.
- -
doc.setBookmark(pos: {line, ch}, ?options: object) → TextMarker
-
Inserts a bookmark, a handle that follows the text around it - as it is being edited, at the given position. A bookmark has two - methods find() and clear(). The first - returns the current position of the bookmark, if it is still in - the document, and the second explicitly removes the bookmark. - The options argument is optional. If given, the following - properties are recognized: -
-
widget: Element
Can be used to display a DOM - node at the current location of the bookmark (analogous to - the replacedWith - option to markText).
-
insertLeft: boolean
By default, text typed - when the cursor is on top of the bookmark will end up to the - right of the bookmark. Set this option to true to make it go - to the left instead.
-
shared: boolean
See - the corresponding option - to markText.
-
- -
doc.findMarks(from: {line, ch}, to: {line, ch}) → array<TextMarker>
-
Returns an array of all the bookmarks and marked ranges - found between the given positions.
-
doc.findMarksAt(pos: {line, ch}) → array<TextMarker>
-
Returns an array of all the bookmarks and marked ranges - present at the given position.
-
doc.getAllMarks() → array<TextMarker>
-
Returns an array containing all marked ranges in the document.
-
- -

Widget, gutter, and decoration methods

- -
-
cm.setGutterMarker(line: integer|LineHandle, gutterID: string, value: Element) → LineHandle
-
Sets the gutter marker for the given gutter (identified by - its CSS class, see - the gutters option) - to the given value. Value can be either null, to - clear the marker, or a DOM element, to set it. The DOM element - will be shown in the specified gutter next to the specified - line.
- -
cm.clearGutter(gutterID: string)
-
Remove all gutter markers in - the gutter with the given ID.
- -
doc.addLineClass(line: integer|LineHandle, where: string, class: string) → LineHandle
-
Set a CSS class name for the given line. line - can be a number or a line handle. where determines - to which element this class should be applied, can can be one - of "text" (the text element, which lies in front of - the selection), "background" (a background element - that will be behind the selection), "gutter" (the - line's gutter space), or "wrap" (the wrapper node - that wraps all of the line's elements, including gutter - elements). class should be the name of the class to - apply.
- -
doc.removeLineClass(line: integer|LineHandle, where: string, class: string) → LineHandle
-
Remove a CSS class from a line. line can be a - line handle or number. where should be one - of "text", "background", - or "wrap" - (see addLineClass). class - can be left off to remove all classes for the specified node, or - be a string to remove only a specific class.
- -
cm.lineInfo(line: integer|LineHandle) → object
-
Returns the line number, text content, and marker status of - the given line, which can be either a number or a line handle. - The returned object has the structure {line, handle, text, - gutterMarkers, textClass, bgClass, wrapClass, widgets}, - where gutterMarkers is an object mapping gutter IDs - to marker elements, and widgets is an array - of line widgets attached to this - line, and the various class properties refer to classes added - with addLineClass.
- -
cm.addWidget(pos: {line, ch}, node: Element, scrollIntoView: boolean)
-
Puts node, which should be an absolutely - positioned DOM node, into the editor, positioned right below the - given {line, ch} position. - When scrollIntoView is true, the editor will ensure - that the entire node is visible (if possible). To remove the - widget again, simply use DOM methods (move it somewhere else, or - call removeChild on its parent).
- -
cm.addLineWidget(line: integer|LineHandle, node: Element, ?options: object) → LineWidget
-
Adds a line widget, an element shown below a line, spanning - the whole of the editor's width, and moving the lines below it - downwards. line should be either an integer or a - line handle, and node should be a DOM node, which - will be displayed below the given line. options, - when given, should be an object that configures the behavior of - the widget. The following options are supported (all default to - false): -
-
coverGutter: boolean
-
Whether the widget should cover the gutter.
-
noHScroll: boolean
-
Whether the widget should stay fixed in the face of - horizontal scrolling.
-
above: boolean
-
Causes the widget to be placed above instead of below - the text of the line.
-
handleMouseEvents: boolean
-
Determines whether the editor will capture mouse and - drag events occurring in this widget. Default is false—the - events will be left alone for the default browser handler, - or specific handlers on the widget, to capture.
-
insertAt: integer
-
By default, the widget is added below other widgets for - the line. This option can be used to place it at a different - position (zero for the top, N to put it after the Nth other - widget). Note that this only has effect once, when the - widget is created. -
- Note that the widget node will become a descendant of nodes with - CodeMirror-specific CSS classes, and those classes might in some - cases affect it. This method returns an object that represents - the widget placement. It'll have a line property - pointing at the line handle that it is associated with, and the following methods: -
-
clear()
Removes the widget.
-
changed()
Call - this if you made some change to the widget's DOM node that - might affect its height. It'll force CodeMirror to update - the height of the line that contains the widget.
-
-
-
- -

Sizing, scrolling and positioning methods

- -
-
cm.setSize(width: number|string, height: number|string)
-
Programatically set the size of the editor (overriding the - applicable CSS - rules). width and height - can be either numbers (interpreted as pixels) or CSS units - ("100%", for example). You can - pass null for either of them to indicate that that - dimension should not be changed.
- -
cm.scrollTo(x: number, y: number)
-
Scroll the editor to a given (pixel) position. Both - arguments may be left as null - or undefined to have no effect.
-
cm.getScrollInfo() → {left, top, width, height, clientWidth, clientHeight}
-
Get an {left, top, width, height, clientWidth, - clientHeight} object that represents the current scroll - position, the size of the scrollable area, and the size of the - visible area (minus scrollbars).
-
cm.scrollIntoView(what: {line, ch}|{left, top, right, bottom}|{from, to}|null, ?margin: number)
-
Scrolls the given position into view. what may - be null to scroll the cursor into view, - a {line, ch} position to scroll a character into - view, a {left, top, right, bottom} pixel range (in - editor-local coordinates), or a range {from, to} - containing either two character positions or two pixel squares. - The margin parameter is optional. When given, it - indicates the amount of vertical pixels around the given area - that should be made visible as well.
- -
cm.cursorCoords(where: boolean|{line, ch}, mode: string) → {left, top, bottom}
-
Returns an {left, top, bottom} object - containing the coordinates of the cursor position. - If mode is "local", they will be - relative to the top-left corner of the editable document. If it - is "page" or not given, they are relative to the - top-left corner of the page. If mode - is "window", the coordinates are relative to the - top-left corner of the currently visible (scrolled) - window. where can be a boolean indicating whether - you want the start (true) or the end - (false) of the selection, or, if a {line, - ch} object is given, it specifies the precise position at - which you want to measure.
-
cm.charCoords(pos: {line, ch}, ?mode: string) → {left, right, top, bottom}
-
Returns the position and dimensions of an arbitrary - character. pos should be a {line, ch} - object. This differs from cursorCoords in that - it'll give the size of the whole character, rather than just the - position that the cursor would have when it would sit at that - position.
-
cm.coordsChar(object: {left, top}, ?mode: string) → {line, ch}
-
Given an {left, top} object, returns - the {line, ch} position that corresponds to it. The - optional mode parameter determines relative to what - the coordinates are interpreted. It may - be "window", "page" (the default), - or "local".
-
cm.lineAtHeight(height: number, ?mode: string) → number
-
Computes the line at the given pixel - height. mode can be one of the same strings - that coordsChar - accepts.
-
cm.heightAtLine(line: number, ?mode: string) → number
-
Computes the height of the top of a line, in the coordinate - system specified by mode - (see coordsChar), which - defaults to "page". When a line below the bottom of - the document is specified, the returned value is the bottom of - the last line in the document.
-
cm.defaultTextHeight() → number
-
Returns the line height of the default font for the editor.
-
cm.defaultCharWidth() → number
-
Returns the pixel width of an 'x' in the default font for - the editor. (Note that for non-monospace fonts, this is mostly - useless, and even for monospace fonts, non-ascii characters - might have a different width).
- -
cm.getViewport() → {from: number, to: number}
-
Returns a {from, to} object indicating the - start (inclusive) and end (exclusive) of the currently rendered - part of the document. In big documents, when most content is - scrolled out of view, CodeMirror will only render the visible - part, and a margin around it. See also - the viewportChange - event.
- -
cm.refresh()
-
If your code does something to change the size of the editor - element (window resizes are already listened for), or unhides - it, you should probably follow up by calling this method to - ensure CodeMirror is still looking as intended.
-
- -

Mode, state, and token-related methods

- -

When writing language-aware functionality, it can often be - useful to hook into the knowledge that the CodeMirror language - mode has. See the section on modes for a - more detailed description of how these work.

- -
-
doc.getMode() → object
-
Gets the (outer) mode object for the editor. Note that this - is distinct from getOption("mode"), which gives you - the mode specification, rather than the resolved, instantiated - mode object.
- -
doc.getModeAt(pos: {line, ch}) → object
-
Gets the inner mode at a given position. This will return - the same as getMode for - simple modes, but will return an inner mode for nesting modes - (such as htmlmixed).
- -
cm.getTokenAt(pos: {line, ch}, ?precise: boolean) → object
-
Retrieves information about the token the current mode found - before the given position (a {line, ch} object). The - returned object has the following properties: -
-
start
The character (on the given line) at which the token starts.
-
end
The character at which the token ends.
-
string
The token's string.
-
type
The token type the mode assigned - to the token, such as "keyword" - or "comment" (may also be null).
-
state
The mode's state at the end of this token.
-
- If precise is true, the token will be guaranteed to be accurate based on recent edits. If false or - not specified, the token will use cached state information, which will be faster but might not be accurate if - edits were recently made and highlighting has not yet completed. -
- -
cm.getLineTokens(line: integer, ?precise: boolean) → array<{start, end, string, type, state}>
-
This is similar - to getTokenAt, but - collects all tokens for a given line into an array. It is much - cheaper than repeatedly calling getTokenAt, which - re-parses the part of the line before the token for every call.
- -
cm.getTokenTypeAt(pos: {line, ch}) → string
-
This is a (much) cheaper version - of getTokenAt useful for - when you just need the type of the token at a given position, - and no other information. Will return null for - unstyled tokens, and a string, potentially containing multiple - space-separated style names, otherwise.
- -
cm.getHelpers(pos: {line, ch}, type: string) → array<helper>
-
Fetch the set of applicable helper values for the given - position. Helpers provide a way to look up functionality - appropriate for a mode. The type argument provides - the helper namespace (see - registerHelper), in - which the values will be looked up. When the mode itself has a - property that corresponds to the type, that - directly determines the keys that are used to look up the helper - values (it may be either a single string, or an array of - strings). Failing that, the mode's helperType - property and finally the mode's name are used.
-
For example, the JavaScript mode has a - property fold containing "brace". When - the brace-fold addon is loaded, that defines a - helper named brace in the fold - namespace. This is then used by - the foldcode addon to - figure out that it can use that folding function to fold - JavaScript code.
-
When any 'global' - helpers are defined for the given namespace, their predicates - are called on the current mode and editor, and all those that - declare they are applicable will also be added to the array that - is returned.
- -
cm.getHelper(pos: {line, ch}, type: string) → helper
-
Returns the first applicable helper value. - See getHelpers.
- -
cm.getStateAfter(?line: integer, ?precise: boolean) → object
-
Returns the mode's parser state, if any, at the end of the - given line number. If no line number is given, the state at the - end of the document is returned. This can be useful for storing - parsing errors in the state, or getting other kinds of - contextual information for a line. precise is defined - as in getTokenAt().
-
- -

Miscellaneous methods

- -
-
cm.operation(func: () → any) → any
-
CodeMirror internally buffers changes and only updates its - DOM structure after it has finished performing some operation. - If you need to perform a lot of operations on a CodeMirror - instance, you can call this method with a function argument. It - will call the function, buffering up all changes, and only doing - the expensive update after the function returns. This can be a - lot faster. The return value from this method will be the return - value of your function.
- -
cm.indentLine(line: integer, ?dir: string|integer)
-
Adjust the indentation of the given line. The second - argument (which defaults to "smart") may be one of: -
-
"prev"
-
Base indentation on the indentation of the previous line.
-
"smart"
-
Use the mode's smart indentation if available, behave - like "prev" otherwise.
-
"add"
-
Increase the indentation of the line by - one indent unit.
-
"subtract"
-
Reduce the indentation of the line.
-
<integer>
-
Add (positive number) or reduce (negative number) the - indentation by the given amount of spaces.
-
- -
cm.toggleOverwrite(?value: bool)
-
Switches between overwrite and normal insert mode (when not - given an argument), or sets the overwrite mode to a specific - state (when given an argument).
- -
cm.execCommand(name: string)
-
Runs the command with the given name on the editor.
- -
doc.posFromIndex(index: integer) → {line, ch}
-
Calculates and returns a {line, ch} object for a - zero-based index who's value is relative to the start of the - editor's text. If the index is out of range of the text then - the returned object is clipped to start or end of the text - respectively.
-
doc.indexFromPos(object: {line, ch}) → integer
-
The reverse of posFromIndex.
- -
cm.focus()
-
Give the editor focus.
- -
cm.getInputField() → Element
-
Returns the input field for the editor. Will be a textarea - or an editable div, depending on the value of - the inputStyle - option.
-
cm.getWrapperElement() → Element
-
Returns the DOM node that represents the editor, and - controls its size. Remove this from your tree to delete an - editor instance.
-
cm.getScrollerElement() → Element
-
Returns the DOM node that is responsible for the scrolling - of the editor.
-
cm.getGutterElement() → Element
-
Fetches the DOM node that contains the editor gutters.
-
- -

Static properties

-

The CodeMirror object itself provides - several useful properties.

- -
-
CodeMirror.version: string
-
It contains a string that indicates the version of the - library. This is a triple of - integers "major.minor.patch", - where patch is zero for releases, and something - else (usually one) for dev snapshots.
- -
CodeMirror.fromTextArea(textArea: TextAreaElement, ?config: object)
-
- The method provides another way to initialize an editor. It - takes a textarea DOM node as first argument and an optional - configuration object as second. It will replace the textarea - with a CodeMirror instance, and wire up the form of that - textarea (if any) to make sure the editor contents are put - into the textarea when the form is submitted. The text in the - textarea will provide the content for the editor. A CodeMirror - instance created this way has three additional methods: -
-
cm.save()
-
Copy the content of the editor into the textarea.
- -
cm.toTextArea()
-
Remove the editor, and restore the original textarea (with - the editor's current content).
- -
cm.getTextArea() → TextAreaElement
-
Returns the textarea that the instance was based on.
-
-
- -
CodeMirror.defaults: object
-
An object containing default values for - all options. You can assign to its - properties to modify defaults (though this won't affect editors - that have already been created).
- -
CodeMirror.defineExtension(name: string, value: any)
-
If you want to define extra methods in terms of the - CodeMirror API, it is possible to - use defineExtension. This will cause the given - value (usually a method) to be added to all CodeMirror instances - created from then on.
- -
CodeMirror.defineDocExtension(name: string, value: any)
-
Like defineExtension, - but the method will be added to the interface - for Doc objects instead.
- -
CodeMirror.defineOption(name: string, - default: any, updateFunc: function)
-
Similarly, defineOption can be used to define new options for - CodeMirror. The updateFunc will be called with the - editor instance and the new value when an editor is initialized, - and whenever the option is modified - through setOption.
- -
CodeMirror.defineInitHook(func: function)
-
If your extention just needs to run some - code whenever a CodeMirror instance is initialized, - use CodeMirror.defineInitHook. Give it a function as - its only argument, and from then on, that function will be called - (with the instance as argument) whenever a new CodeMirror instance - is initialized.
- -
CodeMirror.registerHelper(type: string, name: string, value: helper)
-
Registers a helper value with the given name in - the given namespace (type). This is used to define - functionality that may be looked up by mode. Will create (if it - doesn't already exist) a property on the CodeMirror - object for the given type, pointing to an object - that maps names to values. I.e. after - doing CodeMirror.registerHelper("hint", "foo", - myFoo), the value CodeMirror.hint.foo will - point to myFoo.
- -
CodeMirror.registerGlobalHelper(type: string, name: string, predicate: fn(mode, CodeMirror), value: helper)
-
Acts - like registerHelper, - but also registers this helper as 'global', meaning that it will - be included by getHelpers - whenever the given predicate returns true when - called with the local mode and editor.
- -
CodeMirror.Pos(line: integer, ?ch: integer)
-
A constructor for the {line, ch} objects that - are used to represent positions in editor documents.
- -
CodeMirror.changeEnd(change: object) → {line, ch}
-
Utility function that computes an end position from a change - (an object with from, to, - and text properties, as passed to - various event handlers). The - returned position will be the end of the changed - range, after the change is applied.
-
-
- -
-

Addons

- -

The addon directory in the distribution contains a - number of reusable components that implement extra editor - functionality (on top of extension functions - like defineOption, defineExtension, - and registerHelper). In - brief, they are:

- -
-
dialog/dialog.js
-
Provides a very simple way to query users for text input. - Adds the openDialog(template, callback, options) → - closeFunction method to CodeMirror instances, - which can be called with an HTML fragment or a detached DOM - node that provides the prompt (should include an input - or button tag), and a callback function that is called - when the user presses enter. It returns a function closeFunction - which, if called, will close the dialog immediately. - openDialog takes the following options: -
-
closeOnEnter:
-
If true, the dialog will be closed when the user presses - enter in the input. Defaults to true.
-
onKeyDown:
-
An event handler of the signature (event, value, closeFunction) - that will be called whenever keydown fires in the - dialog's input. If your callback returns true, - the dialog will not do any further processing of the event.
-
onKeyUp:
-
Same as onKeyDown but for the - keyup event.
-
onInput:
-
Same as onKeyDown but for the - input event.
-
onClose:
-
A callback of the signature (dialogInstance) - that will be called after the dialog has been closed and - removed from the DOM. No return value.
-
- -

Also adds an openNotification(template, options) → - closeFunction function that simply shows an HTML - fragment as a notification at the top of the editor. It takes a - single option: duration, the amount of time after - which the notification will be automatically closed. If - duration is zero, the dialog will not be closed automatically.

- -

Depends on addon/dialog/dialog.css.

- -
search/searchcursor.js
-
Adds the getSearchCursor(query, start, caseFold) → - cursor method to CodeMirror instances, which can be used - to implement search/replace functionality. query - can be a regular expression or a string (only strings will match - across lines—if they contain newlines). start - provides the starting position of the search. It can be - a {line, ch} object, or can be left off to default - to the start of the document. caseFold is only - relevant when matching a string. It will cause the search to be - case-insensitive. A search cursor has the following methods: -
-
findNext() → boolean
-
findPrevious() → boolean
-
Search forward or backward from the current position. - The return value indicates whether a match was found. If - matching a regular expression, the return value will be the - array returned by the match method, in case you - want to extract matched groups.
-
from() → {line, ch}
-
to() → {line, ch}
-
These are only valid when the last call - to findNext or findPrevious did - not return false. They will return {line, ch} - objects pointing at the start and end of the match.
-
replace(text: string)
-
Replaces the currently found match with the given text - and adjusts the cursor position to reflect the - replacement.
-
- - -
Implements the search commands. CodeMirror has keys bound to - these by default, but will not do anything with them unless an - implementation is provided. Depends - on searchcursor.js, and will make use - of openDialog when - available to make prompting for search queries less ugly.
- -
search/matchesonscrollbar.js
-
Adds a showMatchesOnScrollbar method to editor - instances, which should be given a query (string or regular - expression), optionally a case-fold flag (only applicable for - strings), and optionally a class name (defaults - to CodeMirror-search-match) as arguments. When - called, matches of the given query will be displayed on the - editor's vertical scrollbar. The method returns an object with - a clear method that can be called to remove the - matches. Depends on - the annotatescrollbar - addon, and - the matchesonscrollbar.css - file provides a default (transparent yellowish) definition of - the CSS class applied to the matches. Note that the matches are - only perfectly aligned if your scrollbar does not have buttons - at the top and bottom. You can use - the simplescrollbar - addon to make sure of this. If this addon is loaded, - the search addon will - automatically use it.
- -
edit/matchbrackets.js
-
Defines an option matchBrackets which, when set - to true, causes matching brackets to be highlighted whenever the - cursor is next to them. It also adds a - method matchBrackets that forces this to happen - once, and a method findMatchingBracket that can be - used to run the bracket-finding algorithm that this uses - internally.
- -
edit/closebrackets.js
-
Defines an option autoCloseBrackets that will - auto-close brackets and quotes when typed. By default, it'll - auto-close ()[]{}''"", but you can pass it a string - similar to that (containing pairs of matching characters), or an - object with pairs and - optionally explode properties to customize - it. explode should be a similar string that gives - the pairs of characters that, when enter is pressed between - them, should have the second character also moved to its own - line. Demo here.
- -
edit/matchtags.js
-
Defines an option matchTags that, when enabled, - will cause the tags around the cursor to be highlighted (using - the CodeMirror-matchingtag class). Also - defines - a command toMatchingTag, - which you can bind a key to in order to jump to the tag mathing - the one under the cursor. Depends on - the addon/fold/xml-fold.js - addon. Demo here.
- -
edit/trailingspace.js
-
Adds an option showTrailingSpace which, when - enabled, adds the CSS class cm-trailingspace to - stretches of whitespace at the end of lines. - The demo has a nice - squiggly underline style for this class.
- -
edit/closetag.js
-
Defines an autoCloseTags option that will - auto-close XML tags when '>' or '/' - is typed, and - a closeTag command that - closes the nearest open tag. Depends on - the fold/xml-fold.js addon. See - the demo.
- -
edit/continuelist.js
-
Markdown specific. Defines - a "newlineAndIndentContinueMarkdownList" command - command that can be bound to enter to automatically - insert the leading characters for continuing a list. See - the Markdown mode - demo.
- -
comment/comment.js
-
Addon for commenting and uncommenting code. Adds three - methods to CodeMirror instances: -
-
lineComment(from: {line, ch}, to: {line, ch}, ?options: object)
-
Set the lines in the given range to be line comments. Will - fall back to blockComment when no line comment - style is defined for the mode.
-
blockComment(from: {line, ch}, to: {line, ch}, ?options: object)
-
Wrap the code in the given range in a block comment. Will - fall back to lineComment when no block comment - style is defined for the mode.
-
uncomment(from: {line, ch}, to: {line, ch}, ?options: object) → boolean
-
Try to uncomment the given range. - Returns true if a comment range was found and - removed, false otherwise.
-
- The options object accepted by these methods may - have the following properties: -
-
blockCommentStart, blockCommentEnd, blockCommentLead, lineComment: string
-
Override the comment string - properties of the mode with custom comment strings.
-
padding: string
-
A string that will be inserted after opening and leading - markers, and before closing comment markers. Defaults to a - single space.
-
commentBlankLines: boolean
-
Whether, when adding line comments, to also comment lines - that contain only whitespace.
-
indent: boolean
-
When adding line comments and this is turned on, it will - align the comment block to the current indentation of the - first line of the block.
-
fullLines: boolean
-
When block commenting, this controls whether the whole - lines are indented, or only the precise range that is given. - Defaults to true.
-
- The addon also defines - a toggleComment command, - which will try to uncomment the current selection, and if that - fails, line-comments it.
- -
fold/foldcode.js
-
Helps with code folding. Adds a foldCode method - to editor instances, which will try to do a code fold starting - at the given line, or unfold the fold that is already present. - The method takes as first argument the position that should be - folded (may be a line number or - a Pos), and as second optional - argument either a range-finder function, or an options object, - supporting the following properties: -
-
rangeFinder: fn(CodeMirror, Pos)
-
The function that is used to find - foldable ranges. If this is not directly passed, it will - default to CodeMirror.fold.auto, which - uses getHelpers with - a "fold" type to find folding functions - appropriate for the local mode. There are files in - the addon/fold/ - directory providing CodeMirror.fold.brace, which - finds blocks in brace languages (JavaScript, C, Java, - etc), CodeMirror.fold.indent, for languages where - indentation determines block structure (Python, Haskell), - and CodeMirror.fold.xml, for XML-style languages, - and CodeMirror.fold.comment, for folding comment - blocks.
-
widget: string|Element
-
The widget to show for folded ranges. Can be either a - string, in which case it'll become a span with - class CodeMirror-foldmarker, or a DOM node.
-
scanUp: boolean
-
When true (default is false), the addon will try to find - foldable ranges on the lines above the current one if there - isn't an eligible one on the given line.
-
minFoldSize: integer
-
The minimum amount of lines that a fold should span to be - accepted. Defaults to 0, which also allows single-line - folds.
-
- See the demo for an - example.
- -
fold/foldgutter.js
-
Provides an option foldGutter, which can be - used to create a gutter with markers indicating the blocks that - can be folded. Create a gutter using - the gutters option, - giving it the class CodeMirror-foldgutter or - something else if you configure the addon to use a different - class, and this addon will show markers next to folded and - foldable blocks, and handle clicks in this gutter. Note that - CSS styles should be applied to make the gutter, and the fold - markers within it, visible. A default set of CSS styles are - available in: - - addon/fold/foldgutter.css - . - The option - can be either set to true, or an object containing - the following optional option fields: -
-
gutter: string
-
The CSS class of the gutter. Defaults - to "CodeMirror-foldgutter". You will have to - style this yourself to give it a width (and possibly a - background). See the default gutter style rules above.
-
indicatorOpen: string | Element
-
A CSS class or DOM element to be used as the marker for - open, foldable blocks. Defaults - to "CodeMirror-foldgutter-open".
-
indicatorFolded: string | Element
-
A CSS class or DOM element to be used as the marker for - folded blocks. Defaults to "CodeMirror-foldgutter-folded".
-
rangeFinder: fn(CodeMirror, Pos)
-
The range-finder function to use when determining whether - something can be folded. When not - given, CodeMirror.fold.auto - will be used as default.
-
- The foldOptions editor option can be set to an - object to provide an editor-wide default configuration. - Demo here.
- -
runmode/runmode.js
-
Can be used to run a CodeMirror mode over text without - actually opening an editor instance. - See the demo for an example. - There are alternate versions of the file avaible for - running stand-alone - (without including all of CodeMirror) and - for running under - node.js.
- -
runmode/colorize.js
-
Provides a convenient way to syntax-highlight code snippets - in a webpage. Depends on - the runmode addon (or - its standalone variant). Provides - a CodeMirror.colorize function that can be called - with an array (or other array-ish collection) of DOM nodes that - represent the code snippets. By default, it'll get - all pre tags. Will read the data-lang - attribute of these nodes to figure out their language, and - syntax-color their content using the relevant CodeMirror mode - (you'll have to load the scripts for the relevant modes - yourself). A second argument may be provided to give a default - mode, used when no language attribute is found for a node. Used - in this manual to highlight example code.
- -
mode/overlay.js
-
Mode combinator that can be used to extend a mode with an - 'overlay' — a secondary mode is run over the stream, along with - the base mode, and can color specific pieces of text without - interfering with the base mode. - Defines CodeMirror.overlayMode, which is used to - create such a mode. See this - demo for a detailed example.
- -
mode/multiplex.js
-
Mode combinator that can be used to easily 'multiplex' - between several modes. - Defines CodeMirror.multiplexingMode which, when - given as first argument a mode object, and as other arguments - any number of {open, close, mode [, delimStyle, innerStyle]} - objects, will return a mode object that starts parsing using the - mode passed as first argument, but will switch to another mode - as soon as it encounters a string that occurs in one of - the open fields of the passed objects. When in a - sub-mode, it will go back to the top mode again when - the close string is encountered. - Pass "\n" for open or close - if you want to switch on a blank line. -
  • When delimStyle is specified, it will be the token - style returned for the delimiter tokens.
  • -
  • When innerStyle is specified, it will be the token - style added for each inner mode token.
- The outer mode will not see the content between the delimiters. - See this demo for an - example.
- -
hint/show-hint.js
-
Provides a framework for showing autocompletion hints. - Defines editor.showHint, which takes an optional - options object, and pops up a widget that allows the user to - select a completion. Finding hints is done with a hinting - functions (the hint option), which is a function - that take an editor instance and options object, and return - a {list, from, to} object, where list - is an array of strings or objects (the completions), - and from and to give the start and end - of the token that is being completed as {line, ch} - objects.
-
If no hinting function is given, the addon will - use CodeMirror.hint.auto, which - calls getHelpers with - the "hint" type to find applicable hinting - functions, and tries them one by one. If that fails, it looks - for a "hintWords" helper to fetch a list of - completable words for the mode, and - uses CodeMirror.hint.fromList to complete from - those.
-
When completions aren't simple strings, they should be - objects with the following properties: -
-
text: string
-
The completion text. This is the only required - property.
-
displayText: string
-
The text that should be displayed in the menu.
-
className: string
-
A CSS class name to apply to the completion's line in the - menu.
-
render: fn(Element, self, data)
-
A method used to create the DOM structure for showing the - completion by appending it to its first argument.
-
hint: fn(CodeMirror, self, data)
-
A method used to actually apply the completion, instead of - the default behavior.
-
from: {line, ch}
-
Optional from position that will be used by pick() instead - of the global one passed with the full list of completions.
-
to: {line, ch}
-
Optional to position that will be used by pick() instead - of the global one passed with the full list of completions.
-
- The plugin understands the following options (the options object - will also be passed along to the hinting function, which may - understand additional options): -
-
hint: function
-
A hinting function, as specified above. It is possible to - set the async property on a hinting function to - true, in which case it will be called with - arguments (cm, callback, ?options), and the - completion interface will only be popped up when the hinting - function calls the callback, passing it the object holding the - completions.
-
completeSingle: boolean
-
Determines whether, when only a single completion is - available, it is completed without showing the dialog. - Defaults to true.
-
alignWithWord: boolean
-
Whether the pop-up should be horizontally aligned with the - start of the word (true, default), or with the cursor (false).
-
closeOnUnfocus: boolean
-
When enabled (which is the default), the pop-up will close - when the editor is unfocused.
-
customKeys: keymap
-
Allows you to provide a custom key map of keys to be active - when the pop-up is active. The handlers will be called with an - extra argument, a handle to the completion menu, which - has moveFocus(n), setFocus(n), pick(), - and close() methods (see the source for details), - that can be used to change the focused element, pick the - current element or close the menu. Additionnaly menuSize() - can give you access to the size of the current dropdown menu, - length give you the number of availlable completions, and - data give you full access to the completion returned by the - hinting function.
-
extraKeys: keymap
-
Like customKeys above, but the bindings will - be added to the set of default bindings, instead of replacing - them.
-
- The following events will be fired on the completions object - during completion: -
-
"shown" ()
-
Fired when the pop-up is shown.
-
"select" (completion, Element)
-
Fired when a completion is selected. Passed the completion - value (string or object) and the DOM node that represents it - in the menu.
-
"pick" (completion)
-
Fired when a completion is picked. Passed the completion value - (string or object).
-
"close" ()
-
Fired when the completion is finished.
-
- This addon depends on styles - from addon/hint/show-hint.css. Check - out the demo for an - example.
- -
hint/javascript-hint.js
-
Defines a simple hinting function for JavaScript - (CodeMirror.hint.javascript) and CoffeeScript - (CodeMirror.hint.coffeescript) code. This will - simply use the JavaScript environment that the editor runs in as - a source of information about objects and their properties.
- -
hint/xml-hint.js
-
Defines CodeMirror.hint.xml, which produces - hints for XML tagnames, attribute names, and attribute values, - guided by a schemaInfo option (a property of the - second argument passed to the hinting function, or the third - argument passed to CodeMirror.showHint).
The - schema info should be an object mapping tag names to information - about these tags, with optionally a "!top" property - containing a list of the names of valid top-level tags. The - values of the properties should be objects with optional - properties children (an array of valid child - element names, omit to simply allow all tags to appear) - and attrs (an object mapping attribute names - to null for free-form attributes, and an array of - valid values for restricted - attributes). Demo - here.
- -
hint/html-hint.js
-
Provides schema info to - the xml-hint addon for HTML - documents. Defines a schema - object CodeMirror.htmlSchema that you can pass to - as a schemaInfo option, and - a CodeMirror.hint.html hinting function that - automatically calls CodeMirror.hint.xml with this - schema data. See - the demo.
- -
hint/css-hint.js
-
A hinting function for CSS, SCSS, or LESS code. - Defines CodeMirror.hint.css.
- -
hint/anyword-hint.js
-
A very simple hinting function - (CodeMirror.hint.anyword) that simply looks for - words in the nearby code and completes to those. Takes two - optional options, word, a regular expression that - matches words (sequences of one or more character), - and range, which defines how many lines the addon - should scan when completing (defaults to 500).
- -
hint/sql-hint.js
-
A simple SQL hinter. Defines CodeMirror.hint.sql. - Takes two optional options, tables, a object with - table names as keys and array of respective column names as values, - and defaultTable, a string corresponding to a - table name in tables for autocompletion.
- -
search/match-highlighter.js
-
Adds a highlightSelectionMatches option that - can be enabled to highlight all instances of a currently - selected word. Can be set either to true or to an object - containing the following options: minChars, for the - minimum amount of selected characters that triggers a highlight - (default 2), style, for the style to be used to - highlight the matches (default "matchhighlight", - which will correspond to CSS - class cm-matchhighlight), - and showToken which can be set to true - or to a regexp matching the characters that make up a word. When - enabled, it causes the current word to be highlighted when - nothing is selected (defaults to off). - Demo here.
- -
lint/lint.js
-
Defines an interface component for showing linting warnings, - with pluggable warning sources - (see json-lint.js, - javascript-lint.js, - coffeescript-lint.js, - and css-lint.js - in the same directory). Defines a lint option that - can be set to a warning source (for - example CodeMirror.lint.javascript), or - to true, in which - case getHelper with - type "lint" is used to determined a validator - function. Depends on addon/lint/lint.css. A demo - can be found here.
- -
selection/mark-selection.js
-
Causes the selected text to be marked with the CSS class - CodeMirror-selectedtext when the styleSelectedText option - is enabled. Useful to change the colour of the selection (in addition to the background), - like in this demo.
- -
selection/active-line.js
-
Defines a styleActiveLine option that, when enabled, - gives the wrapper of the active line the class CodeMirror-activeline, - and adds a background with the class CodeMirror-activeline-background. - is enabled. See the demo.
- -
selection/selection-pointer.js
-
Defines a selectionPointer option which you can - use to control the mouse cursor appearance when hovering over - the selection. It can be set to a string, - like "pointer", or to true, in which case - the "default" (arrow) cursor will be used. You can - see a demo here.
- -
mode/loadmode.js
-
Defines a CodeMirror.requireMode(modename, - callback) function that will try to load a given mode and - call the callback when it succeeded. You'll have to - set CodeMirror.modeURL to a string that mode paths - can be constructed from, for - example "mode/%N/%N.js"—the %N's will - be replaced with the mode name. Also - defines CodeMirror.autoLoadMode(instance, mode), - which will ensure the given mode is loaded and cause the given - editor instance to refresh its mode when the loading - succeeded. See the demo.
- -
mode/meta.js
-
Provides meta-information about all the modes in the - distribution in a single file. - Defines CodeMirror.modeInfo, an array of objects - with {name, mime, mode} properties, - where name is the human-readable - name, mime the MIME type, and mode the - name of the mode file that defines this MIME. There are optional - properties mimes, which holds an array of MIME - types for modes with multiple MIMEs associated, - and ext, which holds an array of file extensions - associated with this mode. Four convenience - functions, CodeMirror.findModeByMIME, - CodeMirror.findModeByExtension, - CodeMirror.findModeByFileName - and CodeMirror.findModeByName are provided, which - return such an object given a MIME, extension, file name or mode name - string. Note that, for historical reasons, this file resides in the - top-level mode directory, not - under addon. Demo.
- -
comment/continuecomment.js
-
Adds a continueComments option, which sets whether the - editor will make the next line continue a comment when you press Enter - inside a comment block. Can be set to a boolean to enable/disable this - functionality. Set to a string, it will continue comments using a custom - shortcut. Set to an object, it will use the key property for - a custom shortcut and the boolean continueLineComment - property to determine whether single-line comments should be continued - (defaulting to true).
- -
display/placeholder.js
-
Adds a placeholder option that can be used to - make text appear in the editor when it is empty and not focused. - Also gives the editor a CodeMirror-empty CSS class - whenever it doesn't contain any text. - See the demo.
- -
display/fullscreen.js
-
Defines an option fullScreen that, when set - to true, will make the editor full-screen (as in, - taking up the whole browser window). Depends - on fullscreen.css. Demo - here.
- -
scroll/simplescrollbars.js
-
Defines two additional scrollbar - models, "simple" and "overlay" - (see demo) that can - be selected with - the scrollbarStyle - option. Depends - on simplescrollbars.css, - which can be further overridden to style your own - scrollbars.
- -
scroll/annotatescrollbar.js
-
Provides functionality for showing markers on the scrollbar - to call out certain parts of the document. Adds a - method annotateScrollbar to editor instances that - can be called, with a CSS class name as argument, to create a - set of annotations. The method returns an object - whose update method can be called with an array - of {from: Pos, to: Pos} objects marking the ranges - to be higlighed. To detach the annotations, call the - object's clear method.
- -
display/rulers.js
-
Adds a rulers option, which can be used to show - one or more vertical rulers in the editor. The option, if - defined, should be given an array of {column [, className, - color, lineStyle, width]} objects or numbers (wich - indicate a column). The ruler will be displayed at the column - indicated by the number or the column property. - The className property can be used to assign a - custom style to a ruler. Demo - here.
- -
display/panel.js
-
Defines an addPanel method for CodeMirror - instances, which places a DOM node above or below an editor, and - shrinks the editor to make room for the node. The method takes - as first argument as DOM node, and as second an optional options - object. By default, the panel ends up above the editor. This can - be changed by passing a position option with the - value "bottom". The object returned by this method - has a clear method that is used to remove the - panel, and a changed method that can be used to - notify the addon when the size of the panel's DOM node has - changed.
- -
wrap/hardwrap.js
-
Addon to perform hard line wrapping/breaking for paragraphs - of text. Adds these methods to editor instances: -
-
wrapParagraph(?pos: {line, ch}, ?options: object)
-
Wraps the paragraph at the given position. - If pos is not given, it defaults to the cursor - position.
-
wrapRange(from: {line, ch}, to: {line, ch}, ?options: object)
-
Wraps the given range as one big paragraph.
-
wrapParagraphsInRange(from: {line, ch}, to: {line, ch}, ?options: object)
-
Wrapps the paragraphs in (and overlapping with) the - given range individually.
-
- The following options are recognized: -
-
paragraphStart, paragraphEnd: RegExp
-
Blank lines are always considered paragraph boundaries. - These options can be used to specify a pattern that causes - lines to be considered the start or end of a paragraph.
-
column: number
-
The column to wrap at. Defaults to 80.
-
wrapOn: RegExp
-
A regular expression that matches only those - two-character strings that allow wrapping. By default, the - addon wraps on whitespace and after dash characters.
-
killTrailingSpace: boolean
-
Whether trailing space caused by wrapping should be - preserved, or deleted. Defaults to true.
-
- A demo of the addon is available here. -
- -
merge/merge.js
-
Implements an interface for merging changes, using either a - 2-way or a 3-way view. The CodeMirror.MergeView - constructor takes arguments similar to - the CodeMirror - constructor, first a node to append the interface to, and then - an options object. Options are passed through to the editors - inside the view. These extra options are recognized: -
-
origLeft and origRight: string
-
If given these provide original versions of the - document, which will be shown to the left and right of the - editor in non-editable CodeMirror instances. The merge - interface will highlight changes between the editable - document and the original(s). To create a 2-way (as opposed - to 3-way) merge view, provide only one of them.
-
revertButtons: boolean
-
Determines whether buttons that allow the user to revert - changes are shown. Defaults to true.
-
connect: string
-
Sets the style used to connect changed chunks of code. - By default, connectors are drawn. When this is set - to "align", the smaller chunk is padded to - align with the bigger chunk instead.
-
collapseIdentical: boolean|number
-
When true (default is false), stretches of unchanged - text will be collapsed. When a number is given, this - indicates the amount of lines to leave visible around such - stretches (which defaults to 2).
-
allowEditingOriginals: boolean
-
Determines whether the original editor allows editing. - Defaults to false.
-
showDifferences: boolean
-
When true (the default), changed pieces of text are - highlighted.
-
- Demo here.
- -
tern/tern.js
-
Provides integration with - the Tern JavaScript analysis - engine, for completion, definition finding, and minor - refactoring help. See the demo - for a very simple integration. For more involved scenarios, see - the comments at the top of - the addon and the - implementation of the - (multi-file) demonstration - on the Tern website.
-
-
- -
-

Writing CodeMirror Modes

- -

Modes typically consist of a single JavaScript file. This file - defines, in the simplest case, a lexer (tokenizer) for your - language—a function that takes a character stream as input, - advances it past a token, and returns a style for that token. More - advanced modes can also handle indentation for the language.

- -

This section describes the low-level mode interface. Many modes - are written directly against this, since it offers a lot of - control, but for a quick mode definition, you might want to use - the simple mode addon.

- -

The mode script should - call CodeMirror.defineMode to - register itself with CodeMirror. This function takes two - arguments. The first should be the name of the mode, for which you - should use a lowercase string, preferably one that is also the - name of the files that define the mode (i.e. "xml" is - defined in xml.js). The second argument should be a - function that, given a CodeMirror configuration object (the thing - passed to the CodeMirror function) and an optional - mode configuration object (as in - the mode option), returns - a mode object.

- -

Typically, you should use this second argument - to defineMode as your module scope function (modes - should not leak anything into the global scope!), i.e. write your - whole mode inside this function.

- -

The main responsibility of a mode script is parsing - the content of the editor. Depending on the language and the - amount of functionality desired, this can be done in really easy - or extremely complicated ways. Some parsers can be stateless, - meaning that they look at one element (token) of the code - at a time, with no memory of what came before. Most, however, will - need to remember something. This is done by using a state - object, which is an object that is always passed when - reading a token, and which can be mutated by the tokenizer.

- -

Modes that use a state must define - a startState method on their mode - object. This is a function of no arguments that produces a state - object to be used at the start of a document.

- -

The most important part of a mode object is - its token(stream, state) method. All - modes must define this method. It should read one token from the - stream it is given as an argument, optionally update its state, - and return a style string, or null for tokens that do - not have to be styled. For your styles, you are encouraged to use - the 'standard' names defined in the themes (without - the cm- prefix). If that fails, it is also possible - to come up with your own and write your own CSS theme file.

- -

A typical token string would - be "variable" or "comment". Multiple - styles can be returned (separated by spaces), for - example "string error" for a thing that looks like a - string but is invalid somehow (say, missing its closing quote). - When a style is prefixed by "line-" - or "line-background-", the style will be applied to - the whole line, analogous to what - the addLineClass method - does—styling the "text" in the simple case, and - the "background" element - when "line-background-" is prefixed.

- -

The stream object that's passed - to token encapsulates a line of code (tokens may - never span lines) and our current position in that line. It has - the following API:

- -
-
eol() → boolean
-
Returns true only if the stream is at the end of the - line.
-
sol() → boolean
-
Returns true only if the stream is at the start of the - line.
- -
peek() → string
-
Returns the next character in the stream without advancing - it. Will return an null at the end of the - line.
-
next() → string
-
Returns the next character in the stream and advances it. - Also returns null when no more characters are - available.
- -
eat(match: string|regexp|function(char: string) → boolean) → string
-
match can be a character, a regular expression, - or a function that takes a character and returns a boolean. If - the next character in the stream 'matches' the given argument, - it is consumed and returned. Otherwise, undefined - is returned.
-
eatWhile(match: string|regexp|function(char: string) → boolean) → boolean
-
Repeatedly calls eat with the given argument, - until it fails. Returns true if any characters were eaten.
-
eatSpace() → boolean
-
Shortcut for eatWhile when matching - white-space.
-
skipToEnd()
-
Moves the position to the end of the line.
-
skipTo(ch: string) → boolean
-
Skips to the next occurrence of the given character, if - found on the current line (doesn't advance the stream if the - character does not occur on the line). Returns true if the - character was found.
-
match(pattern: string, ?consume: boolean, ?caseFold: boolean) → boolean
-
match(pattern: regexp, ?consume: boolean) → array<string>
-
Act like a - multi-character eat—if consume is true - or not given—or a look-ahead that doesn't update the stream - position—if it is false. pattern can be either a - string or a regular expression starting with ^. - When it is a string, caseFold can be set to true to - make the match case-insensitive. When successfully matching a - regular expression, the returned value will be the array - returned by match, in case you need to extract - matched groups.
- -
backUp(n: integer)
-
Backs up the stream n characters. Backing it up - further than the start of the current token will cause things to - break, so be careful.
-
column() → integer
-
Returns the column (taking into account tabs) at which the - current token starts.
-
indentation() → integer
-
Tells you how far the current line has been indented, in - spaces. Corrects for tab characters.
- -
current() → string
-
Get the string between the start of the current token and - the current stream position.
-
- -

By default, blank lines are simply skipped when - tokenizing a document. For languages that have significant blank - lines, you can define - a blankLine(state) method on your - mode that will get called whenever a blank line is passed over, so - that it can update the parser state.

- -

Because state object are mutated, and CodeMirror - needs to keep valid versions of a state around so that it can - restart a parse at any line, copies must be made of state objects. - The default algorithm used is that a new state object is created, - which gets all the properties of the old object. Any properties - which hold arrays get a copy of these arrays (since arrays tend to - be used as mutable stacks). When this is not correct, for example - because a mode mutates non-array properties of its state object, a - mode object should define - a copyState method, which is given a - state and should return a safe copy of that state.

- -

If you want your mode to provide smart indentation - (through the indentLine - method and the indentAuto - and newlineAndIndent commands, to which keys can be - bound), you must define - an indent(state, textAfter) method - on your mode object.

- -

The indentation method should inspect the given state object, - and optionally the textAfter string, which contains - the text on the line that is being indented, and return an - integer, the amount of spaces to indent. It should usually take - the indentUnit - option into account. An indentation method may - return CodeMirror.Pass to indicate that it - could not come up with a precise indentation.

- -

To work well with - the commenting addon, a mode may - define lineComment (string that - starts a line - comment), blockCommentStart, blockCommentEnd - (strings that start and end block comments), - and blockCommentLead (a string to put at the start of - continued lines in a block comment). All of these are - optional.

- -

Finally, a mode may define either - an electricChars or an electricInput - property, which are used to automatically reindent the line when - certain patterns are typed and - the electricChars - option is enabled. electricChars may be a string, and - will trigger a reindent whenever one of the characters in that - string are typed. Often, it is more appropriate to - use electricInput, which should hold a regular - expression, and will trigger indentation when the part of the - line before the cursor matches the expression. It should - usually end with a $ character, so that it only - matches when the indentation-changing pattern was just typed, not when something was - typed after the pattern.

- -

So, to summarize, a mode must provide - a token method, and it may - provide startState, copyState, - and indent methods. For an example of a trivial mode, - see the diff mode, for a more - involved example, see the C-like - mode.

- -

Sometimes, it is useful for modes to nest—to have one - mode delegate work to another mode. An example of this kind of - mode is the mixed-mode HTML - mode. To implement such nesting, it is usually necessary to - create mode objects and copy states yourself. To create a mode - object, there are CodeMirror.getMode(options, - parserConfig), where the first argument is a configuration - object as passed to the mode constructor function, and the second - argument is a mode specification as in - the mode option. To copy a - state object, call CodeMirror.copyState(mode, state), - where mode is the mode that created the given - state.

- -

In a nested mode, it is recommended to add an - extra method, innerMode which, given - a state object, returns a {state, mode} object with - the inner mode and its state for the current position. These are - used by utility scripts such as the tag - closer to get context information. Use - the CodeMirror.innerMode helper function to, starting - from a mode and a state, recursively walk down to the innermost - mode and state.

- -

To make indentation work properly in a nested parser, it is - advisable to give the startState method of modes that - are intended to be nested an optional argument that provides the - base indentation for the block of code. The JavaScript and CSS - parser do this, for example, to allow JavaScript and CSS code - inside the mixed-mode HTML mode to be properly indented.

- -

It is possible, and encouraged, to associate - your mode, or a certain configuration of your mode, with - a MIME type. For - example, the JavaScript mode associates itself - with text/javascript, and its JSON variant - with application/json. To do this, - call CodeMirror.defineMIME(mime, - modeSpec), where modeSpec can be a string or - object specifying a mode, as in - the mode option.

- -

If a mode specification wants to add some properties to the - resulting mode object, typically for use - with getHelpers, it may - contain a modeProps property, which holds an object. - This object's properties will be copied to the actual mode - object.

- -

Sometimes, it is useful to add or override mode - object properties from external code. - The CodeMirror.extendMode function - can be used to add properties to mode objects produced for a - specific mode. Its first argument is the name of the mode, its - second an object that specifies the properties that should be - added. This is mostly useful to add utilities that can later be - looked up through getMode.

-
- -
- - diff --git a/shared/html/libs/codemirror/5.0.0/doc/realworld.html b/shared/html/libs/codemirror/5.0.0/doc/realworld.html deleted file mode 100644 index 7a326cf..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/realworld.html +++ /dev/null @@ -1,172 +0,0 @@ - - -CodeMirror: Real-world Uses - - - - - -
- -

CodeMirror real-world uses

- -

Create a pull - request if you'd like your project to be added to this list.

- - - -
- diff --git a/shared/html/libs/codemirror/5.0.0/doc/releases.html b/shared/html/libs/codemirror/5.0.0/doc/releases.html deleted file mode 100644 index 8b2b375..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/releases.html +++ /dev/null @@ -1,1049 +0,0 @@ - - -CodeMirror: Release History - - - - - - -
- -

Release notes and version history

- -
- -

Version 4.x

- -

20-02-2015: Version 5.0:

- -
    -
  • Experimental mobile support (tested on iOS, Android Chrome, stock Android browser)
  • -
  • New option inputStyle to switch between hidden textarea and contenteditable input.
  • -
  • The getInputField - method is no longer guaranteed to return a textarea.
  • -
  • Full list of patches.
  • -
- -

20-02-2015: Version 4.13:

- - - -

22-01-2015: Version 4.12:

- - - -

9-01-2015: Version 4.11:

- -

Unfortunately, 4.10 did not take care of the - Firefox scrolling issue entirely. This release adds two more patches - to address that.

- -

29-12-2014: Version 4.10:

- -

Emergency single-patch update to 4.9. Fixes - Firefox-specific problem where the cursor could end up behind the - horizontal scrollbar.

- -

23-12-2014: Version 4.9:

- - - -

22-11-2014: Version 4.8:

- - - -

20-10-2014: Version 4.7:

- -
    -
  • Incompatible: - The lint addon now passes the - editor's value as first argument to asynchronous lint functions, - for consistency. The editor is still passed, as fourth - argument.
  • -
  • Improved handling of unicode identifiers in modes for - languages that support them.
  • -
  • More mode - improvements: CoffeeScript - (indentation), Verilog - (indentation), Scala - (indentation, triple-quoted strings), - and PHP (interpolated - variables in heredoc strings).
  • -
  • New modes: Textile and Tornado templates.
  • -
  • Experimental new way to define modes.
  • -
  • Improvements to the Vim - bindings: Arbitrary insert mode key mappings are now possible, - and text objects are supported in visual mode.
  • -
  • The mode meta-information file - now includes information about file extensions, - and helper - functions findModeByMIME - and findModeByExtension.
  • -
  • New logo!
  • -
  • Full list of patches.
  • -
- -

19-09-2014: Version 4.6:

- - - -

21-08-2014: Version 4.5:

- -
    -
  • Fix several serious bugs with horizontal scrolling
  • -
  • New mode: Slim
  • -
  • New command: goLineLeftSmart
  • -
  • More fixes and extensions for the Vim visual block mode
  • -
  • Full list of patches.
  • -
- -

21-07-2014: Version 4.4:

- -
    -
  • Note: Some events might now fire in slightly - different order ("change" is still guaranteed to fire - before "cursorActivity")
  • -
  • Nested operations in multiple editors are now synced (complete - at same time, reducing DOM reflows)
  • -
  • Visual block mode for vim (<C-v>) is nearly complete
  • -
  • New mode: Kotlin
  • -
  • Better multi-selection paste for text copied from multiple CodeMirror selections
  • -
  • Full list of patches.
  • -
- -

23-06-2014: Version 4.3:

- -
    -
  • Several vim bindings - improvements: search and exCommand history, global flag - for :substitute, :global command. -
  • Allow hiding the cursor by - setting cursorBlinkRate - to a negative value.
  • -
  • Make gutter markers themeable, use this in foldgutter.
  • -
  • Full list of patches.
  • -
- -

19-05-2014: Version 4.2:

- -
    -
  • Fix problem where some modes were broken by the fact that empty tokens were forbidden.
  • -
  • Several fixes to context menu handling.
  • -
  • On undo, scroll change, not cursor, into view.
  • -
  • Rewritten Jade mode.
  • -
  • Various improvements to Shell (support for more syntax) and Python (better indentation) modes.
  • -
  • New mode: Cypher.
  • -
  • New theme: Neo.
  • -
  • Support direct styling options (color, line style, width) in the rulers addon.
  • -
  • Recognize per-editor configuration for the show-hint and foldcode addons.
  • -
  • More intelligent scanning for existing close tags in closetag addon.
  • -
  • In the Vim bindings: Fix bracket matching, support case conversion in visual mode, visual paste, append action.
  • -
  • Full list of patches.
  • -
- -

22-04-2014: Version 4.1:

- -
    -
  • Slightly incompatible: - The "cursorActivity" - event now fires after all other events for the operation (and only - for handlers that were actually registered at the time the - activity happened).
  • -
  • New command: insertSoftTab.
  • -
  • New mode: Django.
  • -
  • Improved modes: Verilog (rewritten), Jinja2, Haxe, PHP (string interpolation highlighted), JavaScript (indentation of trailing else, template strings), LiveScript (multi-line strings).
  • -
  • Many small issues from the 3.x→4.x transition were found and fixed.
  • -
  • Full list of patches.
  • -
- -

20-03-2014: Version 4.0:

- -

This is a new major version of CodeMirror. There - are a few incompatible changes in the API. Upgrade - with care, and read the upgrading - guide.

- - - -
- -
- -

Version 3.x

- -

22-04-2014: Version 3.24:

- -

Merges the improvements from 4.1 that could - easily be applied to the 3.x code. Also improves the way the editor - size is updated when line widgets change.

- -

20-03-2014: Version 3.23:

- -
    -
  • In the XML mode, - add brackets style to angle brackets, fix - case-sensitivity of tags for HTML.
  • -
  • New mode: Dylan.
  • -
  • Many improvements to the Vim bindings.
  • -
- -

21-02-2014: Version 3.22:

- - - -

16-01-2014: Version 3.21:

- -
    -
  • Auto-indenting a block will no longer add trailing whitespace to blank lines. -
  • Marking text has a new option clearWhenEmpty to control auto-removal.
  • -
  • Several bugfixes in the handling of bidirectional text.
  • -
  • The XML and CSS modes were largely rewritten. LESS support was added to the CSS mode.
  • -
  • The OCaml mode was moved to an mllike mode, F# support added.
  • -
  • Make it possible to fetch multiple applicable helper values with getHelpers, and to register helpers matched on predicates with registerGlobalHelper.
  • -
  • New theme pastel-on-dark.
  • -
  • Better ECMAScript 6 support in JavaScript mode.
  • -
  • Full list of patches.
  • -
- -

21-11-2013: Version 3.20:

- - - -

21-10-2013: Version 3.19:

- - - -

23-09-2013: Version 3.18:

- -

Emergency release to fix a problem in 3.17 - where .setOption("lineNumbers", false) would raise an - error.

- -

23-09-2013: Version 3.17:

- - - -

21-08-2013: Version 3.16:

- - - -

29-07-2013: Version 3.15:

- - - -

20-06-2013: Version 3.14:

- - - -

20-05-2013: Version 3.13:

- - - -

19-04-2013: Version 3.12:

- - - -

20-03-2013: Version 3.11:

- - - -

21-02-2013: Version 3.1:

- - - - -

25-01-2013: Version 3.02:

- -

Single-bugfix release. Fixes a problem that - prevents CodeMirror instances from being garbage-collected after - they become unused.

- -

21-01-2013: Version 3.01:

- - - -

10-12-2012: Version 3.0:

- -

New major version. Only - partially backwards-compatible. See - the upgrading guide for more - information. Changes since release candidate 2:

- -
    -
  • Rewritten VIM mode.
  • -
  • Fix a few minor scrolling and sizing issues.
  • -
  • Work around Safari segfault when dragging.
  • -
  • Full list of patches.
  • -
- -

20-11-2012: Version 3.0, release candidate 2:

- -
    -
  • New mode: HTTP.
  • -
  • Improved handling of selection anchor position.
  • -
  • Improve IE performance on longer lines.
  • -
  • Reduce gutter glitches during horiz. scrolling.
  • -
  • Add addKeyMap and removeKeyMap methods.
  • -
  • Rewrite formatting and closetag add-ons.
  • -
  • Full list of patches.
  • -
- -

20-11-2012: Version 3.0, release candidate 1:

- - - -

22-10-2012: Version 3.0, beta 2:

- -
    -
  • Fix page-based coordinate computation.
  • -
  • Fix firing of gutterClick event.
  • -
  • Add cursorHeight option.
  • -
  • Fix bi-directional text regression.
  • -
  • Add viewportMargin option.
  • -
  • Directly handle mousewheel events (again, hopefully better).
  • -
  • Make vertical cursor movement more robust (through widgets, big line gaps).
  • -
  • Add flattenSpans option.
  • -
  • Many optimizations. Poor responsiveness should be fixed.
  • -
  • Initialization in hidden state works again.
  • -
  • Full list of patches.
  • -
- -

19-09-2012: Version 3.0, beta 1:

- -
    -
  • Bi-directional text support.
  • -
  • More powerful gutter model.
  • -
  • Support for arbitrary text/widget height.
  • -
  • In-line widgets.
  • -
  • Generalized event handling.
  • -
- -
- -
- -

Version 2.x

- -

21-01-2013: Version 2.38:

- -

Integrate some bugfixes, enhancements to the vim keymap, and new - modes - (D, Sass, APL) - from the v3 branch.

- -

20-12-2012: Version 2.37:

- -
    -
  • New mode: SQL (will replace plsql and mysql modes).
  • -
  • Further work on the new VIM mode.
  • -
  • Fix Cmd/Ctrl keys on recent Operas on OS X.
  • -
  • Full list of patches.
  • -
- -

20-11-2012: Version 2.36:

- - - -

22-10-2012: Version 2.35:

- -
    -
  • New (sub) mode: TypeScript.
  • -
  • Don't overwrite (insert key) when pasting.
  • -
  • Fix several bugs in markText/undo interaction.
  • -
  • Better indentation of JavaScript code without semicolons.
  • -
  • Add defineInitHook function.
  • -
  • Full list of patches.
  • -
- -

19-09-2012: Version 2.34:

- -
    -
  • New mode: Common Lisp.
  • -
  • Fix right-click select-all on most browsers.
  • -
  • Change the way highlighting happens:
      Saves memory and CPU cycles.
      compareStates is no longer needed.
      onHighlightComplete no longer works.
  • -
  • Integrate mode (Markdown, XQuery, CSS, sTex) tests in central testsuite.
  • -
  • Add a CodeMirror.version property.
  • -
  • More robust handling of nested modes in formatting and closetag plug-ins.
  • -
  • Un/redo now preserves marked text and bookmarks.
  • -
  • Full list of patches.
  • -
- -

23-08-2012: Version 2.33:

- -
    -
  • New mode: Sieve.
  • -
  • New getViewPort and onViewportChange API.
  • -
  • Configurable cursor blink rate.
  • -
  • Make binding a key to false disabling handling (again).
  • -
  • Show non-printing characters as red dots.
  • -
  • More tweaks to the scrolling model.
  • -
  • Expanded testsuite. Basic linter added.
  • -
  • Remove most uses of innerHTML. Remove CodeMirror.htmlEscape.
  • -
  • Full list of patches.
  • -
- -

23-07-2012: Version 2.32:

- -

Emergency fix for a bug where an editor with - line wrapping on IE will break when there is no - scrollbar.

- -

20-07-2012: Version 2.31:

- - - -

22-06-2012: Version 2.3:

- -
    -
  • New scrollbar implementation. Should flicker less. Changes DOM structure of the editor.
  • -
  • New theme: vibrant-ink.
  • -
  • Many extensions to the VIM keymap (including text objects).
  • -
  • Add mode-multiplexing utility script.
  • -
  • Fix bug where right-click paste works in read-only mode.
  • -
  • Add a getScrollInfo method.
  • -
  • Lots of other fixes.
  • -
- -

23-05-2012: Version 2.25:

- -
    -
  • New mode: Erlang.
  • -
  • Remove xmlpure mode (use xml.js).
  • -
  • Fix line-wrapping in Opera.
  • -
  • Fix X Windows middle-click paste in Chrome.
  • -
  • Fix bug that broke pasting of huge documents.
  • -
  • Fix backspace and tab key repeat in Opera.
  • -
- -

23-04-2012: Version 2.24:

- -
    -
  • Drop support for Internet Explorer 6.
  • -
  • New - modes: Shell, Tiki - wiki, Pig Latin.
  • -
  • New themes: Ambiance, Blackboard.
  • -
  • More control over drag/drop - with dragDrop - and onDragEvent - options.
  • -
  • Make HTML mode a bit less pedantic.
  • -
  • Add compoundChange API method.
  • -
  • Several fixes in undo history and line hiding.
  • -
  • Remove (broken) support for catchall in key maps, - add nofallthrough boolean field instead.
  • -
- -

26-03-2012: Version 2.23:

- -
    -
  • Change default binding for tab [more] - -
  • -
  • New modes: XQuery and VBScript.
  • -
  • Two new themes: lesser-dark and xq-dark.
  • -
  • Differentiate between background and text styles in setLineClass.
  • -
  • Fix drag-and-drop in IE9+.
  • -
  • Extend charCoords - and cursorCoords with a mode argument.
  • -
  • Add autofocus option.
  • -
  • Add findMarksAt method.
  • -
- -

27-02-2012: Version 2.22:

- - - -

27-01-2012: Version 2.21:

- -
    -
  • Added LESS, MySQL, - Go, and Verilog modes.
  • -
  • Add smartIndent - option.
  • -
  • Support a cursor in readOnly-mode.
  • -
  • Support assigning multiple styles to a token.
  • -
  • Use a new approach to drawing the selection.
  • -
  • Add scrollTo method.
  • -
  • Allow undo/redo events to span non-adjacent lines.
  • -
  • Lots and lots of bugfixes.
  • -
- -

20-12-2011: Version 2.2:

- - - -

21-11-2011: Version 2.18:

-

Fixes TextMarker.clear, which is broken in 2.17.

- -

21-11-2011: Version 2.17:

-
    -
  • Add support for line - wrapping and code - folding.
  • -
  • Add Github-style Markdown mode.
  • -
  • Add Monokai - and Rubyblue themes.
  • -
  • Add setBookmark method.
  • -
  • Move some of the demo code into reusable components - under lib/util.
  • -
  • Make screen-coord-finding code faster and more reliable.
  • -
  • Fix drag-and-drop in Firefox.
  • -
  • Improve support for IME.
  • -
  • Speed up content rendering.
  • -
  • Fix browser's built-in search in Webkit.
  • -
  • Make double- and triple-click work in IE.
  • -
  • Various fixes to modes.
  • -
- -

27-10-2011: Version 2.16:

-
    -
  • Add Perl, Rust, TiddlyWiki, and Groovy modes.
  • -
  • Dragging text inside the editor now moves, rather than copies.
  • -
  • Add a coordsFromIndex method.
  • -
  • API change: setValue now no longer clears history. Use clearHistory for that.
  • -
  • API change: markText now - returns an object with clear and find - methods. Marked text is now more robust when edited.
  • -
  • Fix editing code with tabs in Internet Explorer.
  • -
- -

26-09-2011: Version 2.15:

-

Fix bug that snuck into 2.14: Clicking the - character that currently has the cursor didn't re-focus the - editor.

- -

26-09-2011: Version 2.14:

- - - -

23-08-2011: Version 2.13:

- - -

25-07-2011: Version 2.12:

-
    -
  • Add a SPARQL mode.
  • -
  • Fix bug with cursor jumping around in an unfocused editor in IE.
  • -
  • Allow key and mouse events to bubble out of the editor. Ignore widget clicks.
  • -
  • Solve cursor flakiness after undo/redo.
  • -
  • Fix block-reindent ignoring the last few lines.
  • -
  • Fix parsing of multi-line attrs in XML mode.
  • -
  • Use innerHTML for HTML-escaping.
  • -
  • Some fixes to indentation in C-like mode.
  • -
  • Shrink horiz scrollbars when long lines removed.
  • -
  • Fix width feedback loop bug that caused the width of an inner DIV to shrink.
  • -
- -

04-07-2011: Version 2.11:

-
    -
  • Add a Scheme mode.
  • -
  • Add a replace method to search cursors, for cursor-preserving replacements.
  • -
  • Make the C-like mode mode more customizable.
  • -
  • Update XML mode to spot mismatched tags.
  • -
  • Add getStateAfter API and compareState mode API methods for finer-grained mode magic.
  • -
  • Add a getScrollerElement API method to manipulate the scrolling DIV.
  • -
  • Fix drag-and-drop for Firefox.
  • -
  • Add a C# configuration for the C-like mode.
  • -
  • Add full-screen editing and mode-changing demos.
  • -
- -

07-06-2011: Version 2.1:

-

Add - a theme system - (demo). Note that this is not - backwards-compatible—you'll have to update your styles and - modes!

- -

07-06-2011: Version 2.02:

-
    -
  • Add a Lua mode.
  • -
  • Fix reverse-searching for a regexp.
  • -
  • Empty lines can no longer break highlighting.
  • -
  • Rework scrolling model (the outer wrapper no longer does the scrolling).
  • -
  • Solve horizontal jittering on long lines.
  • -
  • Add runmode.js.
  • -
  • Immediately re-highlight text when typing.
  • -
  • Fix problem with 'sticking' horizontal scrollbar.
  • -
- -

26-05-2011: Version 2.01:

-
    -
  • Add a Smalltalk mode.
  • -
  • Add a reStructuredText mode.
  • -
  • Add a Python mode.
  • -
  • Add a PL/SQL mode.
  • -
  • coordsChar now works
  • -
  • Fix a problem where onCursorActivity interfered with onChange.
  • -
  • Fix a number of scrolling and mouse-click-position glitches.
  • -
  • Pass information about the changed lines to onChange.
  • -
  • Support cmd-up/down on OS X.
  • -
  • Add triple-click line selection.
  • -
  • Don't handle shift when changing the selection through the API.
  • -
  • Support "nocursor" mode for readOnly option.
  • -
  • Add an onHighlightComplete option.
  • -
  • Fix the context menu for Firefox.
  • -
- -

28-03-2011: Version 2.0:

-

CodeMirror 2 is a complete rewrite that's - faster, smaller, simpler to use, and less dependent on browser - quirks. See this - and this - for more information.

- -

22-02-2011: Version 2.0 beta 2:

-

Somewhat more mature API, lots of bugs shaken out.

- -

17-02-2011: Version 0.94:

-
    -
  • tabMode: "spaces" was modified slightly (now indents when something is selected).
  • -
  • Fixes a bug that would cause the selection code to break on some IE versions.
  • -
  • Disabling spell-check on WebKit browsers now works.
  • -
- -

08-02-2011: Version 2.0 beta 1:

-

CodeMirror 2 is a complete rewrite of - CodeMirror, no longer depending on an editable frame.

- -

19-01-2011: Version 0.93:

-
    -
  • Added a Regular Expression parser.
  • -
  • Fixes to the PHP parser.
  • -
  • Support for regular expression in search/replace.
  • -
  • Add save method to instances created with fromTextArea.
  • -
  • Add support for MS T-SQL in the SQL parser.
  • -
  • Support use of CSS classes for highlighting brackets.
  • -
  • Fix yet another hang with line-numbering in hidden editors.
  • -
-
- -
- -

Version 0.x

- -

28-03-2011: Version 1.0:

-
    -
  • Fix error when debug history overflows.
  • -
  • Refine handling of C# verbatim strings.
  • -
  • Fix some issues with JavaScript indentation.
  • -
- -

17-12-2010: Version 0.92:

-
    -
  • Make CodeMirror work in XHTML documents.
  • -
  • Fix bug in handling of backslashes in Python strings.
  • -
  • The styleNumbers option is now officially - supported and documented.
  • -
  • onLineNumberClick option added.
  • -
  • More consistent names onLoad and - onCursorActivity callbacks. Old names still work, but - are deprecated.
  • -
  • Add a Freemarker mode.
  • -
- -

11-11-2010: Version 0.91:

-
    -
  • Adds support for Java.
  • -
  • Small additions to the PHP and SQL parsers.
  • -
  • Work around various Webkit issues.
  • -
  • Fix toTextArea to update the code in the textarea.
  • -
  • Add a noScriptCaching option (hack to ease development).
  • -
  • Make sub-modes of HTML mixed mode configurable.
  • -
- -

02-10-2010: Version 0.9:

-
    -
  • Add support for searching backwards.
  • -
  • There are now parsers for Scheme, XQuery, and OmetaJS.
  • -
  • Makes height: "dynamic" more robust.
  • -
  • Fixes bug where paste did not work on OS X.
  • -
  • Add a enterMode and electricChars options to make indentation even more customizable.
  • -
  • Add firstLineNumber option.
  • -
  • Fix bad handling of @media rules by the CSS parser.
  • -
  • Take a new, more robust approach to working around the invisible-last-line bug in WebKit.
  • -
- -

22-07-2010: Version 0.8:

-
    -
  • Add a cursorCoords method to find the screen - coordinates of the cursor.
  • -
  • A number of fixes and support for more syntax in the PHP parser.
  • -
  • Fix indentation problem with JSON-mode JS parser in Webkit.
  • -
  • Add a minification UI.
  • -
  • Support a height: dynamic mode, where the editor's - height will adjust to the size of its content.
  • -
  • Better support for IME input mode.
  • -
  • Fix JavaScript parser getting confused when seeing a no-argument - function call.
  • -
  • Have CSS parser see the difference between selectors and other - identifiers.
  • -
  • Fix scrolling bug when pasting in a horizontally-scrolled - editor.
  • -
  • Support toTextArea method in instances created with - fromTextArea.
  • -
  • Work around new Opera cursor bug that causes the cursor to jump - when pressing backspace at the end of a line.
  • -
- -

27-04-2010: Version - 0.67:

-

More consistent page-up/page-down behaviour - across browsers. Fix some issues with hidden editors looping forever - when line-numbers were enabled. Make PHP parser parse - "\\" correctly. Have jumpToLine work on - line handles, and add cursorLine function to fetch the - line handle where the cursor currently is. Add new - setStylesheet function to switch style-sheets in a - running editor.

- -

01-03-2010: Version - 0.66:

-

Adds removeLine method to API. - Introduces the PLSQL parser. - Marks XML errors by adding (rather than replacing) a CSS class, so - that they can be disabled by modifying their style. Fixes several - selection bugs, and a number of small glitches.

- -

12-11-2009: Version - 0.65:

-

Add support for having both line-wrapping and - line-numbers turned on, make paren-highlighting style customisable - (markParen and unmarkParen config - options), work around a selection bug that Opera - reintroduced in version 10.

- -

23-10-2009: Version - 0.64:

-

Solves some issues introduced by the - paste-handling changes from the previous release. Adds - setSpellcheck, setTextWrapping, - setIndentUnit, setUndoDepth, - setTabMode, and setLineNumbers to - customise a running editor. Introduces an SQL parser. Fixes a few small - problems in the Python - parser. And, as usual, add workarounds for various newly discovered - browser incompatibilities.

- -

31-08-2009: Version 0.63:

-

Overhaul of paste-handling (less fragile), fixes for several - serious IE8 issues (cursor jumping, end-of-document bugs) and a number - of small problems.

- -

30-05-2009: Version 0.62:

-

Introduces Python - and Lua parsers. Add - setParser (on-the-fly mode changing) and - clearHistory methods. Make parsing passes time-based - instead of lines-based (see the passTime option).

- -
-
diff --git a/shared/html/libs/codemirror/5.0.0/doc/reporting.html b/shared/html/libs/codemirror/5.0.0/doc/reporting.html deleted file mode 100644 index 3c582d9..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/reporting.html +++ /dev/null @@ -1,61 +0,0 @@ - - -CodeMirror: Reporting Bugs - - - - - -
- -

Reporting bugs effectively

- -
- -

So you found a problem in CodeMirror. By all means, report it! Bug -reports from users are the main drive behind improvements to -CodeMirror. But first, please read over these points:

- -
    -
  1. CodeMirror is maintained by volunteers. They don't owe you - anything, so be polite. Reports with an indignant or belligerent - tone tend to be moved to the bottom of the pile.
  2. - -
  3. Include information about the browser in which the - problem occurred. Even if you tested several browsers, and - the problem occurred in all of them, mention this fact in the bug - report. Also include browser version numbers and the operating - system that you're on.
  4. - -
  5. Mention which release of CodeMirror you're using. Preferably, - try also with the current development snapshot, to ensure the - problem has not already been fixed.
  6. - -
  7. Mention very precisely what went wrong. "X is broken" is not a - good bug report. What did you expect to happen? What happened - instead? Describe the exact steps a maintainer has to take to make - the problem occur. We can not fix something that we can not - observe.
  8. - -
  9. If the problem can not be reproduced in any of the demos - included in the CodeMirror distribution, please provide an HTML - document that demonstrates the problem. The best way to do this is - to go to jsbin.com, enter - it there, press save, and include the resulting link in your bug - report.
  10. -
- -
- -
diff --git a/shared/html/libs/codemirror/5.0.0/doc/upgrade_v2.2.html b/shared/html/libs/codemirror/5.0.0/doc/upgrade_v2.2.html deleted file mode 100644 index 3948ce6..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/upgrade_v2.2.html +++ /dev/null @@ -1,96 +0,0 @@ - - -CodeMirror: Version 2.2 upgrade guide - - - - - -
- -

Upgrading to v2.2

- -

There are a few things in the 2.2 release that require some care -when upgrading.

- -

No more default.css

- -

The default theme is now included -in codemirror.css, so -you do not have to included it separately anymore. (It was tiny, so -even if you're not using it, the extra data overhead is negligible.) - -

Different key customization

- -

CodeMirror has moved to a system -where keymaps are used to -bind behavior to keys. This means custom -bindings are now possible.

- -

Three options that influenced key -behavior, tabMode, enterMode, -and smartHome, are no longer supported. Instead, you can -provide custom bindings to influence the way these keys act. This is -done through the -new extraKeys -option, which can hold an object mapping key names to functionality. A -simple example would be:

- -
  extraKeys: {
-    "Ctrl-S": function(instance) { saveText(instance.getValue()); },
-    "Ctrl-/": "undo"
-  }
- -

Keys can be mapped either to functions, which will be given the -editor instance as argument, or to strings, which are mapped through -functions through the CodeMirror.commands table, which -contains all the built-in editing commands, and can be inspected and -extended by external code.

- -

By default, the Home key is bound to -the "goLineStartSmart" command, which moves the cursor to -the first non-whitespace character on the line. You can set do this to -make it always go to the very start instead:

- -
  extraKeys: {"Home": "goLineStart"}
- -

Similarly, Enter is bound -to "newlineAndIndent" by default. You can bind it to -something else to get different behavior. To disable special handling -completely and only get a newline character inserted, you can bind it -to false:

- -
  extraKeys: {"Enter": false}
- -

The same works for Tab. If you don't want CodeMirror -to handle it, bind it to false. The default behaviour is -to indent the current line more ("indentMore" command), -and indent it less when shift is held ("indentLess"). -There are also "indentAuto" (smart indent) -and "insertTab" commands provided for alternate -behaviors. Or you can write your own handler function to do something -different altogether.

- -

Tabs

- -

Handling of tabs changed completely. The display width of tabs can -now be set with the tabSize option, and tabs can -be styled by setting CSS rules -for the cm-tab class.

- -

The default width for tabs is now 4, as opposed to the 8 that is -hard-wired into browsers. If you are relying on 8-space tabs, make -sure you explicitly set tabSize: 8 in your options.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/doc/upgrade_v3.html b/shared/html/libs/codemirror/5.0.0/doc/upgrade_v3.html deleted file mode 100644 index 5f94067..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/upgrade_v3.html +++ /dev/null @@ -1,230 +0,0 @@ - - -CodeMirror: Version 3 upgrade guide - - - - - - - - - - - - - - -
- -

Upgrading to version 3

- -

Version 3 does not depart too much from 2.x API, and sites that use -CodeMirror in a very simple way might be able to upgrade without -trouble. But it does introduce a number of incompatibilities. Please -at least skim this text before upgrading.

- -

Note that version 3 drops full support for Internet -Explorer 7. The editor will mostly work on that browser, but -it'll be significantly glitchy.

- -
-

DOM structure

- -

This one is the most likely to cause problems. The internal -structure of the editor has changed quite a lot, mostly to implement a -new scrolling model.

- -

Editor height is now set on the outer wrapper element (CSS -class CodeMirror), not on the scroller element -(CodeMirror-scroll).

- -

Other nodes were moved, dropped, and added. If you have any code -that makes assumptions about the internal DOM structure of the editor, -you'll have to re-test it and probably update it to work with v3.

- -

See the styling section of the -manual for more information.

-
-
-

Gutter model

- -

In CodeMirror 2.x, there was a single gutter, and line markers -created with setMarker would have to somehow coexist with -the line numbers (if present). Version 3 allows you to specify an -array of gutters, by class -name, -use setGutterMarker -to add or remove markers in individual gutters, and clear whole -gutters -with clearGutter. -Gutter markers are now specified as DOM nodes, rather than HTML -snippets.

- -

The gutters no longer horizontally scrolls along with the content. -The fixedGutter option was removed (since it is now the -only behavior).

- -
-<style>
-  /* Define a gutter style */
-  .note-gutter { width: 3em; background: cyan; }
-</style>
-<script>
-  // Create an instance with two gutters -- line numbers and notes
-  var cm = new CodeMirror(document.body, {
-    gutters: ["note-gutter", "CodeMirror-linenumbers"],
-    lineNumbers: true
-  });
-  // Add a note to line 0
-  cm.setGutterMarker(0, "note-gutter", document.createTextNode("hi"));
-</script>
-
-
-
-

Event handling

- -

Most of the onXYZ options have been removed. The same -effect is now obtained by calling -the on method with a string -identifying the event type. Multiple handlers can now be registered -(and individually unregistered) for an event, and objects such as line -handlers now also expose events. See the -full list here.

- -

(The onKeyEvent and onDragEvent options, -which act more as hooks than as event handlers, are still there in -their old form.)

- -
-cm.on("change", function(cm, change) {
-  console.log("something changed! (" + change.origin + ")");
-});
-
-
-
-

markText method arguments

- -

The markText method -(which has gained some interesting new features, such as creating -atomic and read-only spans, or replacing spans with widgets) no longer -takes the CSS class name as a separate argument, but makes it an -optional field in the options object instead.

- -
-// Style first ten lines, and forbid the cursor from entering them
-cm.markText({line: 0, ch: 0}, {line: 10, ch: 0}, {
-  className: "magic-text",
-  inclusiveLeft: true,
-  atomic: true
-});
-
-
-
-

Line folding

- -

The interface for hiding lines has been -removed. markText can -now be used to do the same in a more flexible and powerful way.

- -

The folding script has been -updated to use the new interface, and should now be more robust.

- -
-// Fold a range, replacing it with the text "??"
-var range = cm.markText({line: 4, ch: 2}, {line: 8, ch: 1}, {
-  replacedWith: document.createTextNode("??"),
-  // Auto-unfold when cursor moves into the range
-  clearOnEnter: true
-});
-// Get notified when auto-unfolding
-CodeMirror.on(range, "clear", function() {
-  console.log("boom");
-});
-
-
-
-

Line CSS classes

- -

The setLineClass method has been replaced -by addLineClass -and removeLineClass, -which allow more modular control over the classes attached to a line.

- -
-var marked = cm.addLineClass(10, "background", "highlighted-line");
-setTimeout(function() {
-  cm.removeLineClass(marked, "background", "highlighted-line");
-});
-
-
-
-

Position properties

- -

All methods that take or return objects that represent screen -positions now use {left, top, bottom, right} properties -(not always all of them) instead of the {x, y, yBot} used -by some methods in v2.x.

- -

Affected methods -are cursorCoords, charCoords, coordsChar, -and getScrollInfo.

-
-
-

Bracket matching no longer in core

- -

The matchBrackets -option is no longer defined in the core editor. -Load addon/edit/matchbrackets.js to enable it.

-
-
-

Mode management

- -

The CodeMirror.listModes -and CodeMirror.listMIMEs functions, used for listing -defined modes, are gone. You are now encouraged to simply -inspect CodeMirror.modes (mapping mode names to mode -constructors) and CodeMirror.mimeModes (mapping MIME -strings to mode specs).

-
-
-

New features

- -

Some more reasons to upgrade to version 3.

- -
    -
  • Bi-directional text support. CodeMirror will now mostly do the - right thing when editing Arabic or Hebrew text.
  • -
  • Arbitrary line heights. Using fonts with different heights - inside the editor (whether off by one pixel or fifty) is now - supported and handled gracefully.
  • -
  • In-line widgets. See the demo - and the docs.
  • -
  • Defining custom options - with CodeMirror.defineOption.
  • -
-
-
- - diff --git a/shared/html/libs/codemirror/5.0.0/doc/upgrade_v4.html b/shared/html/libs/codemirror/5.0.0/doc/upgrade_v4.html deleted file mode 100644 index 09df00c..0000000 --- a/shared/html/libs/codemirror/5.0.0/doc/upgrade_v4.html +++ /dev/null @@ -1,144 +0,0 @@ - - -CodeMirror: Version 4 upgrade guide - - - - - - -
- -

Upgrading to version 4

- -

CodeMirror 4's interface is very close version 3, but it -does fix a few awkward details in a backwards-incompatible ways. At -least skim the text below before upgrading.

- -

Multiple selections

- -

The main new feature in version 4 is multiple selections. The -single-selection variants of methods are still there, but now -typically act only on the primary selection (usually the last -one added).

- -

The exception to this -is getSelection, -which will now return the content of all selections -(separated by newlines, or whatever lineSep parameter you passed -it).

- -
- -

The beforeSelectionChange event

- -

This event still exists, but the object it is passed has -a completely new -interface, because such changes now concern multiple -selections.

- -
- -

replaceSelection's collapsing behavior

- -

By -default, replaceSelection -would leave the newly inserted text selected. This is only rarely what -you want, and also (slightly) more expensive in the new model, so the -default was changed to "end", meaning the old behavior -must be explicitly specified by passing a second argument -of "around".

- -
- -

change event data

- -

Rather than forcing client code to follow next -pointers from one change object to the next, the library will now -simply fire -multiple "change" -events. Existing code will probably continue to work unmodified.

- -
- -

showIfHidden option to line widgets

- -

This option, which conceptually caused line widgets to be visible -even if their line was hidden, was never really well-defined, and was -buggy from the start. It would be a rather expensive feature, both in -code complexity and run-time performance, to implement properly. It -has been dropped entirely in 4.0.

- -
- -

Module loaders

- -

All modules in the CodeMirror distribution are now wrapped in a -shim function to make them compatible with both AMD -(requirejs) and CommonJS (as used -by node -and browserify) module loaders. -When neither of these is present, they fall back to simply using the -global CodeMirror variable.

- -

If you have a module loader present in your environment, CodeMirror -will attempt to use it, and you might need to change the way you load -CodeMirror modules.

- -
- -

Mutating shared data structures

- -

Data structures produced by the library should not be mutated -unless explicitly allowed, in general. This is slightly more strict in -4.0 than it was in earlier versions, which copied the position objects -returned by getCursor -for nebulous, historic reasons. In 4.0, mutating these -objects will corrupt your editor's selection.

- -
- -

Deprecated interfaces dropped

- -

A few properties and methods that have been deprecated for a while -are now gone. Most notably, the onKeyEvent -and onDragEvent options (use the -corresponding events instead).

- -

Two silly methods, which were mostly there to stay close to the 0.x -API, setLine and removeLine are now gone. -Use the more -flexible replaceRange -method instead.

- -

The long names for folding and completing functions -(CodeMirror.braceRangeFinder, CodeMirror.javascriptHint, -etc) are also gone -(use CodeMirror.fold.brace, CodeMirror.hint.javascript).

- -

The className property in the return value -of getTokenAt, which -has been superseded by the type property, is also no -longer present.

- -
-
diff --git a/shared/html/libs/codemirror/5.0.0/doc/yinyang.png b/shared/html/libs/codemirror/5.0.0/doc/yinyang.png deleted file mode 100644 index 2eafd3f1ca137898ede8c27d0e64d99919bdc1ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4633 zcmV+!66WoRP)02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{01<&nL_t(|+U=cPY#Y~=$Nxhy zV#HV?X-TGS*&^w9;jhFRrrmgx#ahFz1vCy?kuL#aq!!t?6h%Z81?uLZB43geHDU@V z+Mp;vst;|SN~%ad0C~-k)9hlmSaX=zPPDc)WGqXTMTJAjrb?Oe-3N*cW$Tk1&I~CX zfUqS?^p$>dKJU5bQiKrHlFYFz0f02eVNnnYpU(;c7Gg1IX}a*adb1fCv$^nbBg0Ur zF`=pzaE9keIvT}1$05D+nvTcOcJd?uKugo8)9VXguh#2PZ#E;%afQz<#A3+AVug?I zT)vD}lL=ayhL)z$$S`Q==;%@#3>UWnOCae;gd_$BF~_o)9vj1Ms}+q511(KMV>Ux; zwTkiJV2))A4^1)jMuvgDyBivdh1v!zk|aYRB7{O14+gQ*Y=+)$hrwdXeFI?DcrCgJCeg6hO_fEbc`jSeTt%_4{{s zbQA)kyswm6vdJW70s&0ER} z6HG1_T6%gU_0>fWEG9f2EX3n5`~7IL*{CfAIK%T~!s|u+4}ZXscizEbB7s{MF084g zrAn*G1f$!XkA5Ww9dkONu~@LDzh4&6k^`Rd`N*|%=U`}RLW|3V*asg}1nf#${cK+! z_If;$KhO!k9}^xA8f`Z0zi>g)yjn8A8J;J%91cv~xPeFMv}|sn)nv+>P04-ql+TAT zpAXLk0x&onRLuaM@Oa4RyYJ%B!h&M5hXXx5*ni;y)CPkrW?S!YU~hka#kE;g;ivZ0 zXJ7w18U5MMkW~;|02mt_#Hh`NY%(e7|J!7<;V8!egy6c>I-HI~NL6ZZIuarO{qoDX zd@PeuY^7&+M+Yo^ziiR=mF{jlH!y$}my4o>KKu}ib91OBkrQ$@nZzi=Kx?(a5(tP2S+xx}CkwN);9V}s zeKG*34F()yS%45+qiK>&CQm5}a5kAdHFo9rYb4vK1)f4+1{@;td%_?{ksqC_#*WdpwU{PU!i;O71D zOR<>bIdUZ+mt~^I&YY<^xOsnk+wGQh4VJ+{WOyFD(@A6je5b#keDUFjH3zrw@c!mE z$nde&R&@_y_y=Y_@)EB{Bh{Z6+vY7CCaj&SqS!^x- zw^T|I7UlEKPBbzM+Pq#$bim1AkbH9XEVB3SOZEdb=yZ5K6xvXa)l48zG0<}7#d*o_ zJpQYr1209R8}8uTkcrMFlczp;;|)pS?xAT|S$4w>bj?mDjz%KbQ*<;%ESY0jMQE_b zV!;uw7crMhTpxVf?H-0&Eh*eX;V>FD39C-8$H8C_4LV&-0tNtMUmpk|n7VLbL#B6K z6FnOalc?P;N#9gnUgkJ7baa&b{qr1$2*Y4rB;TndKfIL5;C~qgFLKu`t~O{XIf#Q@e?tvKLzZzxY!t*5<{pMDB5KQGzh#p-(0 z+wG#RE32@Iozd+^JQzfV=Sj(cW8e9Xq#clZXc{{@JH-Lq-7TswUZ_wSR;s8Ch7AQ= zs{&5={UjxEDNvrWAflPhC=75u;L7kkX2W5!X~2{3y(ej4wJoK)v`Mdba~eDw z4wJq29p5M~Ak%X*LdBO{{1-F^JH;{CAJYDJw+hh#8FRt22; z^Pgos+F7t7PABH0(bCL(G>T8UyG31(lFjq7yx8r2!o@8EJpJomD`v5g&dyCko*5j> zeV@o119Hs#D0Q9Vs{zjNJW1TSqnO3cr&9P&nnuj!!a_X0c6yacVbbf(X?_KEeZ;P7 zS4uP%3wD~#%Nq0wo4jI0uVTxsKmfM_0X*w;LT|T2t=FT0rZLZP$O;04PzV#jU`4sWwPJc~tgwx!0&+c9>FqM%ljhmski93mq_oazEmZMT0FdUmVM?RfCig&p{^;m7)gm#=5UqC z$O;0~3$YloTey3&818Dvc&MfG(ChuXB29E=3v?c?CWn9W6CC9@)amuP`wb{+#aA)N z)&4zyM}pEsy%oW>wzuOzFoO?;9r8GIx-;cxLuwHC+U!5<^C=##lzFlW05m&x z)CAn;d_J@|omI8wN(EkbE?-8I%|=m#5c~&4k!pv#k6~~q9Inc>iyd@jcpjq+gX8fy zl?$?JU_aRG_gC%O#WvM*MKOp90G>HjdUHP0OHGMlm2(KVli+|C$3wqiW%TG8xCWq*}QCq^s<(n_9_Zk#Gae6CVTX zHzAW8hg%{JJuOFsQ0R$L?J~fI*Iuide7I4hvBP<}X}4pt#P+4zEW4?D6e<;L2}46q zJow82I~8Gp0|B4wsFT`RP9~mj@J#Ga8qR%C4h)M6}~~@cA?pD7|!+-%`-}&>{3X^xLeaif# z*9+qsx0SC7xXEUt_LO-+RW(Sn$UR(AZhp*$!^rSFT3jw_(|`fM^uY&;OqtRmo~NqQ z>tPnDg14`;Q&JNhbGg$|{C?D%Oso3dysUdU zWrpX;$48DRZcv(-BlZ^s0iz6q$uj13?&;{jQ4uZ6TDwWvWD?h{R+#<%bpfw?K3HS1 zP{-bV7ixv2O=%H_r`GB9IK;BpWipjkcxh^aMZ)}d!s9_>XXmxc7@4~9ahZ))1K=AMW~CG)+r;V{Phe(d-8x;FCl8$RK02?U^0kT0%8-M4|JaUvSU zvm4yR-`ClRLo5ra&RA!YNyJ<(bPNs_dal+JYBM_)cl!Iu&GYAxRlvm^0MIE2P>X!q zcX0t^!sEdl%jQ~{mSmU7ghqye(e197)~@D%zgTJyZXX!f@MZzE*$%$XPMjbU9H)rh zt&TtdEfV!cEiN6$ltNYloD2qW+wI0tj_cZ}_Lc-Vn@pbiTU*=kq5`JlRkANjPI(+~ z{z~_+vFsE3y`uTxLZ!xFxcK77A1lHiPsd_Nh_uzGRJhq>5;q+V9P#-!4Ywq~`2xt% z_uhk60X@kRRXUY@qe0cE&4%Wlo;AynqMGPp8GHS8a{G^els)K@(icmqy}Z*25CY5K zV96aARJn(p#$JD&O#St*vi4JJbUOS?JYKPgS}M4}SIu_3(}{E>f@9HWS?x7tPr5ts zyWdg9Z+=r&bDc@05UaA2{VQtQV{i|#Y*)GODat6r_Fw#>tEsI`R><*C2vb!$%)8h$ z=gso5Xq4JaI#f}>YJ=h8p^rY29rBI-eo<@GQkv#$GKo=!Dck2(1aKbmv8z{QHP@L` z3cS;aY=!PItQ6dZSPY{!8|qCaQQ?XTxY#GRzx5W>GEMHe%W)WG7{x=*!xcgy{0~jT z*xM^QTv4Lv)gC>{9>`W?!E1jK+DQ6NwaBpA$f45q(qq7r-M@Fbh!mYRl7fUi2B%i$T26kw* zvS{-@hJiT{ki}#ZLXeI`F#dxdfDi&pAh6;ogsRivVlg-z)W438ckMiVdedDKV#qkl z;%{a%CM3L*Fq=x@_PKMo-Peb|GYs_I-8eilLP-TzQVlMa*>ITLId=|suU^F?8S2;? zoeu3T7mRLqMKn5_O5vW*htGfdQ&1FzwwGUq=~usklwf5ATnu{rhd;#KYu9A!+BDhi z&@a8psby!E4xUZoy(U2wOUr#E5Vfa0L^qQBBw3 - -CodeMirror - - - - - - - - - - - - - - - - - -
- -
-

CodeMirror is a versatile text editor - implemented in JavaScript for the browser. It is specialized for - editing code, and comes with a number of language modes and addons - that implement more advanced editing functionality.

- -

A rich programming API and a - CSS theming system are - available for customizing CodeMirror to fit your application, and - extending it with new functionality.

-
- -
-

This is CodeMirror

-
-
- - -
-
- - - -
-
- Get the current version: 5.0.
- You can see the code or
- read the release notes.
- There is a minification helper. -
-
- Software needs maintenance,
- maintainers need to subsist.
- Current funding status =
- You can help per month or - once. -
- - -
-
-
- -
- -
-

Features

- -
- -
-

Community

- -

CodeMirror is an open-source project shared under - an MIT license. It is the editor used in the - dev tools for - both Firefox - and Chrome, Light - Table, Adobe - Brackets, Bitbucket, - and many other projects.

- -

Development and bug tracking happens - on github - (alternate git - repository). - Please read these - pointers before submitting a bug. Use pull requests to submit - patches. All contributions must be released under the same MIT - license that CodeMirror uses.

- -

Discussion around the project is done on - a discussion forum. - There is also - the codemirror-announce - list, which is only used for major announcements (such as new - versions). If needed, you can - contact the maintainer - directly.

- -

A list of CodeMirror-related software that is not part of the - main distribution is maintained - on our - wiki. Feel free to add your project.

-
- -
-

Browser support

-

The desktop versions of the following browsers, - in standards mode (HTML5 <!doctype html> - recommended) are supported:

- - - - - - -
Firefoxversion 4 and up
Chromeany version
Safariversion 5.2 and up
Internet Explorerversion 8 and up
Operaversion 9 and up
-

Support for modern mobile browsers is experimental. Recent - versions of the iOS browser and Chrome on Android should work - pretty well.

-
- -
diff --git a/shared/html/libs/codemirror/5.0.0/keymap/emacs.js b/shared/html/libs/codemirror/5.0.0/keymap/emacs.js deleted file mode 100644 index c413523..0000000 --- a/shared/html/libs/codemirror/5.0.0/keymap/emacs.js +++ /dev/null @@ -1,412 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var Pos = CodeMirror.Pos; - function posEq(a, b) { return a.line == b.line && a.ch == b.ch; } - - // Kill 'ring' - - var killRing = []; - function addToRing(str) { - killRing.push(str); - if (killRing.length > 50) killRing.shift(); - } - function growRingTop(str) { - if (!killRing.length) return addToRing(str); - killRing[killRing.length - 1] += str; - } - function getFromRing(n) { return killRing[killRing.length - (n ? Math.min(n, 1) : 1)] || ""; } - function popFromRing() { if (killRing.length > 1) killRing.pop(); return getFromRing(); } - - var lastKill = null; - - function kill(cm, from, to, mayGrow, text) { - if (text == null) text = cm.getRange(from, to); - - if (mayGrow && lastKill && lastKill.cm == cm && posEq(from, lastKill.pos) && cm.isClean(lastKill.gen)) - growRingTop(text); - else - addToRing(text); - cm.replaceRange("", from, to, "+delete"); - - if (mayGrow) lastKill = {cm: cm, pos: from, gen: cm.changeGeneration()}; - else lastKill = null; - } - - // Boundaries of various units - - function byChar(cm, pos, dir) { - return cm.findPosH(pos, dir, "char", true); - } - - function byWord(cm, pos, dir) { - return cm.findPosH(pos, dir, "word", true); - } - - function byLine(cm, pos, dir) { - return cm.findPosV(pos, dir, "line", cm.doc.sel.goalColumn); - } - - function byPage(cm, pos, dir) { - return cm.findPosV(pos, dir, "page", cm.doc.sel.goalColumn); - } - - function byParagraph(cm, pos, dir) { - var no = pos.line, line = cm.getLine(no); - var sawText = /\S/.test(dir < 0 ? line.slice(0, pos.ch) : line.slice(pos.ch)); - var fst = cm.firstLine(), lst = cm.lastLine(); - for (;;) { - no += dir; - if (no < fst || no > lst) - return cm.clipPos(Pos(no - dir, dir < 0 ? 0 : null)); - line = cm.getLine(no); - var hasText = /\S/.test(line); - if (hasText) sawText = true; - else if (sawText) return Pos(no, 0); - } - } - - function bySentence(cm, pos, dir) { - var line = pos.line, ch = pos.ch; - var text = cm.getLine(pos.line), sawWord = false; - for (;;) { - var next = text.charAt(ch + (dir < 0 ? -1 : 0)); - if (!next) { // End/beginning of line reached - if (line == (dir < 0 ? cm.firstLine() : cm.lastLine())) return Pos(line, ch); - text = cm.getLine(line + dir); - if (!/\S/.test(text)) return Pos(line, ch); - line += dir; - ch = dir < 0 ? text.length : 0; - continue; - } - if (sawWord && /[!?.]/.test(next)) return Pos(line, ch + (dir > 0 ? 1 : 0)); - if (!sawWord) sawWord = /\w/.test(next); - ch += dir; - } - } - - function byExpr(cm, pos, dir) { - var wrap; - if (cm.findMatchingBracket && (wrap = cm.findMatchingBracket(pos, true)) - && wrap.match && (wrap.forward ? 1 : -1) == dir) - return dir > 0 ? Pos(wrap.to.line, wrap.to.ch + 1) : wrap.to; - - for (var first = true;; first = false) { - var token = cm.getTokenAt(pos); - var after = Pos(pos.line, dir < 0 ? token.start : token.end); - if (first && dir > 0 && token.end == pos.ch || !/\w/.test(token.string)) { - var newPos = cm.findPosH(after, dir, "char"); - if (posEq(after, newPos)) return pos; - else pos = newPos; - } else { - return after; - } - } - } - - // Prefixes (only crudely supported) - - function getPrefix(cm, precise) { - var digits = cm.state.emacsPrefix; - if (!digits) return precise ? null : 1; - clearPrefix(cm); - return digits == "-" ? -1 : Number(digits); - } - - function repeated(cmd) { - var f = typeof cmd == "string" ? function(cm) { cm.execCommand(cmd); } : cmd; - return function(cm) { - var prefix = getPrefix(cm); - f(cm); - for (var i = 1; i < prefix; ++i) f(cm); - }; - } - - function findEnd(cm, pos, by, dir) { - var prefix = getPrefix(cm); - if (prefix < 0) { dir = -dir; prefix = -prefix; } - for (var i = 0; i < prefix; ++i) { - var newPos = by(cm, pos, dir); - if (posEq(newPos, pos)) break; - pos = newPos; - } - return pos; - } - - function move(by, dir) { - var f = function(cm) { - cm.extendSelection(findEnd(cm, cm.getCursor(), by, dir)); - }; - f.motion = true; - return f; - } - - function killTo(cm, by, dir) { - var selections = cm.listSelections(), cursor; - var i = selections.length; - while (i--) { - cursor = selections[i].head; - kill(cm, cursor, findEnd(cm, cursor, by, dir), true); - } - } - - function killRegion(cm) { - if (cm.somethingSelected()) { - var selections = cm.listSelections(), selection; - var i = selections.length; - while (i--) { - selection = selections[i]; - kill(cm, selection.anchor, selection.head); - } - return true; - } - } - - function addPrefix(cm, digit) { - if (cm.state.emacsPrefix) { - if (digit != "-") cm.state.emacsPrefix += digit; - return; - } - // Not active yet - cm.state.emacsPrefix = digit; - cm.on("keyHandled", maybeClearPrefix); - cm.on("inputRead", maybeDuplicateInput); - } - - var prefixPreservingKeys = {"Alt-G": true, "Ctrl-X": true, "Ctrl-Q": true, "Ctrl-U": true}; - - function maybeClearPrefix(cm, arg) { - if (!cm.state.emacsPrefixMap && !prefixPreservingKeys.hasOwnProperty(arg)) - clearPrefix(cm); - } - - function clearPrefix(cm) { - cm.state.emacsPrefix = null; - cm.off("keyHandled", maybeClearPrefix); - cm.off("inputRead", maybeDuplicateInput); - } - - function maybeDuplicateInput(cm, event) { - var dup = getPrefix(cm); - if (dup > 1 && event.origin == "+input") { - var one = event.text.join("\n"), txt = ""; - for (var i = 1; i < dup; ++i) txt += one; - cm.replaceSelection(txt); - } - } - - function addPrefixMap(cm) { - cm.state.emacsPrefixMap = true; - cm.addKeyMap(prefixMap); - cm.on("keyHandled", maybeRemovePrefixMap); - cm.on("inputRead", maybeRemovePrefixMap); - } - - function maybeRemovePrefixMap(cm, arg) { - if (typeof arg == "string" && (/^\d$/.test(arg) || arg == "Ctrl-U")) return; - cm.removeKeyMap(prefixMap); - cm.state.emacsPrefixMap = false; - cm.off("keyHandled", maybeRemovePrefixMap); - cm.off("inputRead", maybeRemovePrefixMap); - } - - // Utilities - - function setMark(cm) { - cm.setCursor(cm.getCursor()); - cm.setExtending(!cm.getExtending()); - cm.on("change", function() { cm.setExtending(false); }); - } - - function clearMark(cm) { - cm.setExtending(false); - cm.setCursor(cm.getCursor()); - } - - function getInput(cm, msg, f) { - if (cm.openDialog) - cm.openDialog(msg + ": ", f, {bottom: true}); - else - f(prompt(msg, "")); - } - - function operateOnWord(cm, op) { - var start = cm.getCursor(), end = cm.findPosH(start, 1, "word"); - cm.replaceRange(op(cm.getRange(start, end)), start, end); - cm.setCursor(end); - } - - function toEnclosingExpr(cm) { - var pos = cm.getCursor(), line = pos.line, ch = pos.ch; - var stack = []; - while (line >= cm.firstLine()) { - var text = cm.getLine(line); - for (var i = ch == null ? text.length : ch; i > 0;) { - var ch = text.charAt(--i); - if (ch == ")") - stack.push("("); - else if (ch == "]") - stack.push("["); - else if (ch == "}") - stack.push("{"); - else if (/[\(\{\[]/.test(ch) && (!stack.length || stack.pop() != ch)) - return cm.extendSelection(Pos(line, i)); - } - --line; ch = null; - } - } - - function quit(cm) { - cm.execCommand("clearSearch"); - clearMark(cm); - } - - // Actual keymap - - var keyMap = CodeMirror.keyMap.emacs = CodeMirror.normalizeKeyMap({ - "Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"));}, - "Ctrl-K": repeated(function(cm) { - var start = cm.getCursor(), end = cm.clipPos(Pos(start.line)); - var text = cm.getRange(start, end); - if (!/\S/.test(text)) { - text += "\n"; - end = Pos(start.line + 1, 0); - } - kill(cm, start, end, true, text); - }), - "Alt-W": function(cm) { - addToRing(cm.getSelection()); - clearMark(cm); - }, - "Ctrl-Y": function(cm) { - var start = cm.getCursor(); - cm.replaceRange(getFromRing(getPrefix(cm)), start, start, "paste"); - cm.setSelection(start, cm.getCursor()); - }, - "Alt-Y": function(cm) {cm.replaceSelection(popFromRing(), "around", "paste");}, - - "Ctrl-Space": setMark, "Ctrl-Shift-2": setMark, - - "Ctrl-F": move(byChar, 1), "Ctrl-B": move(byChar, -1), - "Right": move(byChar, 1), "Left": move(byChar, -1), - "Ctrl-D": function(cm) { killTo(cm, byChar, 1); }, - "Delete": function(cm) { killRegion(cm) || killTo(cm, byChar, 1); }, - "Ctrl-H": function(cm) { killTo(cm, byChar, -1); }, - "Backspace": function(cm) { killRegion(cm) || killTo(cm, byChar, -1); }, - - "Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1), - "Alt-D": function(cm) { killTo(cm, byWord, 1); }, - "Alt-Backspace": function(cm) { killTo(cm, byWord, -1); }, - - "Ctrl-N": move(byLine, 1), "Ctrl-P": move(byLine, -1), - "Down": move(byLine, 1), "Up": move(byLine, -1), - "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", - "End": "goLineEnd", "Home": "goLineStart", - - "Alt-V": move(byPage, -1), "Ctrl-V": move(byPage, 1), - "PageUp": move(byPage, -1), "PageDown": move(byPage, 1), - - "Ctrl-Up": move(byParagraph, -1), "Ctrl-Down": move(byParagraph, 1), - - "Alt-A": move(bySentence, -1), "Alt-E": move(bySentence, 1), - "Alt-K": function(cm) { killTo(cm, bySentence, 1); }, - - "Ctrl-Alt-K": function(cm) { killTo(cm, byExpr, 1); }, - "Ctrl-Alt-Backspace": function(cm) { killTo(cm, byExpr, -1); }, - "Ctrl-Alt-F": move(byExpr, 1), "Ctrl-Alt-B": move(byExpr, -1), - - "Shift-Ctrl-Alt-2": function(cm) { - var cursor = cm.getCursor(); - cm.setSelection(findEnd(cm, cursor, byExpr, 1), cursor); - }, - "Ctrl-Alt-T": function(cm) { - var leftStart = byExpr(cm, cm.getCursor(), -1), leftEnd = byExpr(cm, leftStart, 1); - var rightEnd = byExpr(cm, leftEnd, 1), rightStart = byExpr(cm, rightEnd, -1); - cm.replaceRange(cm.getRange(rightStart, rightEnd) + cm.getRange(leftEnd, rightStart) + - cm.getRange(leftStart, leftEnd), leftStart, rightEnd); - }, - "Ctrl-Alt-U": repeated(toEnclosingExpr), - - "Alt-Space": function(cm) { - var pos = cm.getCursor(), from = pos.ch, to = pos.ch, text = cm.getLine(pos.line); - while (from && /\s/.test(text.charAt(from - 1))) --from; - while (to < text.length && /\s/.test(text.charAt(to))) ++to; - cm.replaceRange(" ", Pos(pos.line, from), Pos(pos.line, to)); - }, - "Ctrl-O": repeated(function(cm) { cm.replaceSelection("\n", "start"); }), - "Ctrl-T": repeated(function(cm) { - cm.execCommand("transposeChars"); - }), - - "Alt-C": repeated(function(cm) { - operateOnWord(cm, function(w) { - var letter = w.search(/\w/); - if (letter == -1) return w; - return w.slice(0, letter) + w.charAt(letter).toUpperCase() + w.slice(letter + 1).toLowerCase(); - }); - }), - "Alt-U": repeated(function(cm) { - operateOnWord(cm, function(w) { return w.toUpperCase(); }); - }), - "Alt-L": repeated(function(cm) { - operateOnWord(cm, function(w) { return w.toLowerCase(); }); - }), - - "Alt-;": "toggleComment", - - "Ctrl-/": repeated("undo"), "Shift-Ctrl--": repeated("undo"), - "Ctrl-Z": repeated("undo"), "Cmd-Z": repeated("undo"), - "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd", - "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace", - "Alt-/": "autocomplete", - "Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto", - - "Alt-G G": function(cm) { - var prefix = getPrefix(cm, true); - if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1); - - getInput(cm, "Goto line", function(str) { - var num; - if (str && !isNaN(num = Number(str)) && num == num|0 && num > 0) - cm.setCursor(num - 1); - }); - }, - - "Ctrl-X Tab": function(cm) { - cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit")); - }, - "Ctrl-X Ctrl-X": function(cm) { - cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor")); - }, - "Ctrl-X Ctrl-S": "save", - "Ctrl-X Ctrl-W": "save", - "Ctrl-X S": "saveAll", - "Ctrl-X F": "open", - "Ctrl-X U": repeated("undo"), - "Ctrl-X K": "close", - "Ctrl-X Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); }, - "Ctrl-X H": "selectAll", - - "Ctrl-Q Tab": repeated("insertTab"), - "Ctrl-U": addPrefixMap - }); - - var prefixMap = {"Ctrl-G": clearPrefix}; - function regPrefix(d) { - prefixMap[d] = function(cm) { addPrefix(cm, d); }; - keyMap["Ctrl-" + d] = function(cm) { addPrefix(cm, d); }; - prefixPreservingKeys["Ctrl-" + d] = true; - } - for (var i = 0; i < 10; ++i) regPrefix(String(i)); - regPrefix("-"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/keymap/sublime.js b/shared/html/libs/codemirror/5.0.0/keymap/sublime.js deleted file mode 100644 index 45936c3..0000000 --- a/shared/html/libs/codemirror/5.0.0/keymap/sublime.js +++ /dev/null @@ -1,540 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// A rough approximation of Sublime Text's keybindings -// Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/edit/matchbrackets")); - else if (typeof define == "function" && define.amd) // AMD - define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/edit/matchbrackets"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var map = CodeMirror.keyMap.sublime = {fallthrough: "default"}; - var cmds = CodeMirror.commands; - var Pos = CodeMirror.Pos; - var mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault; - var ctrl = mac ? "Cmd-" : "Ctrl-"; - - // This is not exactly Sublime's algorithm. I couldn't make heads or tails of that. - function findPosSubword(doc, start, dir) { - if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1)); - var line = doc.getLine(start.line); - if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0)); - var state = "start", type; - for (var pos = start.ch, e = dir < 0 ? 0 : line.length, i = 0; pos != e; pos += dir, i++) { - var next = line.charAt(dir < 0 ? pos - 1 : pos); - var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o"; - if (cat == "w" && next.toUpperCase() == next) cat = "W"; - if (state == "start") { - if (cat != "o") { state = "in"; type = cat; } - } else if (state == "in") { - if (type != cat) { - if (type == "w" && cat == "W" && dir < 0) pos--; - if (type == "W" && cat == "w" && dir > 0) { type = "w"; continue; } - break; - } - } - } - return Pos(start.line, pos); - } - - function moveSubword(cm, dir) { - cm.extendSelectionsBy(function(range) { - if (cm.display.shift || cm.doc.extend || range.empty()) - return findPosSubword(cm.doc, range.head, dir); - else - return dir < 0 ? range.from() : range.to(); - }); - } - - cmds[map["Alt-Left"] = "goSubwordLeft"] = function(cm) { moveSubword(cm, -1); }; - cmds[map["Alt-Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); }; - - cmds[map[ctrl + "Up"] = "scrollLineUp"] = function(cm) { - var info = cm.getScrollInfo(); - if (!cm.somethingSelected()) { - var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local"); - if (cm.getCursor().line >= visibleBottomLine) - cm.execCommand("goLineUp"); - } - cm.scrollTo(null, info.top - cm.defaultTextHeight()); - }; - cmds[map[ctrl + "Down"] = "scrollLineDown"] = function(cm) { - var info = cm.getScrollInfo(); - if (!cm.somethingSelected()) { - var visibleTopLine = cm.lineAtHeight(info.top, "local")+1; - if (cm.getCursor().line <= visibleTopLine) - cm.execCommand("goLineDown"); - } - cm.scrollTo(null, info.top + cm.defaultTextHeight()); - }; - - cmds[map["Shift-" + ctrl + "L"] = "splitSelectionByLine"] = function(cm) { - var ranges = cm.listSelections(), lineRanges = []; - for (var i = 0; i < ranges.length; i++) { - var from = ranges[i].from(), to = ranges[i].to(); - for (var line = from.line; line <= to.line; ++line) - if (!(to.line > from.line && line == to.line && to.ch == 0)) - lineRanges.push({anchor: line == from.line ? from : Pos(line, 0), - head: line == to.line ? to : Pos(line)}); - } - cm.setSelections(lineRanges, 0); - }; - - map["Shift-Tab"] = "indentLess"; - - cmds[map["Esc"] = "singleSelectionTop"] = function(cm) { - var range = cm.listSelections()[0]; - cm.setSelection(range.anchor, range.head, {scroll: false}); - }; - - cmds[map[ctrl + "L"] = "selectLine"] = function(cm) { - var ranges = cm.listSelections(), extended = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - extended.push({anchor: Pos(range.from().line, 0), - head: Pos(range.to().line + 1, 0)}); - } - cm.setSelections(extended); - }; - - map["Shift-" + ctrl + "K"] = "deleteLine"; - - function insertLine(cm, above) { - cm.operation(function() { - var len = cm.listSelections().length, newSelection = [], last = -1; - for (var i = 0; i < len; i++) { - var head = cm.listSelections()[i].head; - if (head.line <= last) continue; - var at = Pos(head.line + (above ? 0 : 1), 0); - cm.replaceRange("\n", at, null, "+insertLine"); - cm.indentLine(at.line, null, true); - newSelection.push({head: at, anchor: at}); - last = head.line + 1; - } - cm.setSelections(newSelection); - }); - } - - cmds[map[ctrl + "Enter"] = "insertLineAfter"] = function(cm) { insertLine(cm, false); }; - - cmds[map["Shift-" + ctrl + "Enter"] = "insertLineBefore"] = function(cm) { insertLine(cm, true); }; - - function wordAt(cm, pos) { - var start = pos.ch, end = start, line = cm.getLine(pos.line); - while (start && CodeMirror.isWordChar(line.charAt(start - 1))) --start; - while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) ++end; - return {from: Pos(pos.line, start), to: Pos(pos.line, end), word: line.slice(start, end)}; - } - - cmds[map[ctrl + "D"] = "selectNextOccurrence"] = function(cm) { - var from = cm.getCursor("from"), to = cm.getCursor("to"); - var fullWord = cm.state.sublimeFindFullWord == cm.doc.sel; - if (CodeMirror.cmpPos(from, to) == 0) { - var word = wordAt(cm, from); - if (!word.word) return; - cm.setSelection(word.from, word.to); - fullWord = true; - } else { - var text = cm.getRange(from, to); - var query = fullWord ? new RegExp("\\b" + text + "\\b") : text; - var cur = cm.getSearchCursor(query, to); - if (cur.findNext()) { - cm.addSelection(cur.from(), cur.to()); - } else { - cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0)); - if (cur.findNext()) - cm.addSelection(cur.from(), cur.to()); - } - } - if (fullWord) - cm.state.sublimeFindFullWord = cm.doc.sel; - }; - - var mirror = "(){}[]"; - function selectBetweenBrackets(cm) { - var pos = cm.getCursor(), opening = cm.scanForBracket(pos, -1); - if (!opening) return; - for (;;) { - var closing = cm.scanForBracket(pos, 1); - if (!closing) return; - if (closing.ch == mirror.charAt(mirror.indexOf(opening.ch) + 1)) { - cm.setSelection(Pos(opening.pos.line, opening.pos.ch + 1), closing.pos, false); - return true; - } - pos = Pos(closing.pos.line, closing.pos.ch + 1); - } - } - - cmds[map["Shift-" + ctrl + "Space"] = "selectScope"] = function(cm) { - selectBetweenBrackets(cm) || cm.execCommand("selectAll"); - }; - cmds[map["Shift-" + ctrl + "M"] = "selectBetweenBrackets"] = function(cm) { - if (!selectBetweenBrackets(cm)) return CodeMirror.Pass; - }; - - cmds[map[ctrl + "M"] = "goToBracket"] = function(cm) { - cm.extendSelectionsBy(function(range) { - var next = cm.scanForBracket(range.head, 1); - if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos; - var prev = cm.scanForBracket(range.head, -1); - return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head; - }); - }; - - var swapLineCombo = mac ? "Cmd-Ctrl-" : "Shift-Ctrl-"; - - cmds[map[swapLineCombo + "Up"] = "swapLineUp"] = function(cm) { - var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i], from = range.from().line - 1, to = range.to().line; - newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch), - head: Pos(range.head.line - 1, range.head.ch)}); - if (range.to().ch == 0 && !range.empty()) --to; - if (from > at) linesToMove.push(from, to); - else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; - at = to; - } - cm.operation(function() { - for (var i = 0; i < linesToMove.length; i += 2) { - var from = linesToMove[i], to = linesToMove[i + 1]; - var line = cm.getLine(from); - cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine"); - if (to > cm.lastLine()) - cm.replaceRange("\n" + line, Pos(cm.lastLine()), null, "+swapLine"); - else - cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine"); - } - cm.setSelections(newSels); - cm.scrollIntoView(); - }); - }; - - cmds[map[swapLineCombo + "Down"] = "swapLineDown"] = function(cm) { - var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1; - for (var i = ranges.length - 1; i >= 0; i--) { - var range = ranges[i], from = range.to().line + 1, to = range.from().line; - if (range.to().ch == 0 && !range.empty()) from--; - if (from < at) linesToMove.push(from, to); - else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; - at = to; - } - cm.operation(function() { - for (var i = linesToMove.length - 2; i >= 0; i -= 2) { - var from = linesToMove[i], to = linesToMove[i + 1]; - var line = cm.getLine(from); - if (from == cm.lastLine()) - cm.replaceRange("", Pos(from - 1), Pos(from), "+swapLine"); - else - cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine"); - cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine"); - } - cm.scrollIntoView(); - }); - }; - - map[ctrl + "/"] = "toggleComment"; - - cmds[map[ctrl + "J"] = "joinLines"] = function(cm) { - var ranges = cm.listSelections(), joined = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i], from = range.from(); - var start = from.line, end = range.to().line; - while (i < ranges.length - 1 && ranges[i + 1].from().line == end) - end = ranges[++i].to().line; - joined.push({start: start, end: end, anchor: !range.empty() && from}); - } - cm.operation(function() { - var offset = 0, ranges = []; - for (var i = 0; i < joined.length; i++) { - var obj = joined[i]; - var anchor = obj.anchor && Pos(obj.anchor.line - offset, obj.anchor.ch), head; - for (var line = obj.start; line <= obj.end; line++) { - var actual = line - offset; - if (line == obj.end) head = Pos(actual, cm.getLine(actual).length + 1); - if (actual < cm.lastLine()) { - cm.replaceRange(" ", Pos(actual), Pos(actual + 1, /^\s*/.exec(cm.getLine(actual + 1))[0].length)); - ++offset; - } - } - ranges.push({anchor: anchor || head, head: head}); - } - cm.setSelections(ranges, 0); - }); - }; - - cmds[map["Shift-" + ctrl + "D"] = "duplicateLine"] = function(cm) { - cm.operation(function() { - var rangeCount = cm.listSelections().length; - for (var i = 0; i < rangeCount; i++) { - var range = cm.listSelections()[i]; - if (range.empty()) - cm.replaceRange(cm.getLine(range.head.line) + "\n", Pos(range.head.line, 0)); - else - cm.replaceRange(cm.getRange(range.from(), range.to()), range.from()); - } - cm.scrollIntoView(); - }); - }; - - map[ctrl + "T"] = "transposeChars"; - - function sortLines(cm, caseSensitive) { - var ranges = cm.listSelections(), toSort = [], selected; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.empty()) continue; - var from = range.from().line, to = range.to().line; - while (i < ranges.length - 1 && ranges[i + 1].from().line == to) - to = range[++i].to().line; - toSort.push(from, to); - } - if (toSort.length) selected = true; - else toSort.push(cm.firstLine(), cm.lastLine()); - - cm.operation(function() { - var ranges = []; - for (var i = 0; i < toSort.length; i += 2) { - var from = toSort[i], to = toSort[i + 1]; - var start = Pos(from, 0), end = Pos(to); - var lines = cm.getRange(start, end, false); - if (caseSensitive) - lines.sort(); - else - lines.sort(function(a, b) { - var au = a.toUpperCase(), bu = b.toUpperCase(); - if (au != bu) { a = au; b = bu; } - return a < b ? -1 : a == b ? 0 : 1; - }); - cm.replaceRange(lines, start, end); - if (selected) ranges.push({anchor: start, head: end}); - } - if (selected) cm.setSelections(ranges, 0); - }); - } - - cmds[map["F9"] = "sortLines"] = function(cm) { sortLines(cm, true); }; - cmds[map[ctrl + "F9"] = "sortLinesInsensitive"] = function(cm) { sortLines(cm, false); }; - - cmds[map["F2"] = "nextBookmark"] = function(cm) { - var marks = cm.state.sublimeBookmarks; - if (marks) while (marks.length) { - var current = marks.shift(); - var found = current.find(); - if (found) { - marks.push(current); - return cm.setSelection(found.from, found.to); - } - } - }; - - cmds[map["Shift-F2"] = "prevBookmark"] = function(cm) { - var marks = cm.state.sublimeBookmarks; - if (marks) while (marks.length) { - marks.unshift(marks.pop()); - var found = marks[marks.length - 1].find(); - if (!found) - marks.pop(); - else - return cm.setSelection(found.from, found.to); - } - }; - - cmds[map[ctrl + "F2"] = "toggleBookmark"] = function(cm) { - var ranges = cm.listSelections(); - var marks = cm.state.sublimeBookmarks || (cm.state.sublimeBookmarks = []); - for (var i = 0; i < ranges.length; i++) { - var from = ranges[i].from(), to = ranges[i].to(); - var found = cm.findMarks(from, to); - for (var j = 0; j < found.length; j++) { - if (found[j].sublimeBookmark) { - found[j].clear(); - for (var k = 0; k < marks.length; k++) - if (marks[k] == found[j]) - marks.splice(k--, 1); - break; - } - } - if (j == found.length) - marks.push(cm.markText(from, to, {sublimeBookmark: true, clearWhenEmpty: false})); - } - }; - - cmds[map["Shift-" + ctrl + "F2"] = "clearBookmarks"] = function(cm) { - var marks = cm.state.sublimeBookmarks; - if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear(); - marks.length = 0; - }; - - cmds[map["Alt-F2"] = "selectBookmarks"] = function(cm) { - var marks = cm.state.sublimeBookmarks, ranges = []; - if (marks) for (var i = 0; i < marks.length; i++) { - var found = marks[i].find(); - if (!found) - marks.splice(i--, 0); - else - ranges.push({anchor: found.from, head: found.to}); - } - if (ranges.length) - cm.setSelections(ranges, 0); - }; - - map["Alt-Q"] = "wrapLines"; - - var cK = ctrl + "K "; - - function modifyWordOrSelection(cm, mod) { - cm.operation(function() { - var ranges = cm.listSelections(), indices = [], replacements = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.empty()) { indices.push(i); replacements.push(""); } - else replacements.push(mod(cm.getRange(range.from(), range.to()))); - } - cm.replaceSelections(replacements, "around", "case"); - for (var i = indices.length - 1, at; i >= 0; i--) { - var range = ranges[indices[i]]; - if (at && CodeMirror.cmpPos(range.head, at) > 0) continue; - var word = wordAt(cm, range.head); - at = word.from; - cm.replaceRange(mod(word.word), word.from, word.to); - } - }); - } - - map[cK + ctrl + "Backspace"] = "delLineLeft"; - - cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) { - cm.operation(function() { - var ranges = cm.listSelections(); - for (var i = ranges.length - 1; i >= 0; i--) - cm.replaceRange("", ranges[i].anchor, Pos(ranges[i].to().line), "+delete"); - cm.scrollIntoView(); - }); - }; - - cmds[map[cK + ctrl + "U"] = "upcaseAtCursor"] = function(cm) { - modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); }); - }; - cmds[map[cK + ctrl + "L"] = "downcaseAtCursor"] = function(cm) { - modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); }); - }; - - cmds[map[cK + ctrl + "Space"] = "setSublimeMark"] = function(cm) { - if (cm.state.sublimeMark) cm.state.sublimeMark.clear(); - cm.state.sublimeMark = cm.setBookmark(cm.getCursor()); - }; - cmds[map[cK + ctrl + "A"] = "selectToSublimeMark"] = function(cm) { - var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); - if (found) cm.setSelection(cm.getCursor(), found); - }; - cmds[map[cK + ctrl + "W"] = "deleteToSublimeMark"] = function(cm) { - var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); - if (found) { - var from = cm.getCursor(), to = found; - if (CodeMirror.cmpPos(from, to) > 0) { var tmp = to; to = from; from = tmp; } - cm.state.sublimeKilled = cm.getRange(from, to); - cm.replaceRange("", from, to); - } - }; - cmds[map[cK + ctrl + "X"] = "swapWithSublimeMark"] = function(cm) { - var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); - if (found) { - cm.state.sublimeMark.clear(); - cm.state.sublimeMark = cm.setBookmark(cm.getCursor()); - cm.setCursor(found); - } - }; - cmds[map[cK + ctrl + "Y"] = "sublimeYank"] = function(cm) { - if (cm.state.sublimeKilled != null) - cm.replaceSelection(cm.state.sublimeKilled, null, "paste"); - }; - - map[cK + ctrl + "G"] = "clearBookmarks"; - cmds[map[cK + ctrl + "C"] = "showInCenter"] = function(cm) { - var pos = cm.cursorCoords(null, "local"); - cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2); - }; - - cmds[map["Shift-Alt-Up"] = "selectLinesUpward"] = function(cm) { - cm.operation(function() { - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.head.line > cm.firstLine()) - cm.addSelection(Pos(range.head.line - 1, range.head.ch)); - } - }); - }; - cmds[map["Shift-Alt-Down"] = "selectLinesDownward"] = function(cm) { - cm.operation(function() { - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.head.line < cm.lastLine()) - cm.addSelection(Pos(range.head.line + 1, range.head.ch)); - } - }); - }; - - function getTarget(cm) { - var from = cm.getCursor("from"), to = cm.getCursor("to"); - if (CodeMirror.cmpPos(from, to) == 0) { - var word = wordAt(cm, from); - if (!word.word) return; - from = word.from; - to = word.to; - } - return {from: from, to: to, query: cm.getRange(from, to), word: word}; - } - - function findAndGoTo(cm, forward) { - var target = getTarget(cm); - if (!target) return; - var query = target.query; - var cur = cm.getSearchCursor(query, forward ? target.to : target.from); - - if (forward ? cur.findNext() : cur.findPrevious()) { - cm.setSelection(cur.from(), cur.to()); - } else { - cur = cm.getSearchCursor(query, forward ? Pos(cm.firstLine(), 0) - : cm.clipPos(Pos(cm.lastLine()))); - if (forward ? cur.findNext() : cur.findPrevious()) - cm.setSelection(cur.from(), cur.to()); - else if (target.word) - cm.setSelection(target.from, target.to); - } - }; - cmds[map[ctrl + "F3"] = "findUnder"] = function(cm) { findAndGoTo(cm, true); }; - cmds[map["Shift-" + ctrl + "F3"] = "findUnderPrevious"] = function(cm) { findAndGoTo(cm,false); }; - cmds[map["Alt-F3"] = "findAllUnder"] = function(cm) { - var target = getTarget(cm); - if (!target) return; - var cur = cm.getSearchCursor(target.query); - var matches = []; - var primaryIndex = -1; - while (cur.findNext()) { - matches.push({anchor: cur.from(), head: cur.to()}); - if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch) - primaryIndex++; - } - cm.setSelections(matches, primaryIndex); - }; - - map["Shift-" + ctrl + "["] = "fold"; - map["Shift-" + ctrl + "]"] = "unfold"; - map[cK + ctrl + "0"] = map[cK + ctrl + "j"] = "unfoldAll"; - - map[ctrl + "I"] = "findIncremental"; - map["Shift-" + ctrl + "I"] = "findIncrementalReverse"; - map[ctrl + "H"] = "replace"; - map["F3"] = "findNext"; - map["Shift-F3"] = "findPrev"; - - CodeMirror.normalizeKeyMap(map); -}); diff --git a/shared/html/libs/codemirror/5.0.0/keymap/vim.js b/shared/html/libs/codemirror/5.0.0/keymap/vim.js deleted file mode 100644 index 682eb7a..0000000 --- a/shared/html/libs/codemirror/5.0.0/keymap/vim.js +++ /dev/null @@ -1,4959 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Supported keybindings: - * - * Motion: - * h, j, k, l - * gj, gk - * e, E, w, W, b, B, ge, gE - * f, F, t, T - * $, ^, 0, -, +, _ - * gg, G - * % - * ', ` - * - * Operator: - * d, y, c - * dd, yy, cc - * g~, g~g~ - * >, <, >>, << - * - * Operator-Motion: - * x, X, D, Y, C, ~ - * - * Action: - * a, i, s, A, I, S, o, O - * zz, z., z, zt, zb, z- - * J - * u, Ctrl-r - * m - * r - * - * Modes: - * ESC - leave insert mode, visual mode, and clear input state. - * Ctrl-[, Ctrl-c - same as ESC. - * - * Registers: unnamed, -, a-z, A-Z, 0-9 - * (Does not respect the special case for number registers when delete - * operator is made with these commands: %, (, ), , /, ?, n, N, {, } ) - * TODO: Implement the remaining registers. - * Marks: a-z, A-Z, and 0-9 - * TODO: Implement the remaining special marks. They have more complex - * behavior. - * - * Events: - * 'vim-mode-change' - raised on the editor anytime the current mode changes, - * Event object: {mode: "visual", subMode: "linewise"} - * - * Code structure: - * 1. Default keymap - * 2. Variable declarations and short basic helpers - * 3. Instance (External API) implementation - * 4. Internal state tracking objects (input state, counter) implementation - * and instanstiation - * 5. Key handler (the main command dispatcher) implementation - * 6. Motion, operator, and action implementations - * 7. Helper functions for the key handler, motions, operators, and actions - * 8. Set up Vim to work as a keymap for CodeMirror. - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/dialog/dialog"), require("../addon/edit/matchbrackets.js")); - else if (typeof define == "function" && define.amd) // AMD - define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/dialog/dialog", "../addon/edit/matchbrackets"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - 'use strict'; - - var defaultKeymap = [ - // Key to key mapping. This goes first to make it possible to override - // existing mappings. - { keys: '', type: 'keyToKey', toKeys: 'h' }, - { keys: '', type: 'keyToKey', toKeys: 'l' }, - { keys: '', type: 'keyToKey', toKeys: 'k' }, - { keys: '', type: 'keyToKey', toKeys: 'j' }, - { keys: '', type: 'keyToKey', toKeys: 'l' }, - { keys: '', type: 'keyToKey', toKeys: 'h', context: 'normal'}, - { keys: '', type: 'keyToKey', toKeys: 'W' }, - { keys: '', type: 'keyToKey', toKeys: 'B', context: 'normal' }, - { keys: '', type: 'keyToKey', toKeys: 'w' }, - { keys: '', type: 'keyToKey', toKeys: 'b', context: 'normal' }, - { keys: '', type: 'keyToKey', toKeys: 'j' }, - { keys: '', type: 'keyToKey', toKeys: 'k' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, - { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, - { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, - { keys: 's', type: 'keyToKey', toKeys: 'xi', context: 'visual'}, - { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, - { keys: 'S', type: 'keyToKey', toKeys: 'dcc', context: 'visual' }, - { keys: '', type: 'keyToKey', toKeys: '0' }, - { keys: '', type: 'keyToKey', toKeys: '$' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, - // Motions - { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }}, - { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }}, - { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }}, - { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }}, - { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }}, - { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }}, - { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }}, - { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }}, - { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }}, - { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }}, - { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }}, - { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }}, - { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }}, - { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }}, - { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }}, - { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, - { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, - { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, - { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, - { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }}, - { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: '0', type: 'motion', motion: 'moveToStartOfLine' }, - { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }}, - { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }}, - { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, - { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }}, - { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }}, - { keys: 'f', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }}, - { keys: 'F', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }}, - { keys: 't', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }}, - { keys: 'T', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }}, - { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }}, - { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }}, - { keys: '\'', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}}, - { keys: '`', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}}, - { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, - { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, - { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, - { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, - // the next two aren't motions but must come before more general motion declarations - { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}}, - { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}}, - { keys: ']', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}}, - { keys: '[', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}}, - { keys: '|', type: 'motion', motion: 'moveToColumn'}, - { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'}, - { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, - // Operators - { keys: 'd', type: 'operator', operator: 'delete' }, - { keys: 'y', type: 'operator', operator: 'yank' }, - { keys: 'c', type: 'operator', operator: 'change' }, - { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }}, - { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }}, - { keys: 'g~', type: 'operator', operator: 'changeCase' }, - { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true }, - { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true }, - { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }}, - { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }}, - // Operator-Motion dual commands - { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, - { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, - { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, - { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'}, - { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, - { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'}, - { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, - { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'}, - { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'}, - { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'}, - { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, - // Actions - { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, - { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, - { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }}, - { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }}, - { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' }, - { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, - { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, - { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, - { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' }, - { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' }, - { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, - { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, - { keys: 'v', type: 'action', action: 'toggleVisualMode' }, - { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }}, - { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, - { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, - { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, - { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }}, - { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, - { keys: 'r', type: 'action', action: 'replace', isEdit: true }, - { keys: '@', type: 'action', action: 'replayMacro' }, - { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, - // Handle Replace-mode as a special case of insert mode. - { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, - { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, - { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true }, - { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, - { keys: '', type: 'action', action: 'redo' }, - { keys: 'm', type: 'action', action: 'setMark' }, - { keys: '"', type: 'action', action: 'setRegister' }, - { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }}, - { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }}, - { keys: 'z', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }}, - { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: '.', type: 'action', action: 'repeatLastEdit' }, - { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}}, - { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}}, - // Text object motions - { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, - { keys: 'i', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }}, - // Search - { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, - { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, - { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, - { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, - // Ex command - { keys: ':', type: 'ex' } - ]; - - var Pos = CodeMirror.Pos; - - var Vim = function() { - function enterVimMode(cm) { - cm.setOption('disableInput', true); - cm.setOption('showCursorWhenSelecting', false); - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - cm.on('cursorActivity', onCursorActivity); - maybeInitVimState(cm); - CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); - } - - function leaveVimMode(cm) { - cm.setOption('disableInput', false); - cm.off('cursorActivity', onCursorActivity); - CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); - cm.state.vim = null; - } - - function detachVimMap(cm, next) { - if (this == CodeMirror.keyMap.vim) - CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor"); - - if (!next || next.attach != attachVimMap) - leaveVimMode(cm, false); - } - function attachVimMap(cm, prev) { - if (this == CodeMirror.keyMap.vim) - CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); - - if (!prev || prev.attach != attachVimMap) - enterVimMode(cm); - } - - // Deprecated, simply setting the keymap works again. - CodeMirror.defineOption('vimMode', false, function(cm, val, prev) { - if (val && cm.getOption("keyMap") != "vim") - cm.setOption("keyMap", "vim"); - else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) - cm.setOption("keyMap", "default"); - }); - - function cmKey(key, cm) { - if (!cm) { return undefined; } - var vimKey = cmKeyToVimKey(key); - if (!vimKey) { - return false; - } - var cmd = CodeMirror.Vim.findKey(cm, vimKey); - if (typeof cmd == 'function') { - CodeMirror.signal(cm, 'vim-keypress', vimKey); - } - return cmd; - } - - var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'}; - var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del'}; - function cmKeyToVimKey(key) { - if (key.charAt(0) == '\'') { - // Keypress character binding of format "'a'" - return key.charAt(1); - } - var pieces = key.split('-'); - if (/-$/.test(key)) { - // If the - key was typed, split will result in 2 extra empty strings - // in the array. Replace them with 1 '-'. - pieces.splice(-2, 2, '-'); - } - var lastPiece = pieces[pieces.length - 1]; - if (pieces.length == 1 && pieces[0].length == 1) { - // No-modifier bindings use literal character bindings above. Skip. - return false; - } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) { - // Ignore Shift+char bindings as they should be handled by literal character. - return false; - } - var hasCharacter = false; - for (var i = 0; i < pieces.length; i++) { - var piece = pieces[i]; - if (piece in modifiers) { pieces[i] = modifiers[piece]; } - else { hasCharacter = true; } - if (piece in specialKeys) { pieces[i] = specialKeys[piece]; } - } - if (!hasCharacter) { - // Vim does not support modifier only keys. - return false; - } - // TODO: Current bindings expect the character to be lower case, but - // it looks like vim key notation uses upper case. - if (isUpperCase(lastPiece)) { - pieces[pieces.length - 1] = lastPiece.toLowerCase(); - } - return '<' + pieces.join('-') + '>'; - } - - function getOnPasteFn(cm) { - var vim = cm.state.vim; - if (!vim.onPasteFn) { - vim.onPasteFn = function() { - if (!vim.insertMode) { - cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); - actions.enterInsertMode(cm, {}, vim); - } - }; - } - return vim.onPasteFn; - } - - var numberRegex = /[\d]/; - var wordRegexp = [(/\w/), (/[^\w\s]/)], bigWordRegexp = [(/\S/)]; - function makeKeyRange(start, size) { - var keys = []; - for (var i = start; i < start + size; i++) { - keys.push(String.fromCharCode(i)); - } - return keys; - } - var upperCaseAlphabet = makeKeyRange(65, 26); - var lowerCaseAlphabet = makeKeyRange(97, 26); - var numbers = makeKeyRange(48, 10); - var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); - var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); - - function isLine(cm, line) { - return line >= cm.firstLine() && line <= cm.lastLine(); - } - function isLowerCase(k) { - return (/^[a-z]$/).test(k); - } - function isMatchableSymbol(k) { - return '()[]{}'.indexOf(k) != -1; - } - function isNumber(k) { - return numberRegex.test(k); - } - function isUpperCase(k) { - return (/^[A-Z]$/).test(k); - } - function isWhiteSpaceString(k) { - return (/^\s*$/).test(k); - } - function inArray(val, arr) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] == val) { - return true; - } - } - return false; - } - - var options = {}; - function defineOption(name, defaultValue, type) { - if (defaultValue === undefined) { throw Error('defaultValue is required'); } - if (!type) { type = 'string'; } - options[name] = { - type: type, - defaultValue: defaultValue - }; - setOption(name, defaultValue); - } - - function setOption(name, value) { - var option = options[name]; - if (!option) { - throw Error('Unknown option: ' + name); - } - if (option.type == 'boolean') { - if (value && value !== true) { - throw Error('Invalid argument: ' + name + '=' + value); - } else if (value !== false) { - // Boolean options are set to true if value is not defined. - value = true; - } - } - option.value = option.type == 'boolean' ? !!value : value; - } - - function getOption(name) { - var option = options[name]; - if (!option) { - throw Error('Unknown option: ' + name); - } - return option.value; - } - - var createCircularJumpList = function() { - var size = 100; - var pointer = -1; - var head = 0; - var tail = 0; - var buffer = new Array(size); - function add(cm, oldCur, newCur) { - var current = pointer % size; - var curMark = buffer[current]; - function useNextSlot(cursor) { - var next = ++pointer % size; - var trashMark = buffer[next]; - if (trashMark) { - trashMark.clear(); - } - buffer[next] = cm.setBookmark(cursor); - } - if (curMark) { - var markPos = curMark.find(); - // avoid recording redundant cursor position - if (markPos && !cursorEqual(markPos, oldCur)) { - useNextSlot(oldCur); - } - } else { - useNextSlot(oldCur); - } - useNextSlot(newCur); - head = pointer; - tail = pointer - size + 1; - if (tail < 0) { - tail = 0; - } - } - function move(cm, offset) { - pointer += offset; - if (pointer > head) { - pointer = head; - } else if (pointer < tail) { - pointer = tail; - } - var mark = buffer[(size + pointer) % size]; - // skip marks that are temporarily removed from text buffer - if (mark && !mark.find()) { - var inc = offset > 0 ? 1 : -1; - var newCur; - var oldCur = cm.getCursor(); - do { - pointer += inc; - mark = buffer[(size + pointer) % size]; - // skip marks that are the same as current position - if (mark && - (newCur = mark.find()) && - !cursorEqual(oldCur, newCur)) { - break; - } - } while (pointer < head && pointer > tail); - } - return mark; - } - return { - cachedCursor: undefined, //used for # and * jumps - add: add, - move: move - }; - }; - - // Returns an object to track the changes associated insert mode. It - // clones the object that is passed in, or creates an empty object one if - // none is provided. - var createInsertModeChanges = function(c) { - if (c) { - // Copy construction - return { - changes: c.changes, - expectCursorActivityForChange: c.expectCursorActivityForChange - }; - } - return { - // Change list - changes: [], - // Set to true on change, false on cursorActivity. - expectCursorActivityForChange: false - }; - }; - - function MacroModeState() { - this.latestRegister = undefined; - this.isPlaying = false; - this.isRecording = false; - this.replaySearchQueries = []; - this.onRecordingDone = undefined; - this.lastInsertModeChanges = createInsertModeChanges(); - } - MacroModeState.prototype = { - exitMacroRecordMode: function() { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.onRecordingDone) { - macroModeState.onRecordingDone(); // close dialog - } - macroModeState.onRecordingDone = undefined; - macroModeState.isRecording = false; - }, - enterMacroRecordMode: function(cm, registerName) { - var register = - vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.clear(); - this.latestRegister = registerName; - if (cm.openDialog) { - this.onRecordingDone = cm.openDialog( - '(recording)['+registerName+']', null, {bottom:true}); - } - this.isRecording = true; - } - } - }; - - function maybeInitVimState(cm) { - if (!cm.state.vim) { - // Store instance state in the CodeMirror object. - cm.state.vim = { - inputState: new InputState(), - // Vim's input state that triggered the last edit, used to repeat - // motions and operators with '.'. - lastEditInputState: undefined, - // Vim's action command before the last edit, used to repeat actions - // with '.' and insert mode repeat. - lastEditActionCommand: undefined, - // When using jk for navigation, if you move from a longer line to a - // shorter line, the cursor may clip to the end of the shorter line. - // If j is pressed again and cursor goes to the next line, the - // cursor should go back to its horizontal position on the longer - // line if it can. This is to keep track of the horizontal position. - lastHPos: -1, - // Doing the same with screen-position for gj/gk - lastHSPos: -1, - // The last motion command run. Cleared if a non-motion command gets - // executed in between. - lastMotion: null, - marks: {}, - // Mark for rendering fake cursor for visual mode. - fakeCursor: null, - insertMode: false, - // Repeat count for changes made in insert mode, triggered by key - // sequences like 3,i. Only exists when insertMode is true. - insertModeRepeat: undefined, - visualMode: false, - // If we are in visual line mode. No effect if visualMode is false. - visualLine: false, - visualBlock: false, - lastSelection: null, - lastPastedText: null, - sel: { - } - }; - } - return cm.state.vim; - } - var vimGlobalState; - function resetVimGlobalState() { - vimGlobalState = { - // The current search query. - searchQuery: null, - // Whether we are searching backwards. - searchIsReversed: false, - // Replace part of the last substituted pattern - lastSubstituteReplacePart: undefined, - jumpList: createCircularJumpList(), - macroModeState: new MacroModeState, - // Recording latest f, t, F or T motion command. - lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''}, - registerController: new RegisterController({}), - // search history buffer - searchHistoryController: new HistoryController({}), - // ex Command history buffer - exCommandHistoryController : new HistoryController({}) - }; - for (var optionName in options) { - var option = options[optionName]; - option.value = option.defaultValue; - } - } - - var lastInsertModeKeyTimer; - var vimApi= { - buildKeyMap: function() { - // TODO: Convert keymap into dictionary format for fast lookup. - }, - // Testing hook, though it might be useful to expose the register - // controller anyways. - getRegisterController: function() { - return vimGlobalState.registerController; - }, - // Testing hook. - resetVimGlobalState_: resetVimGlobalState, - - // Testing hook. - getVimGlobalState_: function() { - return vimGlobalState; - }, - - // Testing hook. - maybeInitVimState_: maybeInitVimState, - - suppressErrorLogging: false, - - InsertModeKey: InsertModeKey, - map: function(lhs, rhs, ctx) { - // Add user defined key bindings. - exCommandDispatcher.map(lhs, rhs, ctx); - }, - setOption: setOption, - getOption: getOption, - defineOption: defineOption, - defineEx: function(name, prefix, func){ - if (name.indexOf(prefix) !== 0) { - throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered'); - } - exCommands[name]=func; - exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'}; - }, - handleKey: function (cm, key, origin) { - var command = this.findKey(cm, key, origin); - if (typeof command === 'function') { - return command(); - } - }, - /** - * This is the outermost function called by CodeMirror, after keys have - * been mapped to their Vim equivalents. - * - * Finds a command based on the key (and cached keys if there is a - * multi-key sequence). Returns `undefined` if no key is matched, a noop - * function if a partial match is found (multi-key), and a function to - * execute the bound command if a a key is matched. The function always - * returns true. - */ - findKey: function(cm, key, origin) { - var vim = maybeInitVimState(cm); - function handleMacroRecording() { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - if (key == 'q') { - macroModeState.exitMacroRecordMode(); - clearInputState(cm); - return true; - } - if (origin != 'mapping') { - logKey(macroModeState, key); - } - } - } - function handleEsc() { - if (key == '') { - // Clear input state and get back to normal mode. - clearInputState(cm); - if (vim.visualMode) { - exitVisualMode(cm); - } else if (vim.insertMode) { - exitInsertMode(cm); - } - return true; - } - } - function doKeyToKey(keys) { - // TODO: prevent infinite recursion. - var match; - while (keys) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = (/<\w+-.+?>|<\w+>|./).exec(keys); - key = match[0]; - keys = keys.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key, 'mapping'); - } - } - - function handleKeyInsertMode() { - if (handleEsc()) { return true; } - var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; - var keysAreChars = key.length == 1; - var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); - // Need to check all key substrings in insert mode. - while (keys.length > 1 && match.type != 'full') { - var keys = vim.inputState.keyBuffer = keys.slice(1); - var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); - if (thisMatch.type != 'none') { match = thisMatch; } - } - if (match.type == 'none') { clearInputState(cm); return false; } - else if (match.type == 'partial') { - if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } - lastInsertModeKeyTimer = window.setTimeout( - function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } }, - getOption('insertModeEscKeysTimeout')); - return !keysAreChars; - } - - if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } - if (keysAreChars) { - var here = cm.getCursor(); - cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); - } - clearInputState(cm); - return match.command; - } - - function handleKeyNonInsertMode() { - if (handleMacroRecording() || handleEsc()) { return true; }; - - var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; - if (/^[1-9]\d*$/.test(keys)) { return true; } - - var keysMatcher = /^(\d*)(.*)$/.exec(keys); - if (!keysMatcher) { clearInputState(cm); return false; } - var context = vim.visualMode ? 'visual' : - 'normal'; - var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); - if (match.type == 'none') { clearInputState(cm); return false; } - else if (match.type == 'partial') { return true; } - - vim.inputState.keyBuffer = ''; - var keysMatcher = /^(\d*)(.*)$/.exec(keys); - if (keysMatcher[1] && keysMatcher[1] != '0') { - vim.inputState.pushRepeatDigit(keysMatcher[1]); - } - return match.command; - } - - var command; - if (vim.insertMode) { command = handleKeyInsertMode(); } - else { command = handleKeyNonInsertMode(); } - if (command === false) { - return undefined; - } else if (command === true) { - // TODO: Look into using CodeMirror's multi-key handling. - // Return no-op since we are caching the key. Counts as handled, but - // don't want act on it just yet. - return function() {}; - } else { - return function() { - return cm.operation(function() { - cm.curOp.isVimOp = true; - try { - if (command.type == 'keyToKey') { - doKeyToKey(command.toKeys); - } else { - commandDispatcher.processCommand(cm, vim, command); - } - } catch (e) { - // clear VIM state in case it's in a bad state. - cm.state.vim = undefined; - maybeInitVimState(cm); - if (!CodeMirror.Vim.suppressErrorLogging) { - console['log'](e); - } - throw e; - } - return true; - }); - }; - } - }, - handleEx: function(cm, input) { - exCommandDispatcher.processCommand(cm, input); - }, - - defineMotion: defineMotion, - defineAction: defineAction, - defineOperator: defineOperator, - mapCommand: mapCommand, - _mapCommand: _mapCommand, - - exitVisualMode: exitVisualMode, - exitInsertMode: exitInsertMode - }; - - // Represents the current input state. - function InputState() { - this.prefixRepeat = []; - this.motionRepeat = []; - - this.operator = null; - this.operatorArgs = null; - this.motion = null; - this.motionArgs = null; - this.keyBuffer = []; // For matching multi-key commands. - this.registerName = null; // Defaults to the unnamed register. - } - InputState.prototype.pushRepeatDigit = function(n) { - if (!this.operator) { - this.prefixRepeat = this.prefixRepeat.concat(n); - } else { - this.motionRepeat = this.motionRepeat.concat(n); - } - }; - InputState.prototype.getRepeat = function() { - var repeat = 0; - if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) { - repeat = 1; - if (this.prefixRepeat.length > 0) { - repeat *= parseInt(this.prefixRepeat.join(''), 10); - } - if (this.motionRepeat.length > 0) { - repeat *= parseInt(this.motionRepeat.join(''), 10); - } - } - return repeat; - }; - - function clearInputState(cm, reason) { - cm.state.vim.inputState = new InputState(); - CodeMirror.signal(cm, 'vim-command-done', reason); - } - - /* - * Register stores information about copy and paste registers. Besides - * text, a register must store whether it is linewise (i.e., when it is - * pasted, should it insert itself into a new line, or should the text be - * inserted at the cursor position.) - */ - function Register(text, linewise, blockwise) { - this.clear(); - this.keyBuffer = [text || '']; - this.insertModeChanges = []; - this.searchQueries = []; - this.linewise = !!linewise; - this.blockwise = !!blockwise; - } - Register.prototype = { - setText: function(text, linewise, blockwise) { - this.keyBuffer = [text || '']; - this.linewise = !!linewise; - this.blockwise = !!blockwise; - }, - pushText: function(text, linewise) { - // if this register has ever been set to linewise, use linewise. - if (linewise) { - if (!this.linewise) { - this.keyBuffer.push('\n'); - } - this.linewise = true; - } - this.keyBuffer.push(text); - }, - pushInsertModeChanges: function(changes) { - this.insertModeChanges.push(createInsertModeChanges(changes)); - }, - pushSearchQuery: function(query) { - this.searchQueries.push(query); - }, - clear: function() { - this.keyBuffer = []; - this.insertModeChanges = []; - this.searchQueries = []; - this.linewise = false; - }, - toString: function() { - return this.keyBuffer.join(''); - } - }; - - /* - * vim registers allow you to keep many independent copy and paste buffers. - * See http://usevim.com/2012/04/13/registers/ for an introduction. - * - * RegisterController keeps the state of all the registers. An initial - * state may be passed in. The unnamed register '"' will always be - * overridden. - */ - function RegisterController(registers) { - this.registers = registers; - this.unnamedRegister = registers['"'] = new Register(); - registers['.'] = new Register(); - registers[':'] = new Register(); - registers['/'] = new Register(); - } - RegisterController.prototype = { - pushText: function(registerName, operator, text, linewise, blockwise) { - if (linewise && text.charAt(0) == '\n') { - text = text.slice(1) + '\n'; - } - if (linewise && text.charAt(text.length - 1) !== '\n'){ - text += '\n'; - } - // Lowercase and uppercase registers refer to the same register. - // Uppercase just means append. - var register = this.isValidRegister(registerName) ? - this.getRegister(registerName) : null; - // if no register/an invalid register was specified, things go to the - // default registers - if (!register) { - switch (operator) { - case 'yank': - // The 0 register contains the text from the most recent yank. - this.registers['0'] = new Register(text, linewise, blockwise); - break; - case 'delete': - case 'change': - if (text.indexOf('\n') == -1) { - // Delete less than 1 line. Update the small delete register. - this.registers['-'] = new Register(text, linewise); - } else { - // Shift down the contents of the numbered registers and put the - // deleted text into register 1. - this.shiftNumericRegisters_(); - this.registers['1'] = new Register(text, linewise); - } - break; - } - // Make sure the unnamed register is set to what just happened - this.unnamedRegister.setText(text, linewise, blockwise); - return; - } - - // If we've gotten to this point, we've actually specified a register - var append = isUpperCase(registerName); - if (append) { - register.pushText(text, linewise); - } else { - register.setText(text, linewise, blockwise); - } - // The unnamed register always has the same value as the last used - // register. - this.unnamedRegister.setText(register.toString(), linewise); - }, - // Gets the register named @name. If one of @name doesn't already exist, - // create it. If @name is invalid, return the unnamedRegister. - getRegister: function(name) { - if (!this.isValidRegister(name)) { - return this.unnamedRegister; - } - name = name.toLowerCase(); - if (!this.registers[name]) { - this.registers[name] = new Register(); - } - return this.registers[name]; - }, - isValidRegister: function(name) { - return name && inArray(name, validRegisters); - }, - shiftNumericRegisters_: function() { - for (var i = 9; i >= 2; i--) { - this.registers[i] = this.getRegister('' + (i - 1)); - } - } - }; - function HistoryController() { - this.historyBuffer = []; - this.iterator; - this.initialPrefix = null; - } - HistoryController.prototype = { - // the input argument here acts a user entered prefix for a small time - // until we start autocompletion in which case it is the autocompleted. - nextMatch: function (input, up) { - var historyBuffer = this.historyBuffer; - var dir = up ? -1 : 1; - if (this.initialPrefix === null) this.initialPrefix = input; - for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) { - var element = historyBuffer[i]; - for (var j = 0; j <= element.length; j++) { - if (this.initialPrefix == element.substring(0, j)) { - this.iterator = i; - return element; - } - } - } - // should return the user input in case we reach the end of buffer. - if (i >= historyBuffer.length) { - this.iterator = historyBuffer.length; - return this.initialPrefix; - } - // return the last autocompleted query or exCommand as it is. - if (i < 0 ) return input; - }, - pushInput: function(input) { - var index = this.historyBuffer.indexOf(input); - if (index > -1) this.historyBuffer.splice(index, 1); - if (input.length) this.historyBuffer.push(input); - }, - reset: function() { - this.initialPrefix = null; - this.iterator = this.historyBuffer.length; - } - }; - var commandDispatcher = { - matchCommand: function(keys, keyMap, inputState, context) { - var matches = commandMatches(keys, keyMap, context, inputState); - if (!matches.full && !matches.partial) { - return {type: 'none'}; - } else if (!matches.full && matches.partial) { - return {type: 'partial'}; - } - - var bestMatch; - for (var i = 0; i < matches.full.length; i++) { - var match = matches.full[i]; - if (!bestMatch) { - bestMatch = match; - } - } - if (bestMatch.keys.slice(-11) == '') { - inputState.selectedCharacter = lastChar(keys); - } - return {type: 'full', command: bestMatch}; - }, - processCommand: function(cm, vim, command) { - vim.inputState.repeatOverride = command.repeatOverride; - switch (command.type) { - case 'motion': - this.processMotion(cm, vim, command); - break; - case 'operator': - this.processOperator(cm, vim, command); - break; - case 'operatorMotion': - this.processOperatorMotion(cm, vim, command); - break; - case 'action': - this.processAction(cm, vim, command); - break; - case 'search': - this.processSearch(cm, vim, command); - clearInputState(cm); - break; - case 'ex': - case 'keyToEx': - this.processEx(cm, vim, command); - clearInputState(cm); - break; - default: - break; - } - }, - processMotion: function(cm, vim, command) { - vim.inputState.motion = command.motion; - vim.inputState.motionArgs = copyArgs(command.motionArgs); - this.evalInput(cm, vim); - }, - processOperator: function(cm, vim, command) { - var inputState = vim.inputState; - if (inputState.operator) { - if (inputState.operator == command.operator) { - // Typing an operator twice like 'dd' makes the operator operate - // linewise - inputState.motion = 'expandToLine'; - inputState.motionArgs = { linewise: true }; - this.evalInput(cm, vim); - return; - } else { - // 2 different operators in a row doesn't make sense. - clearInputState(cm); - } - } - inputState.operator = command.operator; - inputState.operatorArgs = copyArgs(command.operatorArgs); - if (vim.visualMode) { - // Operating on a selection in visual mode. We don't need a motion. - this.evalInput(cm, vim); - } - }, - processOperatorMotion: function(cm, vim, command) { - var visualMode = vim.visualMode; - var operatorMotionArgs = copyArgs(command.operatorMotionArgs); - if (operatorMotionArgs) { - // Operator motions may have special behavior in visual mode. - if (visualMode && operatorMotionArgs.visualLine) { - vim.visualLine = true; - } - } - this.processOperator(cm, vim, command); - if (!visualMode) { - this.processMotion(cm, vim, command); - } - }, - processAction: function(cm, vim, command) { - var inputState = vim.inputState; - var repeat = inputState.getRepeat(); - var repeatIsExplicit = !!repeat; - var actionArgs = copyArgs(command.actionArgs) || {}; - if (inputState.selectedCharacter) { - actionArgs.selectedCharacter = inputState.selectedCharacter; - } - // Actions may or may not have motions and operators. Do these first. - if (command.operator) { - this.processOperator(cm, vim, command); - } - if (command.motion) { - this.processMotion(cm, vim, command); - } - if (command.motion || command.operator) { - this.evalInput(cm, vim); - } - actionArgs.repeat = repeat || 1; - actionArgs.repeatIsExplicit = repeatIsExplicit; - actionArgs.registerName = inputState.registerName; - clearInputState(cm); - vim.lastMotion = null; - if (command.isEdit) { - this.recordLastEdit(vim, inputState, command); - } - actions[command.action](cm, actionArgs, vim); - }, - processSearch: function(cm, vim, command) { - if (!cm.getSearchCursor) { - // Search depends on SearchCursor. - return; - } - var forward = command.searchArgs.forward; - var wholeWordOnly = command.searchArgs.wholeWordOnly; - getSearchState(cm).setReversed(!forward); - var promptPrefix = (forward) ? '/' : '?'; - var originalQuery = getSearchState(cm).getQuery(); - var originalScrollPos = cm.getScrollInfo(); - function handleQuery(query, ignoreCase, smartCase) { - vimGlobalState.searchHistoryController.pushInput(query); - vimGlobalState.searchHistoryController.reset(); - try { - updateSearchQuery(cm, query, ignoreCase, smartCase); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + query); - return; - } - commandDispatcher.processMotion(cm, vim, { - type: 'motion', - motion: 'findNext', - motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist } - }); - } - function onPromptClose(query) { - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - handleQuery(query, true /** ignoreCase */, true /** smartCase */); - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - logSearchQuery(macroModeState, query); - } - } - function onPromptKeyUp(e, query, close) { - var keyName = CodeMirror.keyName(e), up; - if (keyName == 'Up' || keyName == 'Down') { - up = keyName == 'Up' ? true : false; - query = vimGlobalState.searchHistoryController.nextMatch(query, up) || ''; - close(query); - } else { - if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') - vimGlobalState.searchHistoryController.reset(); - } - var parsedQuery; - try { - parsedQuery = updateSearchQuery(cm, query, - true /** ignoreCase */, true /** smartCase */); - } catch (e) { - // Swallow bad regexes for incremental search. - } - if (parsedQuery) { - cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30); - } else { - clearSearchHighlight(cm); - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - } - } - function onPromptKeyDown(e, query, close) { - var keyName = CodeMirror.keyName(e); - if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') { - vimGlobalState.searchHistoryController.pushInput(query); - vimGlobalState.searchHistoryController.reset(); - updateSearchQuery(cm, originalQuery); - clearSearchHighlight(cm); - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - CodeMirror.e_stop(e); - close(); - cm.focus(); - } - } - switch (command.searchArgs.querySrc) { - case 'prompt': - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { - var query = macroModeState.replaySearchQueries.shift(); - handleQuery(query, true /** ignoreCase */, false /** smartCase */); - } else { - showPrompt(cm, { - onClose: onPromptClose, - prefix: promptPrefix, - desc: searchPromptDesc, - onKeyUp: onPromptKeyUp, - onKeyDown: onPromptKeyDown - }); - } - break; - case 'wordUnderCursor': - var word = expandWordUnderCursor(cm, false /** inclusive */, - true /** forward */, false /** bigWord */, - true /** noSymbol */); - var isKeyword = true; - if (!word) { - word = expandWordUnderCursor(cm, false /** inclusive */, - true /** forward */, false /** bigWord */, - false /** noSymbol */); - isKeyword = false; - } - if (!word) { - return; - } - var query = cm.getLine(word.start.line).substring(word.start.ch, - word.end.ch); - if (isKeyword && wholeWordOnly) { - query = '\\b' + query + '\\b'; - } else { - query = escapeRegex(query); - } - - // cachedCursor is used to save the old position of the cursor - // when * or # causes vim to seek for the nearest word and shift - // the cursor before entering the motion. - vimGlobalState.jumpList.cachedCursor = cm.getCursor(); - cm.setCursor(word.start); - - handleQuery(query, true /** ignoreCase */, false /** smartCase */); - break; - } - }, - processEx: function(cm, vim, command) { - function onPromptClose(input) { - // Give the prompt some time to close so that if processCommand shows - // an error, the elements don't overlap. - vimGlobalState.exCommandHistoryController.pushInput(input); - vimGlobalState.exCommandHistoryController.reset(); - exCommandDispatcher.processCommand(cm, input); - } - function onPromptKeyDown(e, input, close) { - var keyName = CodeMirror.keyName(e), up; - if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') { - vimGlobalState.exCommandHistoryController.pushInput(input); - vimGlobalState.exCommandHistoryController.reset(); - CodeMirror.e_stop(e); - close(); - cm.focus(); - } - if (keyName == 'Up' || keyName == 'Down') { - up = keyName == 'Up' ? true : false; - input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || ''; - close(input); - } else { - if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') - vimGlobalState.exCommandHistoryController.reset(); - } - } - if (command.type == 'keyToEx') { - // Handle user defined Ex to Ex mappings - exCommandDispatcher.processCommand(cm, command.exArgs.input); - } else { - if (vim.visualMode) { - showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>', - onKeyDown: onPromptKeyDown}); - } else { - showPrompt(cm, { onClose: onPromptClose, prefix: ':', - onKeyDown: onPromptKeyDown}); - } - } - }, - evalInput: function(cm, vim) { - // If the motion comand is set, execute both the operator and motion. - // Otherwise return. - var inputState = vim.inputState; - var motion = inputState.motion; - var motionArgs = inputState.motionArgs || {}; - var operator = inputState.operator; - var operatorArgs = inputState.operatorArgs || {}; - var registerName = inputState.registerName; - var sel = vim.sel; - // TODO: Make sure cm and vim selections are identical outside visual mode. - var origHead = copyCursor(vim.visualMode ? sel.head: cm.getCursor('head')); - var origAnchor = copyCursor(vim.visualMode ? sel.anchor : cm.getCursor('anchor')); - var oldHead = copyCursor(origHead); - var oldAnchor = copyCursor(origAnchor); - var newHead, newAnchor; - var repeat; - if (operator) { - this.recordLastEdit(vim, inputState); - } - if (inputState.repeatOverride !== undefined) { - // If repeatOverride is specified, that takes precedence over the - // input state's repeat. Used by Ex mode and can be user defined. - repeat = inputState.repeatOverride; - } else { - repeat = inputState.getRepeat(); - } - if (repeat > 0 && motionArgs.explicitRepeat) { - motionArgs.repeatIsExplicit = true; - } else if (motionArgs.noRepeat || - (!motionArgs.explicitRepeat && repeat === 0)) { - repeat = 1; - motionArgs.repeatIsExplicit = false; - } - if (inputState.selectedCharacter) { - // If there is a character input, stick it in all of the arg arrays. - motionArgs.selectedCharacter = operatorArgs.selectedCharacter = - inputState.selectedCharacter; - } - motionArgs.repeat = repeat; - clearInputState(cm); - if (motion) { - var motionResult = motions[motion](cm, origHead, motionArgs, vim); - vim.lastMotion = motions[motion]; - if (!motionResult) { - return; - } - if (motionArgs.toJumplist) { - var jumpList = vimGlobalState.jumpList; - // if the current motion is # or *, use cachedCursor - var cachedCursor = jumpList.cachedCursor; - if (cachedCursor) { - recordJumpPosition(cm, cachedCursor, motionResult); - delete jumpList.cachedCursor; - } else { - recordJumpPosition(cm, origHead, motionResult); - } - } - if (motionResult instanceof Array) { - newAnchor = motionResult[0]; - newHead = motionResult[1]; - } else { - newHead = motionResult; - } - // TODO: Handle null returns from motion commands better. - if (!newHead) { - newHead = copyCursor(origHead); - } - if (vim.visualMode) { - if (!(vim.visualBlock && newHead.ch === Infinity)) { - newHead = clipCursorToContent(cm, newHead, vim.visualBlock); - } - if (newAnchor) { - newAnchor = clipCursorToContent(cm, newAnchor, true); - } - newAnchor = newAnchor || oldAnchor; - sel.anchor = newAnchor; - sel.head = newHead; - updateCmSelection(cm); - updateMark(cm, vim, '<', - cursorIsBefore(newAnchor, newHead) ? newAnchor - : newHead); - updateMark(cm, vim, '>', - cursorIsBefore(newAnchor, newHead) ? newHead - : newAnchor); - } else if (!operator) { - newHead = clipCursorToContent(cm, newHead); - cm.setCursor(newHead.line, newHead.ch); - } - } - if (operator) { - if (operatorArgs.lastSel) { - // Replaying a visual mode operation - newAnchor = oldAnchor; - var lastSel = operatorArgs.lastSel; - var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line); - var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch); - if (lastSel.visualLine) { - // Linewise Visual mode: The same number of lines. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); - } else if (lastSel.visualBlock) { - // Blockwise Visual mode: The same number of lines and columns. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset); - } else if (lastSel.head.line == lastSel.anchor.line) { - // Normal Visual mode within one line: The same number of characters. - newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset); - } else { - // Normal Visual mode with several lines: The same number of lines, in the - // last line the same number of characters as in the last line the last time. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); - } - vim.visualMode = true; - vim.visualLine = lastSel.visualLine; - vim.visualBlock = lastSel.visualBlock; - sel = vim.sel = { - anchor: newAnchor, - head: newHead - }; - updateCmSelection(cm); - } else if (vim.visualMode) { - operatorArgs.lastSel = { - anchor: copyCursor(sel.anchor), - head: copyCursor(sel.head), - visualBlock: vim.visualBlock, - visualLine: vim.visualLine - }; - } - var curStart, curEnd, linewise, mode; - var cmSel; - if (vim.visualMode) { - // Init visual op - curStart = cursorMin(sel.head, sel.anchor); - curEnd = cursorMax(sel.head, sel.anchor); - linewise = vim.visualLine || operatorArgs.linewise; - mode = vim.visualBlock ? 'block' : - linewise ? 'line' : - 'char'; - cmSel = makeCmSelection(cm, { - anchor: curStart, - head: curEnd - }, mode); - if (linewise) { - var ranges = cmSel.ranges; - if (mode == 'block') { - // Linewise operators in visual block mode extend to end of line - for (var i = 0; i < ranges.length; i++) { - ranges[i].head.ch = lineLength(cm, ranges[i].head.line); - } - } else if (mode == 'line') { - ranges[0].head = Pos(ranges[0].head.line + 1, 0); - } - } - } else { - // Init motion op - curStart = copyCursor(newAnchor || oldAnchor); - curEnd = copyCursor(newHead || oldHead); - if (cursorIsBefore(curEnd, curStart)) { - var tmp = curStart; - curStart = curEnd; - curEnd = tmp; - } - linewise = motionArgs.linewise || operatorArgs.linewise; - if (linewise) { - // Expand selection to entire line. - expandSelectionToLine(cm, curStart, curEnd); - } else if (motionArgs.forward) { - // Clip to trailing newlines only if the motion goes forward. - clipToLine(cm, curStart, curEnd); - } - mode = 'char'; - var exclusive = !motionArgs.inclusive || linewise; - cmSel = makeCmSelection(cm, { - anchor: curStart, - head: curEnd - }, mode, exclusive); - } - cm.setSelections(cmSel.ranges, cmSel.primary); - vim.lastMotion = null; - operatorArgs.repeat = repeat; // For indent in visual mode. - operatorArgs.registerName = registerName; - // Keep track of linewise as it affects how paste and change behave. - operatorArgs.linewise = linewise; - var operatorMoveTo = operators[operator]( - cm, operatorArgs, cmSel.ranges, oldAnchor, newHead); - if (vim.visualMode) { - exitVisualMode(cm, operatorMoveTo != null); - } - if (operatorMoveTo) { - cm.setCursor(operatorMoveTo); - } - } - }, - recordLastEdit: function(vim, inputState, actionCommand) { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { return; } - vim.lastEditInputState = inputState; - vim.lastEditActionCommand = actionCommand; - macroModeState.lastInsertModeChanges.changes = []; - macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false; - } - }; - - /** - * typedef {Object{line:number,ch:number}} Cursor An object containing the - * position of the cursor. - */ - // All of the functions below return Cursor objects. - var motions = { - moveToTopLine: function(cm, _head, motionArgs) { - var line = getUserVisibleLines(cm).top + motionArgs.repeat -1; - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - moveToMiddleLine: function(cm) { - var range = getUserVisibleLines(cm); - var line = Math.floor((range.top + range.bottom) * 0.5); - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - moveToBottomLine: function(cm, _head, motionArgs) { - var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1; - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - expandToLine: function(_cm, head, motionArgs) { - // Expands forward to end of line, and then to next line if repeat is - // >1. Does not handle backward motion! - var cur = head; - return Pos(cur.line + motionArgs.repeat - 1, Infinity); - }, - findNext: function(cm, _head, motionArgs) { - var state = getSearchState(cm); - var query = state.getQuery(); - if (!query) { - return; - } - var prev = !motionArgs.forward; - // If search is initiated with ? instead of /, negate direction. - prev = (state.isReversed()) ? !prev : prev; - highlightSearchMatches(cm, query); - return findNext(cm, prev/** prev */, query, motionArgs.repeat); - }, - goToMark: function(cm, _head, motionArgs, vim) { - var mark = vim.marks[motionArgs.selectedCharacter]; - if (mark) { - var pos = mark.find(); - return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos; - } - return null; - }, - moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) { - if (vim.visualBlock && motionArgs.sameLine) { - var sel = vim.sel; - return [ - clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)), - clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch)) - ]; - } else { - return ([vim.sel.head, vim.sel.anchor]); - } - }, - jumpToMark: function(cm, head, motionArgs, vim) { - var best = head; - for (var i = 0; i < motionArgs.repeat; i++) { - var cursor = best; - for (var key in vim.marks) { - if (!isLowerCase(key)) { - continue; - } - var mark = vim.marks[key].find(); - var isWrongDirection = (motionArgs.forward) ? - cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark); - - if (isWrongDirection) { - continue; - } - if (motionArgs.linewise && (mark.line == cursor.line)) { - continue; - } - - var equal = cursorEqual(cursor, best); - var between = (motionArgs.forward) ? - cursorIsBetween(cursor, mark, best) : - cursorIsBetween(best, mark, cursor); - - if (equal || between) { - best = mark; - } - } - } - - if (motionArgs.linewise) { - // Vim places the cursor on the first non-whitespace character of - // the line if there is one, else it places the cursor at the end - // of the line, regardless of whether a mark was found. - best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line))); - } - return best; - }, - moveByCharacters: function(_cm, head, motionArgs) { - var cur = head; - var repeat = motionArgs.repeat; - var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; - return Pos(cur.line, ch); - }, - moveByLines: function(cm, head, motionArgs, vim) { - var cur = head; - var endCh = cur.ch; - // Depending what our last motion was, we may want to do different - // things. If our last motion was moving vertically, we want to - // preserve the HPos from our last horizontal move. If our last motion - // was going to the end of a line, moving vertically we should go to - // the end of the line, etc. - switch (vim.lastMotion) { - case this.moveByLines: - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveToColumn: - case this.moveToEol: - endCh = vim.lastHPos; - break; - default: - vim.lastHPos = endCh; - } - var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0); - var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; - var first = cm.firstLine(); - var last = cm.lastLine(); - // Vim cancels linewise motions that start on an edge and move beyond - // that edge. It does not cancel motions that do not start on an edge. - if ((line < first && cur.line == first) || - (line > last && cur.line == last)) { - return; - } - if (motionArgs.toFirstChar){ - endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line)); - vim.lastHPos = endCh; - } - vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left; - return Pos(line, endCh); - }, - moveByDisplayLines: function(cm, head, motionArgs, vim) { - var cur = head; - switch (vim.lastMotion) { - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveByLines: - case this.moveToColumn: - case this.moveToEol: - break; - default: - vim.lastHSPos = cm.charCoords(cur,'div').left; - } - var repeat = motionArgs.repeat; - var res=cm.findPosV(cur,(motionArgs.forward ? repeat : -repeat),'line',vim.lastHSPos); - if (res.hitSide) { - if (motionArgs.forward) { - var lastCharCoords = cm.charCoords(res, 'div'); - var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos }; - var res = cm.coordsChar(goalCoords, 'div'); - } else { - var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div'); - resCoords.left = vim.lastHSPos; - res = cm.coordsChar(resCoords, 'div'); - } - } - vim.lastHPos = res.ch; - return res; - }, - moveByPage: function(cm, head, motionArgs) { - // CodeMirror only exposes functions that move the cursor page down, so - // doing this bad hack to move the cursor and move it back. evalInput - // will move the cursor to where it should be in the end. - var curStart = head; - var repeat = motionArgs.repeat; - return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); - }, - moveByParagraph: function(cm, head, motionArgs) { - var dir = motionArgs.forward ? 1 : -1; - return findParagraph(cm, head, motionArgs.repeat, dir); - }, - moveByScroll: function(cm, head, motionArgs, vim) { - var scrollbox = cm.getScrollInfo(); - var curEnd = null; - var repeat = motionArgs.repeat; - if (!repeat) { - repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); - } - var orig = cm.charCoords(head, 'local'); - motionArgs.repeat = repeat; - var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim); - if (!curEnd) { - return null; - } - var dest = cm.charCoords(curEnd, 'local'); - cm.scrollTo(null, scrollbox.top + dest.top - orig.top); - return curEnd; - }, - moveByWords: function(cm, head, motionArgs) { - return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward, - !!motionArgs.wordEnd, !!motionArgs.bigWord); - }, - moveTillCharacter: function(cm, _head, motionArgs) { - var repeat = motionArgs.repeat; - var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter); - var increment = motionArgs.forward ? -1 : 1; - recordLastCharacterSearch(increment, motionArgs); - if (!curEnd) return null; - curEnd.ch += increment; - return curEnd; - }, - moveToCharacter: function(cm, head, motionArgs) { - var repeat = motionArgs.repeat; - recordLastCharacterSearch(0, motionArgs); - return moveToCharacter(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || head; - }, - moveToSymbol: function(cm, head, motionArgs) { - var repeat = motionArgs.repeat; - return findSymbol(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || head; - }, - moveToColumn: function(cm, head, motionArgs, vim) { - var repeat = motionArgs.repeat; - // repeat is equivalent to which column we want to move to! - vim.lastHPos = repeat - 1; - vim.lastHSPos = cm.charCoords(head,'div').left; - return moveToColumn(cm, repeat); - }, - moveToEol: function(cm, head, motionArgs, vim) { - var cur = head; - vim.lastHPos = Infinity; - var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); - var end=cm.clipPos(retval); - end.ch--; - vim.lastHSPos = cm.charCoords(end,'div').left; - return retval; - }, - moveToFirstNonWhiteSpaceCharacter: function(cm, head) { - // Go to the start of the line where the text begins, or the end for - // whitespace-only lines - var cursor = head; - return Pos(cursor.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); - }, - moveToMatchedSymbol: function(cm, head) { - var cursor = head; - var line = cursor.line; - var ch = cursor.ch; - var lineText = cm.getLine(line); - var symbol; - do { - symbol = lineText.charAt(ch++); - if (symbol && isMatchableSymbol(symbol)) { - var style = cm.getTokenTypeAt(Pos(line, ch)); - if (style !== "string" && style !== "comment") { - break; - } - } - } while (symbol); - if (symbol) { - var matched = cm.findMatchingBracket(Pos(line, ch)); - return matched.to; - } else { - return cursor; - } - }, - moveToStartOfLine: function(_cm, head) { - return Pos(head.line, 0); - }, - moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) { - var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); - if (motionArgs.repeatIsExplicit) { - lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); - } - return Pos(lineNum, - findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); - }, - textObjectManipulation: function(cm, head, motionArgs, vim) { - // TODO: lots of possible exceptions that can be thrown here. Try da( - // outside of a () block. - - // TODO: adding <> >< to this map doesn't work, presumably because - // they're operators - var mirroredPairs = {'(': ')', ')': '(', - '{': '}', '}': '{', - '[': ']', ']': '['}; - var selfPaired = {'\'': true, '"': true}; - - var character = motionArgs.selectedCharacter; - // 'b' refers to '()' block. - // 'B' refers to '{}' block. - if (character == 'b') { - character = '('; - } else if (character == 'B') { - character = '{'; - } - - // Inclusive is the difference between a and i - // TODO: Instead of using the additional text object map to perform text - // object operations, merge the map into the defaultKeyMap and use - // motionArgs to define behavior. Define separate entries for 'aw', - // 'iw', 'a[', 'i[', etc. - var inclusive = !motionArgs.textObjectInner; - - var tmp; - if (mirroredPairs[character]) { - tmp = selectCompanionObject(cm, head, character, inclusive); - } else if (selfPaired[character]) { - tmp = findBeginningAndEnd(cm, head, character, inclusive); - } else if (character === 'W') { - tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, - true /** bigWord */); - } else if (character === 'w') { - tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, - false /** bigWord */); - } else if (character === 'p') { - tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive); - motionArgs.linewise = true; - if (vim.visualMode) { - if (!vim.visualLine) { vim.visualLine = true; } - } else { - var operatorArgs = vim.inputState.operatorArgs; - if (operatorArgs) { operatorArgs.linewise = true; } - tmp.end.line--; - } - } else { - // No text object defined for this, don't move. - return null; - } - - if (!cm.state.vim.visualMode) { - return [tmp.start, tmp.end]; - } else { - return expandSelection(cm, tmp.start, tmp.end); - } - }, - - repeatLastCharacterSearch: function(cm, head, motionArgs) { - var lastSearch = vimGlobalState.lastChararacterSearch; - var repeat = motionArgs.repeat; - var forward = motionArgs.forward === lastSearch.forward; - var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1); - cm.moveH(-increment, 'char'); - motionArgs.inclusive = forward ? true : false; - var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); - if (!curEnd) { - cm.moveH(increment, 'char'); - return head; - } - curEnd.ch += increment; - return curEnd; - } - }; - - function defineMotion(name, fn) { - motions[name] = fn; - } - - function fillArray(val, times) { - var arr = []; - for (var i = 0; i < times; i++) { - arr.push(val); - } - return arr; - } - /** - * An operator acts on a text selection. It receives the list of selections - * as input. The corresponding CodeMirror selection is guaranteed to - * match the input selection. - */ - var operators = { - change: function(cm, args, ranges) { - var finalHead, text; - var vim = cm.state.vim; - vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock; - if (!vim.visualMode) { - var anchor = ranges[0].anchor, - head = ranges[0].head; - text = cm.getRange(anchor, head); - if (!isWhiteSpaceString(text)) { - // Exclude trailing whitespace if the range is not all whitespace. - var match = (/\s+$/).exec(text); - if (match) { - head = offsetCursor(head, 0, - match[0].length); - text = text.slice(0, - match[0].length); - } - } - var wasLastLine = head.line - 1 == cm.lastLine(); - cm.replaceRange('', anchor, head); - if (args.linewise && !wasLastLine) { - // Push the next line back down, if there is a next line. - CodeMirror.commands.newlineAndIndent(cm); - // null ch so setCursor moves to end of line. - anchor.ch = null; - } - finalHead = anchor; - } else { - text = cm.getSelection(); - var replacement = fillArray('', ranges.length); - cm.replaceSelections(replacement); - finalHead = cursorMin(ranges[0].head, ranges[0].anchor); - } - vimGlobalState.registerController.pushText( - args.registerName, 'change', text, - args.linewise, ranges.length > 1); - actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim); - }, - // delete is a javascript keyword. - 'delete': function(cm, args, ranges) { - var finalHead, text; - var vim = cm.state.vim; - if (!vim.visualBlock) { - var anchor = ranges[0].anchor, - head = ranges[0].head; - if (args.linewise && - head.line != cm.firstLine() && - anchor.line == cm.lastLine() && - anchor.line == head.line - 1) { - // Special case for dd on last line (and first line). - if (anchor.line == cm.firstLine()) { - anchor.ch = 0; - } else { - anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1)); - } - } - text = cm.getRange(anchor, head); - cm.replaceRange('', anchor, head); - finalHead = anchor; - if (args.linewise) { - finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor); - } - } else { - text = cm.getSelection(); - var replacement = fillArray('', ranges.length); - cm.replaceSelections(replacement); - finalHead = ranges[0].anchor; - } - vimGlobalState.registerController.pushText( - args.registerName, 'delete', text, - args.linewise, vim.visualBlock); - return clipCursorToContent(cm, finalHead); - }, - indent: function(cm, args, ranges) { - var vim = cm.state.vim; - var startLine = ranges[0].anchor.line; - var endLine = vim.visualBlock ? - ranges[ranges.length - 1].anchor.line : - ranges[0].head.line; - // In visual mode, n> shifts the selection right n times, instead of - // shifting n lines right once. - var repeat = (vim.visualMode) ? args.repeat : 1; - if (args.linewise) { - // The only way to delete a newline is to delete until the start of - // the next line, so in linewise mode evalInput will include the next - // line. We don't want this in indent, so we go back a line. - endLine--; - } - for (var i = startLine; i <= endLine; i++) { - for (var j = 0; j < repeat; j++) { - cm.indentLine(i, args.indentRight); - } - } - return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor); - }, - changeCase: function(cm, args, ranges, oldAnchor, newHead) { - var selections = cm.getSelections(); - var swapped = []; - var toLower = args.toLower; - for (var j = 0; j < selections.length; j++) { - var toSwap = selections[j]; - var text = ''; - if (toLower === true) { - text = toSwap.toLowerCase(); - } else if (toLower === false) { - text = toSwap.toUpperCase(); - } else { - for (var i = 0; i < toSwap.length; i++) { - var character = toSwap.charAt(i); - text += isUpperCase(character) ? character.toLowerCase() : - character.toUpperCase(); - } - } - swapped.push(text); - } - cm.replaceSelections(swapped); - if (args.shouldMoveCursor){ - return newHead; - } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) { - return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor); - } else if (args.linewise){ - return oldAnchor; - } else { - return cursorMin(ranges[0].anchor, ranges[0].head); - } - }, - yank: function(cm, args, ranges, oldAnchor) { - var vim = cm.state.vim; - var text = cm.getSelection(); - var endPos = vim.visualMode - ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor) - : oldAnchor; - vimGlobalState.registerController.pushText( - args.registerName, 'yank', - text, args.linewise, vim.visualBlock); - return endPos; - } - }; - - function defineOperator(name, fn) { - operators[name] = fn; - } - - var actions = { - jumpListWalk: function(cm, actionArgs, vim) { - if (vim.visualMode) { - return; - } - var repeat = actionArgs.repeat; - var forward = actionArgs.forward; - var jumpList = vimGlobalState.jumpList; - - var mark = jumpList.move(cm, forward ? repeat : -repeat); - var markPos = mark ? mark.find() : undefined; - markPos = markPos ? markPos : cm.getCursor(); - cm.setCursor(markPos); - }, - scroll: function(cm, actionArgs, vim) { - if (vim.visualMode) { - return; - } - var repeat = actionArgs.repeat || 1; - var lineHeight = cm.defaultTextHeight(); - var top = cm.getScrollInfo().top; - var delta = lineHeight * repeat; - var newPos = actionArgs.forward ? top + delta : top - delta; - var cursor = copyCursor(cm.getCursor()); - var cursorCoords = cm.charCoords(cursor, 'local'); - if (actionArgs.forward) { - if (newPos > cursorCoords.top) { - cursor.line += (newPos - cursorCoords.top) / lineHeight; - cursor.line = Math.ceil(cursor.line); - cm.setCursor(cursor); - cursorCoords = cm.charCoords(cursor, 'local'); - cm.scrollTo(null, cursorCoords.top); - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos); - } - } else { - var newBottom = newPos + cm.getScrollInfo().clientHeight; - if (newBottom < cursorCoords.bottom) { - cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight; - cursor.line = Math.floor(cursor.line); - cm.setCursor(cursor); - cursorCoords = cm.charCoords(cursor, 'local'); - cm.scrollTo( - null, cursorCoords.bottom - cm.getScrollInfo().clientHeight); - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos); - } - } - }, - scrollToCursor: function(cm, actionArgs) { - var lineNum = cm.getCursor().line; - var charCoords = cm.charCoords(Pos(lineNum, 0), 'local'); - var height = cm.getScrollInfo().clientHeight; - var y = charCoords.top; - var lineHeight = charCoords.bottom - y; - switch (actionArgs.position) { - case 'center': y = y - (height / 2) + lineHeight; - break; - case 'bottom': y = y - height + lineHeight*1.4; - break; - case 'top': y = y + lineHeight*0.4; - break; - } - cm.scrollTo(null, y); - }, - replayMacro: function(cm, actionArgs, vim) { - var registerName = actionArgs.selectedCharacter; - var repeat = actionArgs.repeat; - var macroModeState = vimGlobalState.macroModeState; - if (registerName == '@') { - registerName = macroModeState.latestRegister; - } - while(repeat--){ - executeMacroRegister(cm, vim, macroModeState, registerName); - } - }, - enterMacroRecordMode: function(cm, actionArgs) { - var macroModeState = vimGlobalState.macroModeState; - var registerName = actionArgs.selectedCharacter; - macroModeState.enterMacroRecordMode(cm, registerName); - }, - enterInsertMode: function(cm, actionArgs, vim) { - if (cm.getOption('readOnly')) { return; } - vim.insertMode = true; - vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; - var insertAt = (actionArgs) ? actionArgs.insertAt : null; - var sel = vim.sel; - var head = actionArgs.head || cm.getCursor('head'); - var height = cm.listSelections().length; - if (insertAt == 'eol') { - head = Pos(head.line, lineLength(cm, head.line)); - } else if (insertAt == 'charAfter') { - head = offsetCursor(head, 0, 1); - } else if (insertAt == 'firstNonBlank') { - head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head); - } else if (insertAt == 'startOfSelectedArea') { - if (!vim.visualBlock) { - if (sel.head.line < sel.anchor.line) { - head = sel.head; - } else { - head = Pos(sel.anchor.line, 0); - } - } else { - head = Pos( - Math.min(sel.head.line, sel.anchor.line), - Math.min(sel.head.ch, sel.anchor.ch)); - height = Math.abs(sel.head.line - sel.anchor.line) + 1; - } - } else if (insertAt == 'endOfSelectedArea') { - if (!vim.visualBlock) { - if (sel.head.line >= sel.anchor.line) { - head = offsetCursor(sel.head, 0, 1); - } else { - head = Pos(sel.anchor.line, 0); - } - } else { - head = Pos( - Math.min(sel.head.line, sel.anchor.line), - Math.max(sel.head.ch + 1, sel.anchor.ch)); - height = Math.abs(sel.head.line - sel.anchor.line) + 1; - } - } else if (insertAt == 'inplace') { - if (vim.visualMode){ - return; - } - } - cm.setOption('keyMap', 'vim-insert'); - cm.setOption('disableInput', false); - if (actionArgs && actionArgs.replace) { - // Handle Replace-mode as a special case of insert mode. - cm.toggleOverwrite(true); - cm.setOption('keyMap', 'vim-replace'); - CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); - } else { - cm.setOption('keyMap', 'vim-insert'); - CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); - } - if (!vimGlobalState.macroModeState.isPlaying) { - // Only record if not replaying. - cm.on('change', onChange); - CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); - } - if (vim.visualMode) { - exitVisualMode(cm); - } - selectForInsert(cm, head, height); - }, - toggleVisualMode: function(cm, actionArgs, vim) { - var repeat = actionArgs.repeat; - var anchor = cm.getCursor(); - var head; - // TODO: The repeat should actually select number of characters/lines - // equal to the repeat times the size of the previous visual - // operation. - if (!vim.visualMode) { - // Entering visual mode - vim.visualMode = true; - vim.visualLine = !!actionArgs.linewise; - vim.visualBlock = !!actionArgs.blockwise; - head = clipCursorToContent( - cm, Pos(anchor.line, anchor.ch + repeat - 1), - true /** includeLineBreak */); - vim.sel = { - anchor: anchor, - head: head - }; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); - updateCmSelection(cm); - updateMark(cm, vim, '<', cursorMin(anchor, head)); - updateMark(cm, vim, '>', cursorMax(anchor, head)); - } else if (vim.visualLine ^ actionArgs.linewise || - vim.visualBlock ^ actionArgs.blockwise) { - // Toggling between modes - vim.visualLine = !!actionArgs.linewise; - vim.visualBlock = !!actionArgs.blockwise; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); - updateCmSelection(cm); - } else { - exitVisualMode(cm); - } - }, - reselectLastSelection: function(cm, _actionArgs, vim) { - var lastSelection = vim.lastSelection; - if (vim.visualMode) { - updateLastSelection(cm, vim); - } - if (lastSelection) { - var anchor = lastSelection.anchorMark.find(); - var head = lastSelection.headMark.find(); - if (!anchor || !head) { - // If the marks have been destroyed due to edits, do nothing. - return; - } - vim.sel = { - anchor: anchor, - head: head - }; - vim.visualMode = true; - vim.visualLine = lastSelection.visualLine; - vim.visualBlock = lastSelection.visualBlock; - updateCmSelection(cm); - updateMark(cm, vim, '<', cursorMin(anchor, head)); - updateMark(cm, vim, '>', cursorMax(anchor, head)); - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'visual', - subMode: vim.visualLine ? 'linewise' : - vim.visualBlock ? 'blockwise' : ''}); - } - }, - joinLines: function(cm, actionArgs, vim) { - var curStart, curEnd; - if (vim.visualMode) { - curStart = cm.getCursor('anchor'); - curEnd = cm.getCursor('head'); - if (cursorIsBefore(curEnd, curStart)) { - var tmp = curEnd; - curEnd = curStart; - curStart = tmp; - } - curEnd.ch = lineLength(cm, curEnd.line) - 1; - } else { - // Repeat is the number of lines to join. Minimum 2 lines. - var repeat = Math.max(actionArgs.repeat, 2); - curStart = cm.getCursor(); - curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1, - Infinity)); - } - var finalCh = 0; - for (var i = curStart.line; i < curEnd.line; i++) { - finalCh = lineLength(cm, curStart.line); - var tmp = Pos(curStart.line + 1, - lineLength(cm, curStart.line + 1)); - var text = cm.getRange(curStart, tmp); - text = text.replace(/\n\s*/g, ' '); - cm.replaceRange(text, curStart, tmp); - } - var curFinalPos = Pos(curStart.line, finalCh); - if (vim.visualMode) { - exitVisualMode(cm, false); - } - cm.setCursor(curFinalPos); - }, - newLineAndEnterInsertMode: function(cm, actionArgs, vim) { - vim.insertMode = true; - var insertAt = copyCursor(cm.getCursor()); - if (insertAt.line === cm.firstLine() && !actionArgs.after) { - // Special case for inserting newline before start of document. - cm.replaceRange('\n', Pos(cm.firstLine(), 0)); - cm.setCursor(cm.firstLine(), 0); - } else { - insertAt.line = (actionArgs.after) ? insertAt.line : - insertAt.line - 1; - insertAt.ch = lineLength(cm, insertAt.line); - cm.setCursor(insertAt); - var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment || - CodeMirror.commands.newlineAndIndent; - newlineFn(cm); - } - this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim); - }, - paste: function(cm, actionArgs, vim) { - var cur = copyCursor(cm.getCursor()); - var register = vimGlobalState.registerController.getRegister( - actionArgs.registerName); - var text = register.toString(); - if (!text) { - return; - } - if (actionArgs.matchIndent) { - var tabSize = cm.getOption("tabSize"); - // length that considers tabs and tabSize - var whitespaceLength = function(str) { - var tabs = (str.split("\t").length - 1); - var spaces = (str.split(" ").length - 1); - return tabs * tabSize + spaces * 1; - }; - var currentLine = cm.getLine(cm.getCursor().line); - var indent = whitespaceLength(currentLine.match(/^\s*/)[0]); - // chomp last newline b/c don't want it to match /^\s*/gm - var chompedText = text.replace(/\n$/, ''); - var wasChomped = text !== chompedText; - var firstIndent = whitespaceLength(text.match(/^\s*/)[0]); - var text = chompedText.replace(/^\s*/gm, function(wspace) { - var newIndent = indent + (whitespaceLength(wspace) - firstIndent); - if (newIndent < 0) { - return ""; - } - else if (cm.getOption("indentWithTabs")) { - var quotient = Math.floor(newIndent / tabSize); - return Array(quotient + 1).join('\t'); - } - else { - return Array(newIndent + 1).join(' '); - } - }); - text += wasChomped ? "\n" : ""; - } - if (actionArgs.repeat > 1) { - var text = Array(actionArgs.repeat + 1).join(text); - } - var linewise = register.linewise; - var blockwise = register.blockwise; - if (linewise) { - if(vim.visualMode) { - text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; - } else if (actionArgs.after) { - // Move the newline at the end to the start instead, and paste just - // before the newline character of the line we are on right now. - text = '\n' + text.slice(0, text.length - 1); - cur.ch = lineLength(cm, cur.line); - } else { - cur.ch = 0; - } - } else { - if (blockwise) { - text = text.split('\n'); - for (var i = 0; i < text.length; i++) { - text[i] = (text[i] == '') ? ' ' : text[i]; - } - } - cur.ch += actionArgs.after ? 1 : 0; - } - var curPosFinal; - var idx; - if (vim.visualMode) { - // save the pasted text for reselection if the need arises - vim.lastPastedText = text; - var lastSelectionCurEnd; - var selectedArea = getSelectedAreaRange(cm, vim); - var selectionStart = selectedArea[0]; - var selectionEnd = selectedArea[1]; - var selectedText = cm.getSelection(); - var selections = cm.listSelections(); - var emptyStrings = new Array(selections.length).join('1').split('1'); - // save the curEnd marker before it get cleared due to cm.replaceRange. - if (vim.lastSelection) { - lastSelectionCurEnd = vim.lastSelection.headMark.find(); - } - // push the previously selected text to unnamed register - vimGlobalState.registerController.unnamedRegister.setText(selectedText); - if (blockwise) { - // first delete the selected text - cm.replaceSelections(emptyStrings); - // Set new selections as per the block length of the yanked text - selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); - cm.replaceSelections(text); - curPosFinal = selectionStart; - } else if (vim.visualBlock) { - cm.replaceSelections(emptyStrings); - cm.setCursor(selectionStart); - cm.replaceRange(text, selectionStart, selectionStart); - curPosFinal = selectionStart; - } else { - cm.replaceRange(text, selectionStart, selectionEnd); - curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1); - } - // restore the the curEnd marker - if(lastSelectionCurEnd) { - vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd); - } - if (linewise) { - curPosFinal.ch=0; - } - } else { - if (blockwise) { - cm.setCursor(cur); - for (var i = 0; i < text.length; i++) { - var line = cur.line+i; - if (line > cm.lastLine()) { - cm.replaceRange('\n', Pos(line, 0)); - } - var lastCh = lineLength(cm, line); - if (lastCh < cur.ch) { - extendLineToColumn(cm, line, cur.ch); - } - } - cm.setCursor(cur); - selectBlock(cm, Pos(cur.line + text.length-1, cur.ch)); - cm.replaceSelections(text); - curPosFinal = cur; - } else { - cm.replaceRange(text, cur); - // Now fine tune the cursor to where we want it. - if (linewise && actionArgs.after) { - curPosFinal = Pos( - cur.line + 1, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))); - } else if (linewise && !actionArgs.after) { - curPosFinal = Pos( - cur.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))); - } else if (!linewise && actionArgs.after) { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length - 1); - } else { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length); - } - } - } - if (vim.visualMode) { - exitVisualMode(cm, false); - } - cm.setCursor(curPosFinal); - }, - undo: function(cm, actionArgs) { - cm.operation(function() { - repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)(); - cm.setCursor(cm.getCursor('anchor')); - }); - }, - redo: function(cm, actionArgs) { - repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)(); - }, - setRegister: function(_cm, actionArgs, vim) { - vim.inputState.registerName = actionArgs.selectedCharacter; - }, - setMark: function(cm, actionArgs, vim) { - var markName = actionArgs.selectedCharacter; - updateMark(cm, vim, markName, cm.getCursor()); - }, - replace: function(cm, actionArgs, vim) { - var replaceWith = actionArgs.selectedCharacter; - var curStart = cm.getCursor(); - var replaceTo; - var curEnd; - var selections = cm.listSelections(); - if (vim.visualMode) { - curStart = cm.getCursor('start'); - curEnd = cm.getCursor('end'); - } else { - var line = cm.getLine(curStart.line); - replaceTo = curStart.ch + actionArgs.repeat; - if (replaceTo > line.length) { - replaceTo=line.length; - } - curEnd = Pos(curStart.line, replaceTo); - } - if (replaceWith=='\n') { - if (!vim.visualMode) cm.replaceRange('', curStart, curEnd); - // special case, where vim help says to replace by just one line-break - (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm); - } else { - var replaceWithStr = cm.getRange(curStart, curEnd); - //replace all characters in range by selected, but keep linebreaks - replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith); - if (vim.visualBlock) { - // Tabs are split in visua block before replacing - var spaces = new Array(cm.getOption("tabSize")+1).join(' '); - replaceWithStr = cm.getSelection(); - replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); - cm.replaceSelections(replaceWithStr); - } else { - cm.replaceRange(replaceWithStr, curStart, curEnd); - } - if (vim.visualMode) { - curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ? - selections[0].anchor : selections[0].head; - cm.setCursor(curStart); - exitVisualMode(cm, false); - } else { - cm.setCursor(offsetCursor(curEnd, 0, -1)); - } - } - }, - incrementNumberToken: function(cm, actionArgs) { - var cur = cm.getCursor(); - var lineStr = cm.getLine(cur.line); - var re = /-?\d+/g; - var match; - var start; - var end; - var numberStr; - var token; - while ((match = re.exec(lineStr)) !== null) { - token = match[0]; - start = match.index; - end = start + token.length; - if (cur.ch < end)break; - } - if (!actionArgs.backtrack && (end <= cur.ch))return; - if (token) { - var increment = actionArgs.increase ? 1 : -1; - var number = parseInt(token) + (increment * actionArgs.repeat); - var from = Pos(cur.line, start); - var to = Pos(cur.line, end); - numberStr = number.toString(); - cm.replaceRange(numberStr, from, to); - } else { - return; - } - cm.setCursor(Pos(cur.line, start + numberStr.length - 1)); - }, - repeatLastEdit: function(cm, actionArgs, vim) { - var lastEditInputState = vim.lastEditInputState; - if (!lastEditInputState) { return; } - var repeat = actionArgs.repeat; - if (repeat && actionArgs.repeatIsExplicit) { - vim.lastEditInputState.repeatOverride = repeat; - } else { - repeat = vim.lastEditInputState.repeatOverride || repeat; - } - repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); - }, - exitInsertMode: exitInsertMode - }; - - function defineAction(name, fn) { - actions[name] = fn; - } - - /* - * Below are miscellaneous utility functions used by vim.js - */ - - /** - * Clips cursor to ensure that line is within the buffer's range - * If includeLineBreak is true, then allow cur.ch == lineLength. - */ - function clipCursorToContent(cm, cur, includeLineBreak) { - var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() ); - var maxCh = lineLength(cm, line) - 1; - maxCh = (includeLineBreak) ? maxCh + 1 : maxCh; - var ch = Math.min(Math.max(0, cur.ch), maxCh); - return Pos(line, ch); - } - function copyArgs(args) { - var ret = {}; - for (var prop in args) { - if (args.hasOwnProperty(prop)) { - ret[prop] = args[prop]; - } - } - return ret; - } - function offsetCursor(cur, offsetLine, offsetCh) { - if (typeof offsetLine === 'object') { - offsetCh = offsetLine.ch; - offsetLine = offsetLine.line; - } - return Pos(cur.line + offsetLine, cur.ch + offsetCh); - } - function getOffset(anchor, head) { - return { - line: head.line - anchor.line, - ch: head.line - anchor.line - }; - } - function commandMatches(keys, keyMap, context, inputState) { - // Partial matches are not applied. They inform the key handler - // that the current key sequence is a subsequence of a valid key - // sequence, so that the key buffer is not cleared. - var match, partial = [], full = []; - for (var i = 0; i < keyMap.length; i++) { - var command = keyMap[i]; - if (context == 'insert' && command.context != 'insert' || - command.context && command.context != context || - inputState.operator && command.type == 'action' || - !(match = commandMatch(keys, command.keys))) { continue; } - if (match == 'partial') { partial.push(command); } - if (match == 'full') { full.push(command); } - } - return { - partial: partial.length && partial, - full: full.length && full - }; - } - function commandMatch(pressed, mapped) { - if (mapped.slice(-11) == '') { - // Last character matches anything. - var prefixLen = mapped.length - 11; - var pressedPrefix = pressed.slice(0, prefixLen); - var mappedPrefix = mapped.slice(0, prefixLen); - return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' : - mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false; - } else { - return pressed == mapped ? 'full' : - mapped.indexOf(pressed) == 0 ? 'partial' : false; - } - } - function lastChar(keys) { - var match = /^.*(<[\w\-]+>)$/.exec(keys); - var selectedCharacter = match ? match[1] : keys.slice(-1); - if (selectedCharacter.length > 1){ - switch(selectedCharacter){ - case '': - selectedCharacter='\n'; - break; - case '': - selectedCharacter=' '; - break; - default: - break; - } - } - return selectedCharacter; - } - function repeatFn(cm, fn, repeat) { - return function() { - for (var i = 0; i < repeat; i++) { - fn(cm); - } - }; - } - function copyCursor(cur) { - return Pos(cur.line, cur.ch); - } - function cursorEqual(cur1, cur2) { - return cur1.ch == cur2.ch && cur1.line == cur2.line; - } - function cursorIsBefore(cur1, cur2) { - if (cur1.line < cur2.line) { - return true; - } - if (cur1.line == cur2.line && cur1.ch < cur2.ch) { - return true; - } - return false; - } - function cursorMin(cur1, cur2) { - if (arguments.length > 2) { - cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1)); - } - return cursorIsBefore(cur1, cur2) ? cur1 : cur2; - } - function cursorMax(cur1, cur2) { - if (arguments.length > 2) { - cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1)); - } - return cursorIsBefore(cur1, cur2) ? cur2 : cur1; - } - function cursorIsBetween(cur1, cur2, cur3) { - // returns true if cur2 is between cur1 and cur3. - var cur1before2 = cursorIsBefore(cur1, cur2); - var cur2before3 = cursorIsBefore(cur2, cur3); - return cur1before2 && cur2before3; - } - function lineLength(cm, lineNum) { - return cm.getLine(lineNum).length; - } - function reverse(s){ - return s.split('').reverse().join(''); - } - function trim(s) { - if (s.trim) { - return s.trim(); - } - return s.replace(/^\s+|\s+$/g, ''); - } - function escapeRegex(s) { - return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1'); - } - function extendLineToColumn(cm, lineNum, column) { - var endCh = lineLength(cm, lineNum); - var spaces = new Array(column-endCh+1).join(' '); - cm.setCursor(Pos(lineNum, endCh)); - cm.replaceRange(spaces, cm.getCursor()); - } - // This functions selects a rectangular block - // of text with selectionEnd as any of its corner - // Height of block: - // Difference in selectionEnd.line and first/last selection.line - // Width of the block: - // Distance between selectionEnd.ch and any(first considered here) selection.ch - function selectBlock(cm, selectionEnd) { - var selections = [], ranges = cm.listSelections(); - var head = copyCursor(cm.clipPos(selectionEnd)); - var isClipped = !cursorEqual(selectionEnd, head); - var curHead = cm.getCursor('head'); - var primIndex = getIndex(ranges, curHead); - var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor); - var max = ranges.length - 1; - var index = max - primIndex > primIndex ? max : 0; - var base = ranges[index].anchor; - - var firstLine = Math.min(base.line, head.line); - var lastLine = Math.max(base.line, head.line); - var baseCh = base.ch, headCh = head.ch; - - var dir = ranges[index].head.ch - baseCh; - var newDir = headCh - baseCh; - if (dir > 0 && newDir <= 0) { - baseCh++; - if (!isClipped) { headCh--; } - } else if (dir < 0 && newDir >= 0) { - baseCh--; - if (!wasClipped) { headCh++; } - } else if (dir < 0 && newDir == -1) { - baseCh--; - headCh++; - } - for (var line = firstLine; line <= lastLine; line++) { - var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)}; - selections.push(range); - } - primIndex = head.line == lastLine ? selections.length - 1 : 0; - cm.setSelections(selections); - selectionEnd.ch = headCh; - base.ch = baseCh; - return base; - } - function selectForInsert(cm, head, height) { - var sel = []; - for (var i = 0; i < height; i++) { - var lineHead = offsetCursor(head, i, 0); - sel.push({anchor: lineHead, head: lineHead}); - } - cm.setSelections(sel, 0); - } - // getIndex returns the index of the cursor in the selections. - function getIndex(ranges, cursor, end) { - for (var i = 0; i < ranges.length; i++) { - var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor); - var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor); - if (atAnchor || atHead) { - return i; - } - } - return -1; - } - function getSelectedAreaRange(cm, vim) { - var lastSelection = vim.lastSelection; - var getCurrentSelectedAreaRange = function() { - var selections = cm.listSelections(); - var start = selections[0]; - var end = selections[selections.length-1]; - var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - return [selectionStart, selectionEnd]; - }; - var getLastSelectedAreaRange = function() { - var selectionStart = cm.getCursor(); - var selectionEnd = cm.getCursor(); - var block = lastSelection.visualBlock; - if (block) { - var width = block.width; - var height = block.height; - selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width); - var selections = []; - // selectBlock creates a 'proper' rectangular block. - // We do not want that in all cases, so we manually set selections. - for (var i = selectionStart.line; i < selectionEnd.line; i++) { - var anchor = Pos(i, selectionStart.ch); - var head = Pos(i, selectionEnd.ch); - var range = {anchor: anchor, head: head}; - selections.push(range); - } - cm.setSelections(selections); - } else { - var start = lastSelection.anchorMark.find(); - var end = lastSelection.headMark.find(); - var line = end.line - start.line; - var ch = end.ch - start.ch; - selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; - if (lastSelection.visualLine) { - selectionStart = Pos(selectionStart.line, 0); - selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line)); - } - cm.setSelection(selectionStart, selectionEnd); - } - return [selectionStart, selectionEnd]; - }; - if (!vim.visualMode) { - // In case of replaying the action. - return getLastSelectedAreaRange(); - } else { - return getCurrentSelectedAreaRange(); - } - } - // Updates the previous selection with the current selection's values. This - // should only be called in visual mode. - function updateLastSelection(cm, vim) { - var anchor = vim.sel.anchor; - var head = vim.sel.head; - // To accommodate the effect of lastPastedText in the last selection - if (vim.lastPastedText) { - head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length); - vim.lastPastedText = null; - } - vim.lastSelection = {'anchorMark': cm.setBookmark(anchor), - 'headMark': cm.setBookmark(head), - 'anchor': copyCursor(anchor), - 'head': copyCursor(head), - 'visualMode': vim.visualMode, - 'visualLine': vim.visualLine, - 'visualBlock': vim.visualBlock}; - } - function expandSelection(cm, start, end) { - var sel = cm.state.vim.sel; - var head = sel.head; - var anchor = sel.anchor; - var tmp; - if (cursorIsBefore(end, start)) { - tmp = end; - end = start; - start = tmp; - } - if (cursorIsBefore(head, anchor)) { - head = cursorMin(start, head); - anchor = cursorMax(anchor, end); - } else { - anchor = cursorMin(start, anchor); - head = cursorMax(head, end); - head = offsetCursor(head, 0, -1); - if (head.ch == -1 && head.line != cm.firstLine()) { - head = Pos(head.line - 1, lineLength(cm, head.line - 1)); - } - } - return [anchor, head]; - } - /** - * Updates the CodeMirror selection to match the provided vim selection. - * If no arguments are given, it uses the current vim selection state. - */ - function updateCmSelection(cm, sel, mode) { - var vim = cm.state.vim; - sel = sel || vim.sel; - var mode = mode || - vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char'; - var cmSel = makeCmSelection(cm, sel, mode); - cm.setSelections(cmSel.ranges, cmSel.primary); - updateFakeCursor(cm); - } - function makeCmSelection(cm, sel, mode, exclusive) { - var head = copyCursor(sel.head); - var anchor = copyCursor(sel.anchor); - if (mode == 'char') { - var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; - var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; - head = offsetCursor(sel.head, 0, headOffset); - anchor = offsetCursor(sel.anchor, 0, anchorOffset); - return { - ranges: [{anchor: anchor, head: head}], - primary: 0 - }; - } else if (mode == 'line') { - if (!cursorIsBefore(sel.head, sel.anchor)) { - anchor.ch = 0; - - var lastLine = cm.lastLine(); - if (head.line > lastLine) { - head.line = lastLine; - } - head.ch = lineLength(cm, head.line); - } else { - head.ch = 0; - anchor.ch = lineLength(cm, anchor.line); - } - return { - ranges: [{anchor: anchor, head: head}], - primary: 0 - }; - } else if (mode == 'block') { - var top = Math.min(anchor.line, head.line), - left = Math.min(anchor.ch, head.ch), - bottom = Math.max(anchor.line, head.line), - right = Math.max(anchor.ch, head.ch) + 1; - var height = bottom - top + 1; - var primary = head.line == top ? 0 : height - 1; - var ranges = []; - for (var i = 0; i < height; i++) { - ranges.push({ - anchor: Pos(top + i, left), - head: Pos(top + i, right) - }); - } - return { - ranges: ranges, - primary: primary - }; - } - } - function getHead(cm) { - var cur = cm.getCursor('head'); - if (cm.getSelection().length == 1) { - // Small corner case when only 1 character is selected. The "real" - // head is the left of head and anchor. - cur = cursorMin(cur, cm.getCursor('anchor')); - } - return cur; - } - - /** - * If moveHead is set to false, the CodeMirror selection will not be - * touched. The caller assumes the responsibility of putting the cursor - * in the right place. - */ - function exitVisualMode(cm, moveHead) { - var vim = cm.state.vim; - if (moveHead !== false) { - cm.setCursor(clipCursorToContent(cm, vim.sel.head)); - } - updateLastSelection(cm, vim); - vim.visualMode = false; - vim.visualLine = false; - vim.visualBlock = false; - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - } - - // Remove any trailing newlines from the selection. For - // example, with the caret at the start of the last word on the line, - // 'dw' should word, but not the newline, while 'w' should advance the - // caret to the first character of the next line. - function clipToLine(cm, curStart, curEnd) { - var selection = cm.getRange(curStart, curEnd); - // Only clip if the selection ends with trailing newline + whitespace - if (/\n\s*$/.test(selection)) { - var lines = selection.split('\n'); - // We know this is all whitepsace. - lines.pop(); - - // Cases: - // 1. Last word is an empty line - do not clip the trailing '\n' - // 2. Last word is not an empty line - clip the trailing '\n' - var line; - // Find the line containing the last word, and clip all whitespace up - // to it. - for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) { - curEnd.line--; - curEnd.ch = 0; - } - // If the last word is not an empty line, clip an additional newline - if (line) { - curEnd.line--; - curEnd.ch = lineLength(cm, curEnd.line); - } else { - curEnd.ch = 0; - } - } - } - - // Expand the selection to line ends. - function expandSelectionToLine(_cm, curStart, curEnd) { - curStart.ch = 0; - curEnd.ch = 0; - curEnd.line++; - } - - function findFirstNonWhiteSpaceCharacter(text) { - if (!text) { - return 0; - } - var firstNonWS = text.search(/\S/); - return firstNonWS == -1 ? text.length : firstNonWS; - } - - function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { - var cur = getHead(cm); - var line = cm.getLine(cur.line); - var idx = cur.ch; - - // Seek to first word or non-whitespace character, depending on if - // noSymbol is true. - var textAfterIdx = line.substring(idx); - var firstMatchedChar; - if (noSymbol) { - firstMatchedChar = textAfterIdx.search(/\w/); - } else { - firstMatchedChar = textAfterIdx.search(/\S/); - } - if (firstMatchedChar == -1) { - return null; - } - idx += firstMatchedChar; - textAfterIdx = line.substring(idx); - var textBeforeIdx = line.substring(0, idx); - - var matchRegex; - // Greedy matchers for the "word" we are trying to expand. - if (bigWord) { - matchRegex = /^\S+/; - } else { - if ((/\w/).test(line.charAt(idx))) { - matchRegex = /^\w+/; - } else { - matchRegex = /^[^\w\s]+/; - } - } - - var wordAfterRegex = matchRegex.exec(textAfterIdx); - var wordStart = idx; - var wordEnd = idx + wordAfterRegex[0].length; - // TODO: Find a better way to do this. It will be slow on very long lines. - var revTextBeforeIdx = reverse(textBeforeIdx); - var wordBeforeRegex = matchRegex.exec(revTextBeforeIdx); - if (wordBeforeRegex) { - wordStart -= wordBeforeRegex[0].length; - } - - if (inclusive) { - // If present, trim all whitespace after word. - // Otherwise, trim all whitespace before word. - var textAfterWordEnd = line.substring(wordEnd); - var whitespacesAfterWord = textAfterWordEnd.match(/^\s*/)[0].length; - if (whitespacesAfterWord > 0) { - wordEnd += whitespacesAfterWord; - } else { - var revTrim = revTextBeforeIdx.length - wordStart; - var textBeforeWordStart = revTextBeforeIdx.substring(revTrim); - var whitespacesBeforeWord = textBeforeWordStart.match(/^\s*/)[0].length; - wordStart -= whitespacesBeforeWord; - } - } - - return { start: Pos(cur.line, wordStart), - end: Pos(cur.line, wordEnd) }; - } - - function recordJumpPosition(cm, oldCur, newCur) { - if (!cursorEqual(oldCur, newCur)) { - vimGlobalState.jumpList.add(cm, oldCur, newCur); - } - } - - function recordLastCharacterSearch(increment, args) { - vimGlobalState.lastChararacterSearch.increment = increment; - vimGlobalState.lastChararacterSearch.forward = args.forward; - vimGlobalState.lastChararacterSearch.selectedCharacter = args.selectedCharacter; - } - - var symbolToMode = { - '(': 'bracket', ')': 'bracket', '{': 'bracket', '}': 'bracket', - '[': 'section', ']': 'section', - '*': 'comment', '/': 'comment', - 'm': 'method', 'M': 'method', - '#': 'preprocess' - }; - var findSymbolModes = { - bracket: { - isComplete: function(state) { - if (state.nextCh === state.symb) { - state.depth++; - if (state.depth >= 1)return true; - } else if (state.nextCh === state.reverseSymb) { - state.depth--; - } - return false; - } - }, - section: { - init: function(state) { - state.curMoveThrough = true; - state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}'; - }, - isComplete: function(state) { - return state.index === 0 && state.nextCh === state.symb; - } - }, - comment: { - isComplete: function(state) { - var found = state.lastCh === '*' && state.nextCh === '/'; - state.lastCh = state.nextCh; - return found; - } - }, - // TODO: The original Vim implementation only operates on level 1 and 2. - // The current implementation doesn't check for code block level and - // therefore it operates on any levels. - method: { - init: function(state) { - state.symb = (state.symb === 'm' ? '{' : '}'); - state.reverseSymb = state.symb === '{' ? '}' : '{'; - }, - isComplete: function(state) { - if (state.nextCh === state.symb)return true; - return false; - } - }, - preprocess: { - init: function(state) { - state.index = 0; - }, - isComplete: function(state) { - if (state.nextCh === '#') { - var token = state.lineText.match(/#(\w+)/)[1]; - if (token === 'endif') { - if (state.forward && state.depth === 0) { - return true; - } - state.depth++; - } else if (token === 'if') { - if (!state.forward && state.depth === 0) { - return true; - } - state.depth--; - } - if (token === 'else' && state.depth === 0)return true; - } - return false; - } - } - }; - function findSymbol(cm, repeat, forward, symb) { - var cur = copyCursor(cm.getCursor()); - var increment = forward ? 1 : -1; - var endLine = forward ? cm.lineCount() : -1; - var curCh = cur.ch; - var line = cur.line; - var lineText = cm.getLine(line); - var state = { - lineText: lineText, - nextCh: lineText.charAt(curCh), - lastCh: null, - index: curCh, - symb: symb, - reverseSymb: (forward ? { ')': '(', '}': '{' } : { '(': ')', '{': '}' })[symb], - forward: forward, - depth: 0, - curMoveThrough: false - }; - var mode = symbolToMode[symb]; - if (!mode)return cur; - var init = findSymbolModes[mode].init; - var isComplete = findSymbolModes[mode].isComplete; - if (init) { init(state); } - while (line !== endLine && repeat) { - state.index += increment; - state.nextCh = state.lineText.charAt(state.index); - if (!state.nextCh) { - line += increment; - state.lineText = cm.getLine(line) || ''; - if (increment > 0) { - state.index = 0; - } else { - var lineLen = state.lineText.length; - state.index = (lineLen > 0) ? (lineLen-1) : 0; - } - state.nextCh = state.lineText.charAt(state.index); - } - if (isComplete(state)) { - cur.line = line; - cur.ch = state.index; - repeat--; - } - } - if (state.nextCh || state.curMoveThrough) { - return Pos(line, state.index); - } - return cur; - } - - /* - * Returns the boundaries of the next word. If the cursor in the middle of - * the word, then returns the boundaries of the current word, starting at - * the cursor. If the cursor is at the start/end of a word, and we are going - * forward/backward, respectively, find the boundaries of the next word. - * - * @param {CodeMirror} cm CodeMirror object. - * @param {Cursor} cur The cursor position. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only [a-zA-Z0-9] characters count as part of the word. - * @param {boolean} emptyLineIsWord True if empty lines should be treated - * as words. - * @return {Object{from:number, to:number, line: number}} The boundaries of - * the word, or null if there are no more words. - */ - function findWord(cm, cur, forward, bigWord, emptyLineIsWord) { - var lineNum = cur.line; - var pos = cur.ch; - var line = cm.getLine(lineNum); - var dir = forward ? 1 : -1; - var regexps = bigWord ? bigWordRegexp : wordRegexp; - - if (emptyLineIsWord && line == '') { - lineNum += dir; - line = cm.getLine(lineNum); - if (!isLine(cm, lineNum)) { - return null; - } - pos = (forward) ? 0 : line.length; - } - - while (true) { - if (emptyLineIsWord && line == '') { - return { from: 0, to: 0, line: lineNum }; - } - var stop = (dir > 0) ? line.length : -1; - var wordStart = stop, wordEnd = stop; - // Find bounds of next word. - while (pos != stop) { - var foundWord = false; - for (var i = 0; i < regexps.length && !foundWord; ++i) { - if (regexps[i].test(line.charAt(pos))) { - wordStart = pos; - // Advance to end of word. - while (pos != stop && regexps[i].test(line.charAt(pos))) { - pos += dir; - } - wordEnd = pos; - foundWord = wordStart != wordEnd; - if (wordStart == cur.ch && lineNum == cur.line && - wordEnd == wordStart + dir) { - // We started at the end of a word. Find the next one. - continue; - } else { - return { - from: Math.min(wordStart, wordEnd + 1), - to: Math.max(wordStart, wordEnd), - line: lineNum }; - } - } - } - if (!foundWord) { - pos += dir; - } - } - // Advance to next/prev line. - lineNum += dir; - if (!isLine(cm, lineNum)) { - return null; - } - line = cm.getLine(lineNum); - pos = (dir > 0) ? 0 : line.length; - } - // Should never get here. - throw new Error('The impossible happened.'); - } - - /** - * @param {CodeMirror} cm CodeMirror object. - * @param {Pos} cur The position to start from. - * @param {int} repeat Number of words to move past. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} wordEnd True to move to end of word. False to move to - * beginning of word. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only alphabet characters count as part of the word. - * @return {Cursor} The position the cursor should move to. - */ - function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) { - var curStart = copyCursor(cur); - var words = []; - if (forward && !wordEnd || !forward && wordEnd) { - repeat++; - } - // For 'e', empty lines are not considered words, go figure. - var emptyLineIsWord = !(forward && wordEnd); - for (var i = 0; i < repeat; i++) { - var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord); - if (!word) { - var eodCh = lineLength(cm, cm.lastLine()); - words.push(forward - ? {line: cm.lastLine(), from: eodCh, to: eodCh} - : {line: 0, from: 0, to: 0}); - break; - } - words.push(word); - cur = Pos(word.line, forward ? (word.to - 1) : word.from); - } - var shortCircuit = words.length != repeat; - var firstWord = words[0]; - var lastWord = words.pop(); - if (forward && !wordEnd) { - // w - if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop(); - } - return Pos(lastWord.line, lastWord.from); - } else if (forward && wordEnd) { - return Pos(lastWord.line, lastWord.to - 1); - } else if (!forward && wordEnd) { - // ge - if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop(); - } - return Pos(lastWord.line, lastWord.to); - } else { - // b - return Pos(lastWord.line, lastWord.from); - } - } - - function moveToCharacter(cm, repeat, forward, character) { - var cur = cm.getCursor(); - var start = cur.ch; - var idx; - for (var i = 0; i < repeat; i ++) { - var line = cm.getLine(cur.line); - idx = charIdxInLine(start, line, character, forward, true); - if (idx == -1) { - return null; - } - start = idx; - } - return Pos(cm.getCursor().line, idx); - } - - function moveToColumn(cm, repeat) { - // repeat is always >= 1, so repeat - 1 always corresponds - // to the column we want to go to. - var line = cm.getCursor().line; - return clipCursorToContent(cm, Pos(line, repeat - 1)); - } - - function updateMark(cm, vim, markName, pos) { - if (!inArray(markName, validMarks)) { - return; - } - if (vim.marks[markName]) { - vim.marks[markName].clear(); - } - vim.marks[markName] = cm.setBookmark(pos); - } - - function charIdxInLine(start, line, character, forward, includeChar) { - // Search for char in line. - // motion_options: {forward, includeChar} - // If includeChar = true, include it too. - // If forward = true, search forward, else search backwards. - // If char is not found on this line, do nothing - var idx; - if (forward) { - idx = line.indexOf(character, start + 1); - if (idx != -1 && !includeChar) { - idx -= 1; - } - } else { - idx = line.lastIndexOf(character, start - 1); - if (idx != -1 && !includeChar) { - idx += 1; - } - } - return idx; - } - - function findParagraph(cm, head, repeat, dir, inclusive) { - var line = head.line; - var min = cm.firstLine(); - var max = cm.lastLine(); - var start, end, i = line; - function isEmpty(i) { return !cm.getLine(i); } - function isBoundary(i, dir, any) { - if (any) { return isEmpty(i) != isEmpty(i + dir); } - return !isEmpty(i) && isEmpty(i + dir); - } - if (dir) { - while (min <= i && i <= max && repeat > 0) { - if (isBoundary(i, dir)) { repeat--; } - i += dir; - } - return new Pos(i, 0); - } - - var vim = cm.state.vim; - if (vim.visualLine && isBoundary(line, 1, true)) { - var anchor = vim.sel.anchor; - if (isBoundary(anchor.line, -1, true)) { - if (!inclusive || anchor.line != line) { - line += 1; - } - } - } - var startState = isEmpty(line); - for (i = line; i <= max && repeat; i++) { - if (isBoundary(i, 1, true)) { - if (!inclusive || isEmpty(i) != startState) { - repeat--; - } - } - } - end = new Pos(i, 0); - // select boundary before paragraph for the last one - if (i > max && !startState) { startState = true; } - else { inclusive = false; } - for (i = line; i > min; i--) { - if (!inclusive || isEmpty(i) == startState || i == line) { - if (isBoundary(i, -1, true)) { break; } - } - } - start = new Pos(i, 0); - return { start: start, end: end }; - } - - // TODO: perhaps this finagling of start and end positions belonds - // in codmirror/replaceRange? - function selectCompanionObject(cm, head, symb, inclusive) { - var cur = head, start, end; - - var bracketRegexp = ({ - '(': /[()]/, ')': /[()]/, - '[': /[[\]]/, ']': /[[\]]/, - '{': /[{}]/, '}': /[{}]/})[symb]; - var openSym = ({ - '(': '(', ')': '(', - '[': '[', ']': '[', - '{': '{', '}': '{'})[symb]; - var curChar = cm.getLine(cur.line).charAt(cur.ch); - // Due to the behavior of scanForBracket, we need to add an offset if the - // cursor is on a matching open bracket. - var offset = curChar === openSym ? 1 : 0; - - start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp}); - end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp}); - - if (!start || !end) { - return { start: cur, end: cur }; - } - - start = start.pos; - end = end.pos; - - if ((start.line == end.line && start.ch > end.ch) - || (start.line > end.line)) { - var tmp = start; - start = end; - end = tmp; - } - - if (inclusive) { - end.ch += 1; - } else { - start.ch += 1; - } - - return { start: start, end: end }; - } - - // Takes in a symbol and a cursor and tries to simulate text objects that - // have identical opening and closing symbols - // TODO support across multiple lines - function findBeginningAndEnd(cm, head, symb, inclusive) { - var cur = copyCursor(head); - var line = cm.getLine(cur.line); - var chars = line.split(''); - var start, end, i, len; - var firstIndex = chars.indexOf(symb); - - // the decision tree is to always look backwards for the beginning first, - // but if the cursor is in front of the first instance of the symb, - // then move the cursor forward - if (cur.ch < firstIndex) { - cur.ch = firstIndex; - // Why is this line even here??? - // cm.setCursor(cur.line, firstIndex+1); - } - // otherwise if the cursor is currently on the closing symbol - else if (firstIndex < cur.ch && chars[cur.ch] == symb) { - end = cur.ch; // assign end to the current cursor - --cur.ch; // make sure to look backwards - } - - // if we're currently on the symbol, we've got a start - if (chars[cur.ch] == symb && !end) { - start = cur.ch + 1; // assign start to ahead of the cursor - } else { - // go backwards to find the start - for (i = cur.ch; i > -1 && !start; i--) { - if (chars[i] == symb) { - start = i + 1; - } - } - } - - // look forwards for the end symbol - if (start && !end) { - for (i = start, len = chars.length; i < len && !end; i++) { - if (chars[i] == symb) { - end = i; - } - } - } - - // nothing found - if (!start || !end) { - return { start: cur, end: cur }; - } - - // include the symbols - if (inclusive) { - --start; ++end; - } - - return { - start: Pos(cur.line, start), - end: Pos(cur.line, end) - }; - } - - // Search functions - defineOption('pcre', true, 'boolean'); - function SearchState() {} - SearchState.prototype = { - getQuery: function() { - return vimGlobalState.query; - }, - setQuery: function(query) { - vimGlobalState.query = query; - }, - getOverlay: function() { - return this.searchOverlay; - }, - setOverlay: function(overlay) { - this.searchOverlay = overlay; - }, - isReversed: function() { - return vimGlobalState.isReversed; - }, - setReversed: function(reversed) { - vimGlobalState.isReversed = reversed; - }, - getScrollbarAnnotate: function() { - return this.annotate; - }, - setScrollbarAnnotate: function(annotate) { - this.annotate = annotate; - } - }; - function getSearchState(cm) { - var vim = cm.state.vim; - return vim.searchState_ || (vim.searchState_ = new SearchState()); - } - function dialog(cm, template, shortText, onClose, options) { - if (cm.openDialog) { - cm.openDialog(template, onClose, { bottom: true, value: options.value, - onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp }); - } - else { - onClose(prompt(shortText, '')); - } - } - function splitBySlash(argString) { - var slashes = findUnescapedSlashes(argString) || []; - if (!slashes.length) return []; - var tokens = []; - // in case of strings like foo/bar - if (slashes[0] !== 0) return; - for (var i = 0; i < slashes.length; i++) { - if (typeof slashes[i] == 'number') - tokens.push(argString.substring(slashes[i] + 1, slashes[i+1])); - } - return tokens; - } - - function findUnescapedSlashes(str) { - var escapeNextChar = false; - var slashes = []; - for (var i = 0; i < str.length; i++) { - var c = str.charAt(i); - if (!escapeNextChar && c == '/') { - slashes.push(i); - } - escapeNextChar = !escapeNextChar && (c == '\\'); - } - return slashes; - } - - // Translates a search string from ex (vim) syntax into javascript form. - function translateRegex(str) { - // When these match, add a '\' if unescaped or remove one if escaped. - var specials = '|(){'; - // Remove, but never add, a '\' for these. - var unescape = '}'; - var escapeNextChar = false; - var out = []; - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || ''; - var n = str.charAt(i+1) || ''; - var specialComesNext = (n && specials.indexOf(n) != -1); - if (escapeNextChar) { - if (c !== '\\' || !specialComesNext) { - out.push(c); - } - escapeNextChar = false; - } else { - if (c === '\\') { - escapeNextChar = true; - // Treat the unescape list as special for removing, but not adding '\'. - if (n && unescape.indexOf(n) != -1) { - specialComesNext = true; - } - // Not passing this test means removing a '\'. - if (!specialComesNext || n === '\\') { - out.push(c); - } - } else { - out.push(c); - if (specialComesNext && n !== '\\') { - out.push('\\'); - } - } - } - } - return out.join(''); - } - - // Translates the replace part of a search and replace from ex (vim) syntax into - // javascript form. Similar to translateRegex, but additionally fixes back references - // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'. - function translateRegexReplace(str) { - var escapeNextChar = false; - var out = []; - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || ''; - var n = str.charAt(i+1) || ''; - if (escapeNextChar) { - // At any point in the loop, escapeNextChar is true if the previous - // character was a '\' and was not escaped. - out.push(c); - escapeNextChar = false; - } else { - if (c === '\\') { - escapeNextChar = true; - if ((isNumber(n) || n === '$')) { - out.push('$'); - } else if (n !== '/' && n !== '\\') { - out.push('\\'); - } - } else { - if (c === '$') { - out.push('$'); - } - out.push(c); - if (n === '/') { - out.push('\\'); - } - } - } - } - return out.join(''); - } - - // Unescape \ and / in the replace part, for PCRE mode. - function unescapeRegexReplace(str) { - var stream = new CodeMirror.StringStream(str); - var output = []; - while (!stream.eol()) { - // Search for \. - while (stream.peek() && stream.peek() != '\\') { - output.push(stream.next()); - } - if (stream.match('\\/', true)) { - // \/ => / - output.push('/'); - } else if (stream.match('\\\\', true)) { - // \\ => \ - output.push('\\'); - } else { - // Don't change anything - output.push(stream.next()); - } - } - return output.join(''); - } - - /** - * Extract the regular expression from the query and return a Regexp object. - * Returns null if the query is blank. - * If ignoreCase is passed in, the Regexp object will have the 'i' flag set. - * If smartCase is passed in, and the query contains upper case letters, - * then ignoreCase is overridden, and the 'i' flag will not be set. - * If the query contains the /i in the flag part of the regular expression, - * then both ignoreCase and smartCase are ignored, and 'i' will be passed - * through to the Regex object. - */ - function parseQuery(query, ignoreCase, smartCase) { - // First update the last search register - var lastSearchRegister = vimGlobalState.registerController.getRegister('/'); - lastSearchRegister.setText(query); - // Check if the query is already a regex. - if (query instanceof RegExp) { return query; } - // First try to extract regex + flags from the input. If no flags found, - // extract just the regex. IE does not accept flags directly defined in - // the regex string in the form /regex/flags - var slashes = findUnescapedSlashes(query); - var regexPart; - var forceIgnoreCase; - if (!slashes.length) { - // Query looks like 'regexp' - regexPart = query; - } else { - // Query looks like 'regexp/...' - regexPart = query.substring(0, slashes[0]); - var flagsPart = query.substring(slashes[0]); - forceIgnoreCase = (flagsPart.indexOf('i') != -1); - } - if (!regexPart) { - return null; - } - if (!getOption('pcre')) { - regexPart = translateRegex(regexPart); - } - if (smartCase) { - ignoreCase = (/^[^A-Z]*$/).test(regexPart); - } - var regexp = new RegExp(regexPart, - (ignoreCase || forceIgnoreCase) ? 'i' : undefined); - return regexp; - } - function showConfirm(cm, text) { - if (cm.openNotification) { - cm.openNotification('' + text + '', - {bottom: true, duration: 5000}); - } else { - alert(text); - } - } - function makePrompt(prefix, desc) { - var raw = ''; - if (prefix) { - raw += '' + prefix + ''; - } - raw += ' ' + - ''; - if (desc) { - raw += ''; - raw += desc; - raw += ''; - } - return raw; - } - var searchPromptDesc = '(Javascript regexp)'; - function showPrompt(cm, options) { - var shortText = (options.prefix || '') + ' ' + (options.desc || ''); - var prompt = makePrompt(options.prefix, options.desc); - dialog(cm, prompt, shortText, options.onClose, options); - } - function regexEqual(r1, r2) { - if (r1 instanceof RegExp && r2 instanceof RegExp) { - var props = ['global', 'multiline', 'ignoreCase', 'source']; - for (var i = 0; i < props.length; i++) { - var prop = props[i]; - if (r1[prop] !== r2[prop]) { - return false; - } - } - return true; - } - return false; - } - // Returns true if the query is valid. - function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) { - if (!rawQuery) { - return; - } - var state = getSearchState(cm); - var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase); - if (!query) { - return; - } - highlightSearchMatches(cm, query); - if (regexEqual(query, state.getQuery())) { - return query; - } - state.setQuery(query); - return query; - } - function searchOverlay(query) { - if (query.source.charAt(0) == '^') { - var matchSol = true; - } - return { - token: function(stream) { - if (matchSol && !stream.sol()) { - stream.skipToEnd(); - return; - } - var match = stream.match(query, false); - if (match) { - if (match[0].length == 0) { - // Matched empty string, skip to next. - stream.next(); - return 'searching'; - } - if (!stream.sol()) { - // Backtrack 1 to match \b - stream.backUp(1); - if (!query.exec(stream.next() + match[0])) { - stream.next(); - return null; - } - } - stream.match(query); - return 'searching'; - } - while (!stream.eol()) { - stream.next(); - if (stream.match(query, false)) break; - } - }, - query: query - }; - } - function highlightSearchMatches(cm, query) { - var searchState = getSearchState(cm); - var overlay = searchState.getOverlay(); - if (!overlay || query != overlay.query) { - if (overlay) { - cm.removeOverlay(overlay); - } - overlay = searchOverlay(query); - cm.addOverlay(overlay); - if (cm.showMatchesOnScrollbar) { - if (searchState.getScrollbarAnnotate()) { - searchState.getScrollbarAnnotate().clear(); - } - searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query)); - } - searchState.setOverlay(overlay); - } - } - function findNext(cm, prev, query, repeat) { - if (repeat === undefined) { repeat = 1; } - return cm.operation(function() { - var pos = cm.getCursor(); - var cursor = cm.getSearchCursor(query, pos); - for (var i = 0; i < repeat; i++) { - var found = cursor.find(prev); - if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); } - if (!found) { - // SearchCursor may have returned null because it hit EOF, wrap - // around and try again. - cursor = cm.getSearchCursor(query, - (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) ); - if (!cursor.find(prev)) { - return; - } - } - } - return cursor.from(); - }); - } - function clearSearchHighlight(cm) { - var state = getSearchState(cm); - cm.removeOverlay(getSearchState(cm).getOverlay()); - state.setOverlay(null); - if (state.getScrollbarAnnotate()) { - state.getScrollbarAnnotate().clear(); - state.setScrollbarAnnotate(null); - } - } - /** - * Check if pos is in the specified range, INCLUSIVE. - * Range can be specified with 1 or 2 arguments. - * If the first range argument is an array, treat it as an array of line - * numbers. Match pos against any of the lines. - * If the first range argument is a number, - * if there is only 1 range argument, check if pos has the same line - * number - * if there are 2 range arguments, then check if pos is in between the two - * range arguments. - */ - function isInRange(pos, start, end) { - if (typeof pos != 'number') { - // Assume it is a cursor position. Get the line number. - pos = pos.line; - } - if (start instanceof Array) { - return inArray(pos, start); - } else { - if (end) { - return (pos >= start && pos <= end); - } else { - return pos == start; - } - } - } - function getUserVisibleLines(cm) { - var scrollInfo = cm.getScrollInfo(); - var occludeToleranceTop = 6; - var occludeToleranceBottom = 10; - var from = cm.coordsChar({left:0, top: occludeToleranceTop + scrollInfo.top}, 'local'); - var bottomY = scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top; - var to = cm.coordsChar({left:0, top: bottomY}, 'local'); - return {top: from.line, bottom: to.line}; - } - - // Ex command handling - // Care must be taken when adding to the default Ex command map. For any - // pair of commands that have a shared prefix, at least one of their - // shortNames must not match the prefix of the other command. - var defaultExCommandMap = [ - { name: 'map' }, - { name: 'imap', shortName: 'im' }, - { name: 'nmap', shortName: 'nm' }, - { name: 'vmap', shortName: 'vm' }, - { name: 'unmap' }, - { name: 'write', shortName: 'w' }, - { name: 'undo', shortName: 'u' }, - { name: 'redo', shortName: 'red' }, - { name: 'set', shortName: 'set' }, - { name: 'sort', shortName: 'sor' }, - { name: 'substitute', shortName: 's', possiblyAsync: true }, - { name: 'nohlsearch', shortName: 'noh' }, - { name: 'delmarks', shortName: 'delm' }, - { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, - { name: 'global', shortName: 'g' } - ]; - var ExCommandDispatcher = function() { - this.buildCommandMap_(); - }; - ExCommandDispatcher.prototype = { - processCommand: function(cm, input, opt_params) { - var vim = cm.state.vim; - var commandHistoryRegister = vimGlobalState.registerController.getRegister(':'); - var previousCommand = commandHistoryRegister.toString(); - if (vim.visualMode) { - exitVisualMode(cm); - } - var inputStream = new CodeMirror.StringStream(input); - // update ": with the latest command whether valid or invalid - commandHistoryRegister.setText(input); - var params = opt_params || {}; - params.input = input; - try { - this.parseInput_(cm, inputStream, params); - } catch(e) { - showConfirm(cm, e); - throw e; - } - var command; - var commandName; - if (!params.commandName) { - // If only a line range is defined, move to the line. - if (params.line !== undefined) { - commandName = 'move'; - } - } else { - command = this.matchCommand_(params.commandName); - if (command) { - commandName = command.name; - if (command.excludeFromCommandHistory) { - commandHistoryRegister.setText(previousCommand); - } - this.parseCommandArgs_(inputStream, params, command); - if (command.type == 'exToKey') { - // Handle Ex to Key mapping. - for (var i = 0; i < command.toKeys.length; i++) { - CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping'); - } - return; - } else if (command.type == 'exToEx') { - // Handle Ex to Ex mapping. - this.processCommand(cm, command.toInput); - return; - } - } - } - if (!commandName) { - showConfirm(cm, 'Not an editor command ":' + input + '"'); - return; - } - try { - exCommands[commandName](cm, params); - // Possibly asynchronous commands (e.g. substitute, which might have a - // user confirmation), are responsible for calling the callback when - // done. All others have it taken care of for them here. - if ((!command || !command.possiblyAsync) && params.callback) { - params.callback(); - } - } catch(e) { - showConfirm(cm, e); - throw e; - } - }, - parseInput_: function(cm, inputStream, result) { - inputStream.eatWhile(':'); - // Parse range. - if (inputStream.eat('%')) { - result.line = cm.firstLine(); - result.lineEnd = cm.lastLine(); - } else { - result.line = this.parseLineSpec_(cm, inputStream); - if (result.line !== undefined && inputStream.eat(',')) { - result.lineEnd = this.parseLineSpec_(cm, inputStream); - } - } - - // Parse command name. - var commandMatch = inputStream.match(/^(\w+)/); - if (commandMatch) { - result.commandName = commandMatch[1]; - } else { - result.commandName = inputStream.match(/.*/)[0]; - } - - return result; - }, - parseLineSpec_: function(cm, inputStream) { - var numberMatch = inputStream.match(/^(\d+)/); - if (numberMatch) { - return parseInt(numberMatch[1], 10) - 1; - } - switch (inputStream.next()) { - case '.': - return cm.getCursor().line; - case '$': - return cm.lastLine(); - case '\'': - var mark = cm.state.vim.marks[inputStream.next()]; - if (mark && mark.find()) { - return mark.find().line; - } - throw new Error('Mark not set'); - default: - inputStream.backUp(1); - return undefined; - } - }, - parseCommandArgs_: function(inputStream, params, command) { - if (inputStream.eol()) { - return; - } - params.argString = inputStream.match(/.*/)[0]; - // Parse command-line arguments - var delim = command.argDelimiter || /\s+/; - var args = trim(params.argString).split(delim); - if (args.length && args[0]) { - params.args = args; - } - }, - matchCommand_: function(commandName) { - // Return the command in the command map that matches the shortest - // prefix of the passed in command name. The match is guaranteed to be - // unambiguous if the defaultExCommandMap's shortNames are set up - // correctly. (see @code{defaultExCommandMap}). - for (var i = commandName.length; i > 0; i--) { - var prefix = commandName.substring(0, i); - if (this.commandMap_[prefix]) { - var command = this.commandMap_[prefix]; - if (command.name.indexOf(commandName) === 0) { - return command; - } - } - } - return null; - }, - buildCommandMap_: function() { - this.commandMap_ = {}; - for (var i = 0; i < defaultExCommandMap.length; i++) { - var command = defaultExCommandMap[i]; - var key = command.shortName || command.name; - this.commandMap_[key] = command; - } - }, - map: function(lhs, rhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - if (ctx) { throw Error('Mode not supported for ex mappings'); } - var commandName = lhs.substring(1); - if (rhs != ':' && rhs.charAt(0) == ':') { - // Ex to Ex mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToEx', - toInput: rhs.substring(1), - user: true - }; - } else { - // Ex to key mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToKey', - toKeys: rhs, - user: true - }; - } - } else { - if (rhs != ':' && rhs.charAt(0) == ':') { - // Key to Ex mapping. - var mapping = { - keys: lhs, - type: 'keyToEx', - exArgs: { input: rhs.substring(1) }, - user: true}; - if (ctx) { mapping.context = ctx; } - defaultKeymap.unshift(mapping); - } else { - // Key to key mapping - var mapping = { - keys: lhs, - type: 'keyToKey', - toKeys: rhs, - user: true - }; - if (ctx) { mapping.context = ctx; } - defaultKeymap.unshift(mapping); - } - } - }, - unmap: function(lhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - // Ex to Ex or Ex to key mapping - if (ctx) { throw Error('Mode not supported for ex mappings'); } - var commandName = lhs.substring(1); - if (this.commandMap_[commandName] && this.commandMap_[commandName].user) { - delete this.commandMap_[commandName]; - return; - } - } else { - // Key to Ex or key to key mapping - var keys = lhs; - for (var i = 0; i < defaultKeymap.length; i++) { - if (keys == defaultKeymap[i].keys - && defaultKeymap[i].context === ctx - && defaultKeymap[i].user) { - defaultKeymap.splice(i, 1); - return; - } - } - } - throw Error('No such mapping.'); - } - }; - - var exCommands = { - map: function(cm, params, ctx) { - var mapArgs = params.args; - if (!mapArgs || mapArgs.length < 2) { - if (cm) { - showConfirm(cm, 'Invalid mapping: ' + params.input); - } - return; - } - exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); - }, - imap: function(cm, params) { this.map(cm, params, 'insert'); }, - nmap: function(cm, params) { this.map(cm, params, 'normal'); }, - vmap: function(cm, params) { this.map(cm, params, 'visual'); }, - unmap: function(cm, params, ctx) { - var mapArgs = params.args; - if (!mapArgs || mapArgs.length < 1) { - if (cm) { - showConfirm(cm, 'No such mapping: ' + params.input); - } - return; - } - exCommandDispatcher.unmap(mapArgs[0], ctx); - }, - move: function(cm, params) { - commandDispatcher.processCommand(cm, cm.state.vim, { - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { forward: false, explicitRepeat: true, - linewise: true }, - repeatOverride: params.line+1}); - }, - set: function(cm, params) { - var setArgs = params.args; - if (!setArgs || setArgs.length < 1) { - if (cm) { - showConfirm(cm, 'Invalid mapping: ' + params.input); - } - return; - } - var expr = setArgs[0].split('='); - var optionName = expr[0]; - var value = expr[1]; - var forceGet = false; - - if (optionName.charAt(optionName.length - 1) == '?') { - // If post-fixed with ?, then the set is actually a get. - if (value) { throw Error('Trailing characters: ' + params.argString); } - optionName = optionName.substring(0, optionName.length - 1); - forceGet = true; - } - if (value === undefined && optionName.substring(0, 2) == 'no') { - // To set boolean options to false, the option name is prefixed with - // 'no'. - optionName = optionName.substring(2); - value = false; - } - var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean'; - if (optionIsBoolean && value == undefined) { - // Calling set with a boolean option sets it to true. - value = true; - } - if (!optionIsBoolean && !value || forceGet) { - var oldValue = getOption(optionName); - // If no value is provided, then we assume this is a get. - if (oldValue === true || oldValue === false) { - showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName); - } else { - showConfirm(cm, ' ' + optionName + '=' + oldValue); - } - } else { - setOption(optionName, value); - } - }, - registers: function(cm,params) { - var regArgs = params.args; - var registers = vimGlobalState.registerController.registers; - var regInfo = '----------Registers----------

'; - if (!regArgs) { - for (var registerName in registers) { - var text = registers[registerName].toString(); - if (text.length) { - regInfo += '"' + registerName + ' ' + text + '
'; - } - } - } else { - var registerName; - regArgs = regArgs.join(''); - for (var i = 0; i < regArgs.length; i++) { - registerName = regArgs.charAt(i); - if (!vimGlobalState.registerController.isValidRegister(registerName)) { - continue; - } - var register = registers[registerName] || new Register(); - regInfo += '"' + registerName + ' ' + register.toString() + '
'; - } - } - showConfirm(cm, regInfo); - }, - sort: function(cm, params) { - var reverse, ignoreCase, unique, number; - function parseArgs() { - if (params.argString) { - var args = new CodeMirror.StringStream(params.argString); - if (args.eat('!')) { reverse = true; } - if (args.eol()) { return; } - if (!args.eatSpace()) { return 'Invalid arguments'; } - var opts = args.match(/[a-z]+/); - if (opts) { - opts = opts[0]; - ignoreCase = opts.indexOf('i') != -1; - unique = opts.indexOf('u') != -1; - var decimal = opts.indexOf('d') != -1 && 1; - var hex = opts.indexOf('x') != -1 && 1; - var octal = opts.indexOf('o') != -1 && 1; - if (decimal + hex + octal > 1) { return 'Invalid arguments'; } - number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; - } - if (args.eatSpace() && args.match(/\/.*\//)) { 'patterns not supported'; } - } - } - var err = parseArgs(); - if (err) { - showConfirm(cm, err + ': ' + params.argString); - return; - } - var lineStart = params.line || cm.firstLine(); - var lineEnd = params.lineEnd || params.line || cm.lastLine(); - if (lineStart == lineEnd) { return; } - var curStart = Pos(lineStart, 0); - var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)); - var text = cm.getRange(curStart, curEnd).split('\n'); - var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ : - (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i : - (number == 'octal') ? /([0-7]+)/ : null; - var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null; - var numPart = [], textPart = []; - if (number) { - for (var i = 0; i < text.length; i++) { - if (numberRegex.exec(text[i])) { - numPart.push(text[i]); - } else { - textPart.push(text[i]); - } - } - } else { - textPart = text; - } - function compareFn(a, b) { - if (reverse) { var tmp; tmp = a; a = b; b = tmp; } - if (ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); } - var anum = number && numberRegex.exec(a); - var bnum = number && numberRegex.exec(b); - if (!anum) { return a < b ? -1 : 1; } - anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix); - bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix); - return anum - bnum; - } - numPart.sort(compareFn); - textPart.sort(compareFn); - text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart); - if (unique) { // Remove duplicate lines - var textOld = text; - var lastLine; - text = []; - for (var i = 0; i < textOld.length; i++) { - if (textOld[i] != lastLine) { - text.push(textOld[i]); - } - lastLine = textOld[i]; - } - } - cm.replaceRange(text.join('\n'), curStart, curEnd); - }, - global: function(cm, params) { - // a global command is of the form - // :[range]g/pattern/[cmd] - // argString holds the string /pattern/[cmd] - var argString = params.argString; - if (!argString) { - showConfirm(cm, 'Regular Expression missing from global'); - return; - } - // range is specified here - var lineStart = (params.line !== undefined) ? params.line : cm.firstLine(); - var lineEnd = params.lineEnd || params.line || cm.lastLine(); - // get the tokens from argString - var tokens = splitBySlash(argString); - var regexPart = argString, cmd; - if (tokens.length) { - regexPart = tokens[0]; - cmd = tokens.slice(1, tokens.length).join('/'); - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise - // use the regex part as the new query. - try { - updateSearchQuery(cm, regexPart, true /** ignoreCase */, - true /** smartCase */); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart); - return; - } - } - // now that we have the regexPart, search for regex matches in the - // specified range of lines - var query = getSearchState(cm).getQuery(); - var matchedLines = [], content = ''; - for (var i = lineStart; i <= lineEnd; i++) { - var matched = query.test(cm.getLine(i)); - if (matched) { - matchedLines.push(i+1); - content+= cm.getLine(i) + '
'; - } - } - // if there is no [cmd], just display the list of matched lines - if (!cmd) { - showConfirm(cm, content); - return; - } - var index = 0; - var nextCommand = function() { - if (index < matchedLines.length) { - var command = matchedLines[index] + cmd; - exCommandDispatcher.processCommand(cm, command, { - callback: nextCommand - }); - } - index++; - }; - nextCommand(); - }, - substitute: function(cm, params) { - if (!cm.getSearchCursor) { - throw new Error('Search feature not available. Requires searchcursor.js or ' + - 'any other getSearchCursor implementation.'); - } - var argString = params.argString; - var tokens = argString ? splitBySlash(argString) : []; - var regexPart, replacePart = '', trailing, flagsPart, count; - var confirm = false; // Whether to confirm each replace. - var global = false; // True to replace all instances on a line, false to replace only 1. - if (tokens.length) { - regexPart = tokens[0]; - replacePart = tokens[1]; - if (replacePart !== undefined) { - if (getOption('pcre')) { - replacePart = unescapeRegexReplace(replacePart); - } else { - replacePart = translateRegexReplace(replacePart); - } - vimGlobalState.lastSubstituteReplacePart = replacePart; - } - trailing = tokens[2] ? tokens[2].split(' ') : []; - } else { - // either the argString is empty or its of the form ' hello/world' - // actually splitBySlash returns a list of tokens - // only if the string starts with a '/' - if (argString && argString.length) { - showConfirm(cm, 'Substitutions should be of the form ' + - ':s/pattern/replace/'); - return; - } - } - // After the 3rd slash, we can have flags followed by a space followed - // by count. - if (trailing) { - flagsPart = trailing[0]; - count = parseInt(trailing[1]); - if (flagsPart) { - if (flagsPart.indexOf('c') != -1) { - confirm = true; - flagsPart.replace('c', ''); - } - if (flagsPart.indexOf('g') != -1) { - global = true; - flagsPart.replace('g', ''); - } - regexPart = regexPart + '/' + flagsPart; - } - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise use - // the regex part as the new query. - try { - updateSearchQuery(cm, regexPart, true /** ignoreCase */, - true /** smartCase */); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart); - return; - } - } - replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart; - if (replacePart === undefined) { - showConfirm(cm, 'No previous substitute regular expression'); - return; - } - var state = getSearchState(cm); - var query = state.getQuery(); - var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line; - var lineEnd = params.lineEnd || lineStart; - if (count) { - lineStart = lineEnd; - lineEnd = lineStart + count - 1; - } - var startPos = clipCursorToContent(cm, Pos(lineStart, 0)); - var cursor = cm.getSearchCursor(query, startPos); - doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback); - }, - redo: CodeMirror.commands.redo, - undo: CodeMirror.commands.undo, - write: function(cm) { - if (CodeMirror.commands.save) { - // If a save command is defined, call it. - CodeMirror.commands.save(cm); - } else { - // Saves to text area if no save command is defined. - cm.save(); - } - }, - nohlsearch: function(cm) { - clearSearchHighlight(cm); - }, - delmarks: function(cm, params) { - if (!params.argString || !trim(params.argString)) { - showConfirm(cm, 'Argument required'); - return; - } - - var state = cm.state.vim; - var stream = new CodeMirror.StringStream(trim(params.argString)); - while (!stream.eol()) { - stream.eatSpace(); - - // Record the streams position at the beginning of the loop for use - // in error messages. - var count = stream.pos; - - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - var sym = stream.next(); - // Check if this symbol is part of a range - if (stream.match('-', true)) { - // This symbol is part of a range. - - // The range must terminate at an alphabetic character. - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - var startMark = sym; - var finishMark = stream.next(); - // The range must terminate at an alphabetic character which - // shares the same case as the start of the range. - if (isLowerCase(startMark) && isLowerCase(finishMark) || - isUpperCase(startMark) && isUpperCase(finishMark)) { - var start = startMark.charCodeAt(0); - var finish = finishMark.charCodeAt(0); - if (start >= finish) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - // Because marks are always ASCII values, and we have - // determined that they are the same case, we can use - // their char codes to iterate through the defined range. - for (var j = 0; j <= finish - start; j++) { - var mark = String.fromCharCode(start + j); - delete state.marks[mark]; - } - } else { - showConfirm(cm, 'Invalid argument: ' + startMark + '-'); - return; - } - } else { - // This symbol is a valid mark, and is not part of a range. - delete state.marks[sym]; - } - } - } - }; - - var exCommandDispatcher = new ExCommandDispatcher(); - - /** - * @param {CodeMirror} cm CodeMirror instance we are in. - * @param {boolean} confirm Whether to confirm each replace. - * @param {Cursor} lineStart Line to start replacing from. - * @param {Cursor} lineEnd Line to stop replacing at. - * @param {RegExp} query Query for performing matches with. - * @param {string} replaceWith Text to replace matches with. May contain $1, - * $2, etc for replacing captured groups using Javascript replace. - * @param {function()} callback A callback for when the replace is done. - */ - function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query, - replaceWith, callback) { - // Set up all the functions. - cm.state.vim.exMode = true; - var done = false; - var lastPos = searchCursor.from(); - function replaceAll() { - cm.operation(function() { - while (!done) { - replace(); - next(); - } - stop(); - }); - } - function replace() { - var text = cm.getRange(searchCursor.from(), searchCursor.to()); - var newText = text.replace(query, replaceWith); - searchCursor.replace(newText); - } - function next() { - var found; - // The below only loops to skip over multiple occurrences on the same - // line when 'global' is not true. - while(found = searchCursor.findNext() && - isInRange(searchCursor.from(), lineStart, lineEnd)) { - if (!global && lastPos && searchCursor.from().line == lastPos.line) { - continue; - } - cm.scrollIntoView(searchCursor.from(), 30); - cm.setSelection(searchCursor.from(), searchCursor.to()); - lastPos = searchCursor.from(); - done = false; - return; - } - done = true; - } - function stop(close) { - if (close) { close(); } - cm.focus(); - if (lastPos) { - cm.setCursor(lastPos); - var vim = cm.state.vim; - vim.exMode = false; - vim.lastHPos = vim.lastHSPos = lastPos.ch; - } - if (callback) { callback(); } - } - function onPromptKeyDown(e, _value, close) { - // Swallow all keys. - CodeMirror.e_stop(e); - var keyName = CodeMirror.keyName(e); - switch (keyName) { - case 'Y': - replace(); next(); break; - case 'N': - next(); break; - case 'A': - // replaceAll contains a call to close of its own. We don't want it - // to fire too early or multiple times. - var savedCallback = callback; - callback = undefined; - cm.operation(replaceAll); - callback = savedCallback; - break; - case 'L': - replace(); - // fall through and exit. - case 'Q': - case 'Esc': - case 'Ctrl-C': - case 'Ctrl-[': - stop(close); - break; - } - if (done) { stop(close); } - return true; - } - - // Actually do replace. - next(); - if (done) { - showConfirm(cm, 'No matches for ' + query.source); - return; - } - if (!confirm) { - replaceAll(); - if (callback) { callback(); }; - return; - } - showPrompt(cm, { - prefix: 'replace with ' + replaceWith + ' (y/n/a/q/l)', - onKeyDown: onPromptKeyDown - }); - } - - CodeMirror.keyMap.vim = { - attach: attachVimMap, - detach: detachVimMap, - call: cmKey - }; - - function exitInsertMode(cm) { - var vim = cm.state.vim; - var macroModeState = vimGlobalState.macroModeState; - var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.'); - var isPlaying = macroModeState.isPlaying; - var lastChange = macroModeState.lastInsertModeChanges; - // In case of visual block, the insertModeChanges are not saved as a - // single word, so we convert them to a single word - // so as to update the ". register as expected in real vim. - var text = []; - if (!isPlaying) { - var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1; - var changes = lastChange.changes; - var text = []; - var i = 0; - // In case of multiple selections in blockwise visual, - // the inserted text, for example: 'foo', is stored as - // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines). - // We push the contents of the changes array as per the following: - // 1. In case of InsertModeKey, just increment by 1. - // 2. In case of a character, jump by selLength (2 in the example). - while (i < changes.length) { - // This loop will convert 'ffoooo' to 'foo'. - text.push(changes[i]); - if (changes[i] instanceof InsertModeKey) { - i++; - } else { - i+= selLength; - } - } - lastChange.changes = text; - cm.off('change', onChange); - CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); - } - if (!isPlaying && vim.insertModeRepeat > 1) { - // Perform insert mode repeat for commands like 3,a and 3,o. - repeatLastEdit(cm, vim, vim.insertModeRepeat - 1, - true /** repeatForInsert */); - vim.lastEditInputState.repeatOverride = vim.insertModeRepeat; - } - delete vim.insertModeRepeat; - vim.insertMode = false; - cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1); - cm.setOption('keyMap', 'vim'); - cm.setOption('disableInput', true); - cm.toggleOverwrite(false); // exit replace mode if we were in it. - // update the ". register before exiting insert mode - insertModeChangeRegister.setText(lastChange.changes.join('')); - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - if (macroModeState.isRecording) { - logInsertModeChange(macroModeState); - } - } - - function _mapCommand(command) { - defaultKeymap.push(command); - } - - function mapCommand(keys, type, name, args, extra) { - var command = {keys: keys, type: type}; - command[type] = name; - command[type + "Args"] = args; - for (var key in extra) - command[key] = extra[key]; - _mapCommand(command); - } - - // The timeout in milliseconds for the two-character ESC keymap should be - // adjusted according to your typing speed to prevent false positives. - defineOption('insertModeEscKeysTimeout', 200, 'number'); - - CodeMirror.keyMap['vim-insert'] = { - // TODO: override navigation keys so that Esc will cancel automatic - // indentation from o, O, i_ - 'Ctrl-N': 'autocomplete', - 'Ctrl-P': 'autocomplete', - 'Enter': function(cm) { - var fn = CodeMirror.commands.newlineAndIndentContinueComment || - CodeMirror.commands.newlineAndIndent; - fn(cm); - }, - fallthrough: ['default'], - attach: attachVimMap, - detach: detachVimMap, - call: cmKey - }; - - CodeMirror.keyMap['vim-replace'] = { - 'Backspace': 'goCharLeft', - fallthrough: ['vim-insert'], - attach: attachVimMap, - detach: detachVimMap, - call: cmKey - }; - - function executeMacroRegister(cm, vim, macroModeState, registerName) { - var register = vimGlobalState.registerController.getRegister(registerName); - var keyBuffer = register.keyBuffer; - var imc = 0; - macroModeState.isPlaying = true; - macroModeState.replaySearchQueries = register.searchQueries.slice(0); - for (var i = 0; i < keyBuffer.length; i++) { - var text = keyBuffer[i]; - var match, key; - while (text) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = (/<\w+-.+?>|<\w+>|./).exec(text); - key = match[0]; - text = text.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key, 'macro'); - if (vim.insertMode) { - var changes = register.insertModeChanges[imc++].changes; - vimGlobalState.macroModeState.lastInsertModeChanges.changes = - changes; - repeatInsertModeChanges(cm, changes, 1); - exitInsertMode(cm); - } - } - }; - macroModeState.isPlaying = false; - } - - function logKey(macroModeState, key) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.pushText(key); - } - } - - function logInsertModeChange(macroModeState) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.pushInsertModeChanges(macroModeState.lastInsertModeChanges); - } - } - - function logSearchQuery(macroModeState, query) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.pushSearchQuery(query); - } - } - - /** - * Listens for changes made in insert mode. - * Should only be active in insert mode. - */ - function onChange(_cm, changeObj) { - var macroModeState = vimGlobalState.macroModeState; - var lastChange = macroModeState.lastInsertModeChanges; - if (!macroModeState.isPlaying) { - while(changeObj) { - lastChange.expectCursorActivityForChange = true; - if (changeObj.origin == '+input' || changeObj.origin == 'paste' - || changeObj.origin === undefined /* only in testing */) { - var text = changeObj.text.join('\n'); - lastChange.changes.push(text); - } - // Change objects may be chained with next. - changeObj = changeObj.next; - } - } - } - - /** - * Listens for any kind of cursor activity on CodeMirror. - */ - function onCursorActivity(cm) { - var vim = cm.state.vim; - if (vim.insertMode) { - // Tracking cursor activity in insert mode (for macro support). - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { return; } - var lastChange = macroModeState.lastInsertModeChanges; - if (lastChange.expectCursorActivityForChange) { - lastChange.expectCursorActivityForChange = false; - } else { - // Cursor moved outside the context of an edit. Reset the change. - lastChange.changes = []; - } - } else if (!cm.curOp.isVimOp) { - handleExternalSelection(cm, vim); - } - if (vim.visualMode) { - updateFakeCursor(cm); - } - } - function updateFakeCursor(cm) { - var vim = cm.state.vim; - var from = copyCursor(vim.sel.head); - var to = offsetCursor(from, 0, 1); - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); - } - function handleExternalSelection(cm, vim) { - var anchor = cm.getCursor('anchor'); - var head = cm.getCursor('head'); - // Enter or exit visual mode to match mouse selection. - if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) { - exitVisualMode(cm, false); - } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) { - vim.visualMode = true; - vim.visualLine = false; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); - } - if (vim.visualMode) { - // Bind CodeMirror selection model to vim selection model. - // Mouse selections are considered visual characterwise. - var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; - var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; - head = offsetCursor(head, 0, headOffset); - anchor = offsetCursor(anchor, 0, anchorOffset); - vim.sel = { - anchor: anchor, - head: head - }; - updateMark(cm, vim, '<', cursorMin(head, anchor)); - updateMark(cm, vim, '>', cursorMax(head, anchor)); - } else if (!vim.insertMode) { - // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. - vim.lastHPos = cm.getCursor().ch; - } - } - - /** Wrapper for special keys pressed in insert mode */ - function InsertModeKey(keyName) { - this.keyName = keyName; - } - - /** - * Handles raw key down events from the text area. - * - Should only be active in insert mode. - * - For recording deletes in insert mode. - */ - function onKeyEventTargetKeyDown(e) { - var macroModeState = vimGlobalState.macroModeState; - var lastChange = macroModeState.lastInsertModeChanges; - var keyName = CodeMirror.keyName(e); - if (!keyName) { return; } - function onKeyFound() { - lastChange.changes.push(new InsertModeKey(keyName)); - return true; - } - if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) { - CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound); - } - } - - /** - * Repeats the last edit, which includes exactly 1 command and at most 1 - * insert. Operator and motion commands are read from lastEditInputState, - * while action commands are read from lastEditActionCommand. - * - * If repeatForInsert is true, then the function was called by - * exitInsertMode to repeat the insert mode changes the user just made. The - * corresponding enterInsertMode call was made with a count. - */ - function repeatLastEdit(cm, vim, repeat, repeatForInsert) { - var macroModeState = vimGlobalState.macroModeState; - macroModeState.isPlaying = true; - var isAction = !!vim.lastEditActionCommand; - var cachedInputState = vim.inputState; - function repeatCommand() { - if (isAction) { - commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand); - } else { - commandDispatcher.evalInput(cm, vim); - } - } - function repeatInsert(repeat) { - if (macroModeState.lastInsertModeChanges.changes.length > 0) { - // For some reason, repeat cw in desktop VIM does not repeat - // insert mode changes. Will conform to that behavior. - repeat = !vim.lastEditActionCommand ? 1 : repeat; - var changeObject = macroModeState.lastInsertModeChanges; - repeatInsertModeChanges(cm, changeObject.changes, repeat); - } - } - vim.inputState = vim.lastEditInputState; - if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) { - // o and O repeat have to be interlaced with insert repeats so that the - // insertions appear on separate lines instead of the last line. - for (var i = 0; i < repeat; i++) { - repeatCommand(); - repeatInsert(1); - } - } else { - if (!repeatForInsert) { - // Hack to get the cursor to end up at the right place. If I is - // repeated in insert mode repeat, cursor will be 1 insert - // change set left of where it should be. - repeatCommand(); - } - repeatInsert(repeat); - } - vim.inputState = cachedInputState; - if (vim.insertMode && !repeatForInsert) { - // Don't exit insert mode twice. If repeatForInsert is set, then we - // were called by an exitInsertMode call lower on the stack. - exitInsertMode(cm); - } - macroModeState.isPlaying = false; - }; - - function repeatInsertModeChanges(cm, changes, repeat) { - function keyHandler(binding) { - if (typeof binding == 'string') { - CodeMirror.commands[binding](cm); - } else { - binding(cm); - } - return true; - } - var head = cm.getCursor('head'); - var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; - if (inVisualBlock) { - // Set up block selection again for repeating the changes. - var vim = cm.state.vim; - var lastSel = vim.lastSelection; - var offset = getOffset(lastSel.anchor, lastSel.head); - selectForInsert(cm, head, offset.line + 1); - repeat = cm.listSelections().length; - cm.setCursor(head); - } - for (var i = 0; i < repeat; i++) { - if (inVisualBlock) { - cm.setCursor(offsetCursor(head, i, 0)); - } - for (var j = 0; j < changes.length; j++) { - var change = changes[j]; - if (change instanceof InsertModeKey) { - CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); - } else { - var cur = cm.getCursor(); - cm.replaceRange(change, cur, cur); - } - } - } - if (inVisualBlock) { - cm.setCursor(offsetCursor(head, 0, 1)); - } - } - - resetVimGlobalState(); - return vimApi; - }; - // Initialize Vim and make it available as an API. - CodeMirror.Vim = Vim(); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/apl/apl.js b/shared/html/libs/codemirror/5.0.0/mode/apl/apl.js deleted file mode 100644 index 4357bed..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/apl/apl.js +++ /dev/null @@ -1,175 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("apl", function() { - var builtInOps = { - ".": "innerProduct", - "\\": "scan", - "/": "reduce", - "⌿": "reduce1Axis", - "⍀": "scan1Axis", - "¨": "each", - "⍣": "power" - }; - var builtInFuncs = { - "+": ["conjugate", "add"], - "−": ["negate", "subtract"], - "×": ["signOf", "multiply"], - "÷": ["reciprocal", "divide"], - "⌈": ["ceiling", "greaterOf"], - "⌊": ["floor", "lesserOf"], - "∣": ["absolute", "residue"], - "⍳": ["indexGenerate", "indexOf"], - "?": ["roll", "deal"], - "⋆": ["exponentiate", "toThePowerOf"], - "⍟": ["naturalLog", "logToTheBase"], - "○": ["piTimes", "circularFuncs"], - "!": ["factorial", "binomial"], - "⌹": ["matrixInverse", "matrixDivide"], - "<": [null, "lessThan"], - "≤": [null, "lessThanOrEqual"], - "=": [null, "equals"], - ">": [null, "greaterThan"], - "≥": [null, "greaterThanOrEqual"], - "≠": [null, "notEqual"], - "≡": ["depth", "match"], - "≢": [null, "notMatch"], - "∈": ["enlist", "membership"], - "⍷": [null, "find"], - "∪": ["unique", "union"], - "∩": [null, "intersection"], - "∼": ["not", "without"], - "∨": [null, "or"], - "∧": [null, "and"], - "⍱": [null, "nor"], - "⍲": [null, "nand"], - "⍴": ["shapeOf", "reshape"], - ",": ["ravel", "catenate"], - "⍪": [null, "firstAxisCatenate"], - "⌽": ["reverse", "rotate"], - "⊖": ["axis1Reverse", "axis1Rotate"], - "⍉": ["transpose", null], - "↑": ["first", "take"], - "↓": [null, "drop"], - "⊂": ["enclose", "partitionWithAxis"], - "⊃": ["diclose", "pick"], - "⌷": [null, "index"], - "⍋": ["gradeUp", null], - "⍒": ["gradeDown", null], - "⊤": ["encode", null], - "⊥": ["decode", null], - "⍕": ["format", "formatByExample"], - "⍎": ["execute", null], - "⊣": ["stop", "left"], - "⊢": ["pass", "right"] - }; - - var isOperator = /[\.\/⌿⍀¨⍣]/; - var isNiladic = /⍬/; - var isFunction = /[\+−×÷⌈⌊∣⍳\?⋆⍟○!⌹<≤=>≥≠≡≢∈⍷∪∩∼∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⌷⍋⍒⊤⊥⍕⍎⊣⊢]/; - var isArrow = /←/; - var isComment = /[⍝#].*$/; - - var stringEater = function(type) { - var prev; - prev = false; - return function(c) { - prev = c; - if (c === type) { - return prev === "\\"; - } - return true; - }; - }; - return { - startState: function() { - return { - prev: false, - func: false, - op: false, - string: false, - escape: false - }; - }, - token: function(stream, state) { - var ch, funcName, word; - if (stream.eatSpace()) { - return null; - } - ch = stream.next(); - if (ch === '"' || ch === "'") { - stream.eatWhile(stringEater(ch)); - stream.next(); - state.prev = true; - return "string"; - } - if (/[\[{\(]/.test(ch)) { - state.prev = false; - return null; - } - if (/[\]}\)]/.test(ch)) { - state.prev = true; - return null; - } - if (isNiladic.test(ch)) { - state.prev = false; - return "niladic"; - } - if (/[¯\d]/.test(ch)) { - if (state.func) { - state.func = false; - state.prev = false; - } else { - state.prev = true; - } - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (isOperator.test(ch)) { - return "operator apl-" + builtInOps[ch]; - } - if (isArrow.test(ch)) { - return "apl-arrow"; - } - if (isFunction.test(ch)) { - funcName = "apl-"; - if (builtInFuncs[ch] != null) { - if (state.prev) { - funcName += builtInFuncs[ch][1]; - } else { - funcName += builtInFuncs[ch][0]; - } - } - state.func = true; - state.prev = false; - return "function " + funcName; - } - if (isComment.test(ch)) { - stream.skipToEnd(); - return "comment"; - } - if (ch === "∘" && stream.peek() === ".") { - stream.next(); - return "function jot-dot"; - } - stream.eatWhile(/[\w\$_]/); - word = stream.current(); - state.prev = true; - return "keyword"; - } - }; -}); - -CodeMirror.defineMIME("text/apl", "apl"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/apl/index.html b/shared/html/libs/codemirror/5.0.0/mode/apl/index.html deleted file mode 100644 index 53dda6b..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/apl/index.html +++ /dev/null @@ -1,72 +0,0 @@ - - -CodeMirror: APL mode - - - - - - - - - - -
-

APL mode

-
- - - -

Simple mode that tries to handle APL as well as it can.

-

It attempts to label functions/operators based upon - monadic/dyadic usage (but this is far from fully fleshed out). - This means there are meaningful classnames so hover states can - have popups etc.

- -

MIME types defined: text/apl (APL code)

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/asterisk/asterisk.js b/shared/html/libs/codemirror/5.0.0/mode/asterisk/asterisk.js deleted file mode 100644 index a1ead11..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/asterisk/asterisk.js +++ /dev/null @@ -1,198 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* - * ===================================================================================== - * - * Filename: mode/asterisk/asterisk.js - * - * Description: CodeMirror mode for Asterisk dialplan - * - * Created: 05/17/2012 09:20:25 PM - * Revision: none - * - * Author: Stas Kobzar (stas@modulis.ca), - * Company: Modulis.ca Inc. - * - * ===================================================================================== - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("asterisk", function() { - var atoms = ["exten", "same", "include","ignorepat","switch"], - dpcmd = ["#include","#exec"], - apps = [ - "addqueuemember","adsiprog","aelsub","agentlogin","agentmonitoroutgoing","agi", - "alarmreceiver","amd","answer","authenticate","background","backgrounddetect", - "bridge","busy","callcompletioncancel","callcompletionrequest","celgenuserevent", - "changemonitor","chanisavail","channelredirect","chanspy","clearhash","confbridge", - "congestion","continuewhile","controlplayback","dahdiacceptr2call","dahdibarge", - "dahdiras","dahdiscan","dahdisendcallreroutingfacility","dahdisendkeypadfacility", - "datetime","dbdel","dbdeltree","deadagi","dial","dictate","directory","disa", - "dumpchan","eagi","echo","endwhile","exec","execif","execiftime","exitwhile","extenspy", - "externalivr","festival","flash","followme","forkcdr","getcpeid","gosub","gosubif", - "goto","gotoif","gotoiftime","hangup","iax2provision","ices","importvar","incomplete", - "ivrdemo","jabberjoin","jabberleave","jabbersend","jabbersendgroup","jabberstatus", - "jack","log","macro","macroexclusive","macroexit","macroif","mailboxexists","meetme", - "meetmeadmin","meetmechanneladmin","meetmecount","milliwatt","minivmaccmess","minivmdelete", - "minivmgreet","minivmmwi","minivmnotify","minivmrecord","mixmonitor","monitor","morsecode", - "mp3player","mset","musiconhold","nbscat","nocdr","noop","odbc","odbc","odbcfinish", - "originate","ospauth","ospfinish","osplookup","ospnext","page","park","parkandannounce", - "parkedcall","pausemonitor","pausequeuemember","pickup","pickupchan","playback","playtones", - "privacymanager","proceeding","progress","queue","queuelog","raiseexception","read","readexten", - "readfile","receivefax","receivefax","receivefax","record","removequeuemember", - "resetcdr","retrydial","return","ringing","sayalpha","saycountedadj","saycountednoun", - "saycountpl","saydigits","saynumber","sayphonetic","sayunixtime","senddtmf","sendfax", - "sendfax","sendfax","sendimage","sendtext","sendurl","set","setamaflags", - "setcallerpres","setmusiconhold","sipaddheader","sipdtmfmode","sipremoveheader","skel", - "slastation","slatrunk","sms","softhangup","speechactivategrammar","speechbackground", - "speechcreate","speechdeactivategrammar","speechdestroy","speechloadgrammar","speechprocessingsound", - "speechstart","speechunloadgrammar","stackpop","startmusiconhold","stopmixmonitor","stopmonitor", - "stopmusiconhold","stopplaytones","system","testclient","testserver","transfer","tryexec", - "trysystem","unpausemonitor","unpausequeuemember","userevent","verbose","vmauthenticate", - "vmsayname","voicemail","voicemailmain","wait","waitexten","waitfornoise","waitforring", - "waitforsilence","waitmusiconhold","waituntil","while","zapateller" - ]; - - function basicToken(stream,state){ - var cur = ''; - var ch = ''; - ch = stream.next(); - // comment - if(ch == ";") { - stream.skipToEnd(); - return "comment"; - } - // context - if(ch == '[') { - stream.skipTo(']'); - stream.eat(']'); - return "header"; - } - // string - if(ch == '"') { - stream.skipTo('"'); - return "string"; - } - if(ch == "'") { - stream.skipTo("'"); - return "string-2"; - } - // dialplan commands - if(ch == '#') { - stream.eatWhile(/\w/); - cur = stream.current(); - if(dpcmd.indexOf(cur) !== -1) { - stream.skipToEnd(); - return "strong"; - } - } - // application args - if(ch == '$'){ - var ch1 = stream.peek(); - if(ch1 == '{'){ - stream.skipTo('}'); - stream.eat('}'); - return "variable-3"; - } - } - // extension - stream.eatWhile(/\w/); - cur = stream.current(); - if(atoms.indexOf(cur) !== -1) { - state.extenStart = true; - switch(cur) { - case 'same': state.extenSame = true; break; - case 'include': - case 'switch': - case 'ignorepat': - state.extenInclude = true;break; - default:break; - } - return "atom"; - } - } - - return { - startState: function() { - return { - extenStart: false, - extenSame: false, - extenInclude: false, - extenExten: false, - extenPriority: false, - extenApplication: false - }; - }, - token: function(stream, state) { - - var cur = ''; - var ch = ''; - if(stream.eatSpace()) return null; - // extension started - if(state.extenStart){ - stream.eatWhile(/[^\s]/); - cur = stream.current(); - if(/^=>?$/.test(cur)){ - state.extenExten = true; - state.extenStart = false; - return "strong"; - } else { - state.extenStart = false; - stream.skipToEnd(); - return "error"; - } - } else if(state.extenExten) { - // set exten and priority - state.extenExten = false; - state.extenPriority = true; - stream.eatWhile(/[^,]/); - if(state.extenInclude) { - stream.skipToEnd(); - state.extenPriority = false; - state.extenInclude = false; - } - if(state.extenSame) { - state.extenPriority = false; - state.extenSame = false; - state.extenApplication = true; - } - return "tag"; - } else if(state.extenPriority) { - state.extenPriority = false; - state.extenApplication = true; - ch = stream.next(); // get comma - if(state.extenSame) return null; - stream.eatWhile(/[^,]/); - return "number"; - } else if(state.extenApplication) { - stream.eatWhile(/,/); - cur = stream.current(); - if(cur === ',') return null; - stream.eatWhile(/\w/); - cur = stream.current().toLowerCase(); - state.extenApplication = false; - if(apps.indexOf(cur) !== -1){ - return "def strong"; - } - } else{ - return basicToken(stream,state); - } - - return null; - } - }; -}); - -CodeMirror.defineMIME("text/x-asterisk", "asterisk"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/asterisk/index.html b/shared/html/libs/codemirror/5.0.0/mode/asterisk/index.html deleted file mode 100644 index 257bd39..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/asterisk/index.html +++ /dev/null @@ -1,154 +0,0 @@ - - -CodeMirror: Asterisk dialplan mode - - - - - - - - - -
-

Asterisk dialplan mode

-
- - -

MIME types defined: text/x-asterisk.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/clike/clike.js b/shared/html/libs/codemirror/5.0.0/mode/clike/clike.js deleted file mode 100644 index e2223cc..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/clike/clike.js +++ /dev/null @@ -1,493 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("clike", function(config, parserConfig) { - var indentUnit = config.indentUnit, - statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, - dontAlignCalls = parserConfig.dontAlignCalls, - keywords = parserConfig.keywords || {}, - builtin = parserConfig.builtin || {}, - blockKeywords = parserConfig.blockKeywords || {}, - atoms = parserConfig.atoms || {}, - hooks = parserConfig.hooks || {}, - multiLineStrings = parserConfig.multiLineStrings, - indentStatements = parserConfig.indentStatements !== false; - var isOperatorChar = /[+\-*&%=<>!?|\/]/; - - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (hooks[ch]) { - var result = hooks[ch](stream, state); - if (result !== false) return result; - } - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; - } - if (builtin.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "builtin"; - } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = null; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - var indent = state.indented; - if (state.context && state.context.type == "statement") - indent = state.context.indented; - return state.context = new Context(indent, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state); - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (indentStatements && - (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || - (ctx.type == "statement" && curPunc == "newstatement"))) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass; - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; - var closing = firstChar == ctx.type; - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); - else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1); - else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit; - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "{}", - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//", - fold: "brace" - }; -}); - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var cKeywords = "auto if break int case long char register continue return default short do sizeof " + - "double static else struct entry switch extern typedef float union for unsigned " + - "goto while enum void const signed volatile"; - - function cppHook(stream, state) { - if (!state.startOfLine) return false; - for (;;) { - if (stream.skipTo("\\")) { - stream.next(); - if (stream.eol()) { - state.tokenize = cppHook; - break; - } - } else { - stream.skipToEnd(); - state.tokenize = null; - break; - } - } - return "meta"; - } - - function cpp11StringHook(stream, state) { - stream.backUp(1); - // Raw strings. - if (stream.match(/(R|u8R|uR|UR|LR)/)) { - var match = stream.match(/"([^\s\\()]{0,16})\(/); - if (!match) { - return false; - } - state.cpp11RawStringDelim = match[1]; - state.tokenize = tokenRawString; - return tokenRawString(stream, state); - } - // Unicode strings/chars. - if (stream.match(/(u8|u|U|L)/)) { - if (stream.match(/["']/, /* eat */ false)) { - return "string"; - } - return false; - } - // Ignore this hook. - stream.next(); - return false; - } - - // C#-style strings where "" escapes a quote. - function tokenAtString(stream, state) { - var next; - while ((next = stream.next()) != null) { - if (next == '"' && !stream.eat('"')) { - state.tokenize = null; - break; - } - } - return "string"; - } - - // C++11 raw string literal is "( anything )", where - // can be a string up to 16 characters long. - function tokenRawString(stream, state) { - // Escape characters that have special regex meanings. - var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&'); - var match = stream.match(new RegExp(".*?\\)" + delim + '"')); - if (match) - state.tokenize = null; - else - stream.skipToEnd(); - return "string"; - } - - function def(mimes, mode) { - if (typeof mimes == "string") mimes = [mimes]; - var words = []; - function add(obj) { - if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop)) - words.push(prop); - } - add(mode.keywords); - add(mode.builtin); - add(mode.atoms); - if (words.length) { - mode.helperType = mimes[0]; - CodeMirror.registerHelper("hintWords", mimes[0], words); - } - - for (var i = 0; i < mimes.length; ++i) - CodeMirror.defineMIME(mimes[i], mode); - } - - def(["text/x-csrc", "text/x-c", "text/x-chdr"], { - name: "clike", - keywords: words(cKeywords), - blockKeywords: words("case do else for if switch while struct"), - atoms: words("null"), - hooks: {"#": cppHook}, - modeProps: {fold: ["brace", "include"]} - }); - - def(["text/x-c++src", "text/x-c++hdr"], { - name: "clike", - keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " + - "static_cast typeid catch operator template typename class friend private " + - "this using const_cast inline public throw virtual delete mutable protected " + - "wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final " + - "static_assert override"), - blockKeywords: words("catch class do else finally for if struct switch try while"), - atoms: words("true false null"), - hooks: { - "#": cppHook, - "u": cpp11StringHook, - "U": cpp11StringHook, - "L": cpp11StringHook, - "R": cpp11StringHook - }, - modeProps: {fold: ["brace", "include"]} - }); - - def("text/x-java", { - name: "clike", - keywords: words("abstract assert boolean break byte case catch char class const continue default " + - "do double else enum extends final finally float for goto if implements import " + - "instanceof int interface long native new package private protected public " + - "return short static strictfp super switch synchronized this throw throws transient " + - "try void volatile while"), - blockKeywords: words("catch class do else finally for if switch try while"), - atoms: words("true false null"), - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - }, - modeProps: {fold: ["brace", "import"]} - }); - - def("text/x-csharp", { - name: "clike", - keywords: words("abstract as base break case catch checked class const continue" + - " default delegate do else enum event explicit extern finally fixed for" + - " foreach goto if implicit in interface internal is lock namespace new" + - " operator out override params private protected public readonly ref return sealed" + - " sizeof stackalloc static struct switch this throw try typeof unchecked" + - " unsafe using virtual void volatile while add alias ascending descending dynamic from get" + - " global group into join let orderby partial remove select set value var yield"), - blockKeywords: words("catch class do else finally for foreach if struct switch try while"), - builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" + - " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" + - " UInt64 bool byte char decimal double short int long object" + - " sbyte float string ushort uint ulong"), - atoms: words("true false null"), - hooks: { - "@": function(stream, state) { - if (stream.eat('"')) { - state.tokenize = tokenAtString; - return tokenAtString(stream, state); - } - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - } - }); - - function tokenTripleString(stream, state) { - var escaped = false; - while (!stream.eol()) { - if (!escaped && stream.match('"""')) { - state.tokenize = null; - break; - } - escaped = stream.next() == "\\" && !escaped; - } - return "string"; - } - - def("text/x-scala", { - name: "clike", - keywords: words( - - /* scala */ - "abstract case catch class def do else extends false final finally for forSome if " + - "implicit import lazy match new null object override package private protected return " + - "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " + - "<% >: # @ " + - - /* package scala */ - "assert assume require print println printf readLine readBoolean readByte readShort " + - "readChar readInt readLong readFloat readDouble " + - - "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " + - "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " + - "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " + - "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " + - "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " + - - /* package java.lang */ - "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " + - "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " + - "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + - "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" - ), - multiLineStrings: true, - blockKeywords: words("catch class do else finally for forSome if match switch try while"), - atoms: words("true false null"), - indentStatements: false, - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - }, - '"': function(stream, state) { - if (!stream.match('""')) return false; - state.tokenize = tokenTripleString; - return state.tokenize(stream, state); - }, - "'": function(stream) { - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - return "atom"; - } - } - }); - - def(["x-shader/x-vertex", "x-shader/x-fragment"], { - name: "clike", - keywords: words("float int bool void " + - "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " + - "mat2 mat3 mat4 " + - "sampler1D sampler2D sampler3D samplerCube " + - "sampler1DShadow sampler2DShadow " + - "const attribute uniform varying " + - "break continue discard return " + - "for while do if else struct " + - "in out inout"), - blockKeywords: words("for while do if else struct"), - builtin: words("radians degrees sin cos tan asin acos atan " + - "pow exp log exp2 sqrt inversesqrt " + - "abs sign floor ceil fract mod min max clamp mix step smoothstep " + - "length distance dot cross normalize ftransform faceforward " + - "reflect refract matrixCompMult " + - "lessThan lessThanEqual greaterThan greaterThanEqual " + - "equal notEqual any all not " + - "texture1D texture1DProj texture1DLod texture1DProjLod " + - "texture2D texture2DProj texture2DLod texture2DProjLod " + - "texture3D texture3DProj texture3DLod texture3DProjLod " + - "textureCube textureCubeLod " + - "shadow1D shadow2D shadow1DProj shadow2DProj " + - "shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " + - "dFdx dFdy fwidth " + - "noise1 noise2 noise3 noise4"), - atoms: words("true false " + - "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " + - "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " + - "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " + - "gl_FogCoord gl_PointCoord " + - "gl_Position gl_PointSize gl_ClipVertex " + - "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " + - "gl_TexCoord gl_FogFragCoord " + - "gl_FragCoord gl_FrontFacing " + - "gl_FragData gl_FragDepth " + - "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " + - "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " + - "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " + - "gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " + - "gl_ProjectionMatrixInverseTranspose " + - "gl_ModelViewProjectionMatrixInverseTranspose " + - "gl_TextureMatrixInverseTranspose " + - "gl_NormalScale gl_DepthRange gl_ClipPlane " + - "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " + - "gl_FrontLightModelProduct gl_BackLightModelProduct " + - "gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " + - "gl_FogParameters " + - "gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " + - "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " + - "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " + - "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " + - "gl_MaxDrawBuffers"), - hooks: {"#": cppHook}, - modeProps: {fold: ["brace", "include"]} - }); - - def("text/x-nesc", { - name: "clike", - keywords: words(cKeywords + "as atomic async call command component components configuration event generic " + - "implementation includes interface module new norace nx_struct nx_union post provides " + - "signal task uses abstract extends"), - blockKeywords: words("case do else for if switch while struct"), - atoms: words("null"), - hooks: {"#": cppHook}, - modeProps: {fold: ["brace", "include"]} - }); - - def("text/x-objectivec", { - name: "clike", - keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " + - "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"), - atoms: words("YES NO NULL NILL ON OFF"), - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$]/); - return "keyword"; - }, - "#": cppHook - }, - modeProps: {fold: "brace"} - }); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/clike/index.html b/shared/html/libs/codemirror/5.0.0/mode/clike/index.html deleted file mode 100644 index 8b386d2..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/clike/index.html +++ /dev/null @@ -1,251 +0,0 @@ - - -CodeMirror: C-like mode - - - - - - - - - - - - -
-

C-like mode

- -
- -

C++ example

- -
- -

Objective-C example

- -
- -

Java example

- -
- -

Scala example

- -
- - - -

Simple mode that tries to handle C-like languages as well as it - can. Takes two configuration parameters: keywords, an - object whose property names are the keywords in the language, - and useCPP, which determines whether C preprocessor - directives are recognized.

- -

MIME types defined: text/x-csrc - (C), text/x-c++src (C++), text/x-java - (Java), text/x-csharp (C#), - text/x-objectivec (Objective-C), - text/x-scala (Scala), text/x-vertex - and x-shader/x-fragment (shader programs).

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/clike/scala.html b/shared/html/libs/codemirror/5.0.0/mode/clike/scala.html deleted file mode 100644 index aa04cf0..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/clike/scala.html +++ /dev/null @@ -1,767 +0,0 @@ - - -CodeMirror: Scala mode - - - - - - - - - - -
-

Scala mode

-
- -
- - -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/clojure/clojure.js b/shared/html/libs/codemirror/5.0.0/mode/clojure/clojure.js deleted file mode 100644 index c334de7..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/clojure/clojure.js +++ /dev/null @@ -1,243 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Author: Hans Engel - * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun) - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("clojure", function (options) { - var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2", - ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword", VAR = "variable"; - var INDENT_WORD_SKIP = options.indentUnit || 2; - var NORMAL_INDENT_UNIT = options.indentUnit || 2; - - function makeKeywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var atoms = makeKeywords("true false nil"); - - var keywords = makeKeywords( - "defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle"); - - var builtins = makeKeywords( - "* *' *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* *compile-path* *compiler-options* *data-readers* *e *err* *file* *flush-on-newline* *fn-loader* *in* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *unchecked-math* *use-context-classloader* *verbose-defrecords* *warn-on-reflection* + +' - -' -> ->> ->ArrayChunk ->Vec ->VecNode ->VecSeq -cache-protocol-fn -reset-methods .. / < <= = == > >= EMPTY-NODE accessor aclone add-classpath add-watch agent agent-error agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint biginteger binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* bound? butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec dec' decimal? declare default-data-readers definline definterface defmacro defmethod defmulti defn defn- defonce defprotocol defrecord defstruct deftype delay delay? deliver denominator deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq error-handler error-mode eval even? every-pred every? ex-data ex-info extend extend-protocol extend-type extenders extends? false? ffirst file-seq filter filterv find find-keyword find-ns find-protocol-impl find-protocol-method find-var first flatten float float-array float? floats flush fn fn? fnext fnil for force format frequencies future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator group-by hash hash-combine hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc inc' init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt keep keep-indexed key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map-indexed map? mapcat mapv max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod munge name namespace namespace-munge neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext nthrest num number? numerator object-array odd? or parents partial partition partition-all partition-by pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-dup print-method print-simple print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int rand-nth range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string realized? reduce reduce-kv reductions ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure reify release-pending-sends rem remove remove-all-methods remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest restart-agent resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-error-handler! set-error-mode! set-validator! set? short short-array shorts shuffle shutdown-agents slurp some some-fn sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-symbol? spit split-at split-with str string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync take take-last take-nth take-while test the-ns thread-bound? time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-add-int unchecked-byte unchecked-char unchecked-dec unchecked-dec-int unchecked-divide-int unchecked-double unchecked-float unchecked-inc unchecked-inc-int unchecked-int unchecked-long unchecked-multiply unchecked-multiply-int unchecked-negate unchecked-negate-int unchecked-remainder-int unchecked-short unchecked-subtract unchecked-subtract-int underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector-of vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision with-redefs with-redefs-fn xml-seq zero? zipmap *default-data-reader-fn* as-> cond-> cond->> reduced reduced? send-via set-agent-send-executor! set-agent-send-off-executor! some-> some->>"); - - var indentKeys = makeKeywords( - // Built-ins - "ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch " + - - // Binding forms - "let letfn binding loop for doseq dotimes when-let if-let " + - - // Data structures - "defstruct struct-map assoc " + - - // clojure.test - "testing deftest " + - - // contrib - "handler-case handle dotrace deftrace"); - - var tests = { - digit: /\d/, - digit_or_colon: /[\d:]/, - hex: /[0-9a-f]/i, - sign: /[+-]/, - exponent: /e/i, - keyword_char: /[^\s\(\[\;\)\]]/, - symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/ - }; - - function stateStack(indent, type, prev) { // represents a state stack object - this.indent = indent; - this.type = type; - this.prev = prev; - } - - function pushStack(state, indent, type) { - state.indentStack = new stateStack(indent, type, state.indentStack); - } - - function popStack(state) { - state.indentStack = state.indentStack.prev; - } - - function isNumber(ch, stream){ - // hex - if ( ch === '0' && stream.eat(/x/i) ) { - stream.eatWhile(tests.hex); - return true; - } - - // leading sign - if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) { - stream.eat(tests.sign); - ch = stream.next(); - } - - if ( tests.digit.test(ch) ) { - stream.eat(ch); - stream.eatWhile(tests.digit); - - if ( '.' == stream.peek() ) { - stream.eat('.'); - stream.eatWhile(tests.digit); - } - - if ( stream.eat(tests.exponent) ) { - stream.eat(tests.sign); - stream.eatWhile(tests.digit); - } - - return true; - } - - return false; - } - - // Eat character that starts after backslash \ - function eatCharacter(stream) { - var first = stream.next(); - // Read special literals: backspace, newline, space, return. - // Just read all lowercase letters. - if (first && first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) { - return; - } - // Read unicode character: \u1000 \uA0a1 - if (first === "u") { - stream.match(/[0-9a-z]{4}/i, true); - } - } - - return { - startState: function () { - return { - indentStack: null, - indentation: 0, - mode: false - }; - }, - - token: function (stream, state) { - if (state.indentStack == null && stream.sol()) { - // update indentation, but only if indentStack is empty - state.indentation = stream.indentation(); - } - - // skip spaces - if (stream.eatSpace()) { - return null; - } - var returnType = null; - - switch(state.mode){ - case "string": // multi-line string parsing mode - var next, escaped = false; - while ((next = stream.next()) != null) { - if (next == "\"" && !escaped) { - - state.mode = false; - break; - } - escaped = !escaped && next == "\\"; - } - returnType = STRING; // continue on in string mode - break; - default: // default parsing mode - var ch = stream.next(); - - if (ch == "\"") { - state.mode = "string"; - returnType = STRING; - } else if (ch == "\\") { - eatCharacter(stream); - returnType = CHARACTER; - } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) { - returnType = ATOM; - } else if (ch == ";") { // comment - stream.skipToEnd(); // rest of the line is a comment - returnType = COMMENT; - } else if (isNumber(ch,stream)){ - returnType = NUMBER; - } else if (ch == "(" || ch == "[" || ch == "{" ) { - var keyWord = '', indentTemp = stream.column(), letter; - /** - Either - (indent-word .. - (non-indent-word .. - (;something else, bracket, etc. - */ - - if (ch == "(") while ((letter = stream.eat(tests.keyword_char)) != null) { - keyWord += letter; - } - - if (keyWord.length > 0 && (indentKeys.propertyIsEnumerable(keyWord) || - /^(?:def|with)/.test(keyWord))) { // indent-word - pushStack(state, indentTemp + INDENT_WORD_SKIP, ch); - } else { // non-indent word - // we continue eating the spaces - stream.eatSpace(); - if (stream.eol() || stream.peek() == ";") { - // nothing significant after - // we restart indentation the user defined spaces after - pushStack(state, indentTemp + NORMAL_INDENT_UNIT, ch); - } else { - pushStack(state, indentTemp + stream.current().length, ch); // else we match - } - } - stream.backUp(stream.current().length - 1); // undo all the eating - - returnType = BRACKET; - } else if (ch == ")" || ch == "]" || ch == "}") { - returnType = BRACKET; - if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : (ch == "]" ? "[" :"{"))) { - popStack(state); - } - } else if ( ch == ":" ) { - stream.eatWhile(tests.symbol); - return ATOM; - } else { - stream.eatWhile(tests.symbol); - - if (keywords && keywords.propertyIsEnumerable(stream.current())) { - returnType = KEYWORD; - } else if (builtins && builtins.propertyIsEnumerable(stream.current())) { - returnType = BUILTIN; - } else if (atoms && atoms.propertyIsEnumerable(stream.current())) { - returnType = ATOM; - } else { - returnType = VAR; - } - } - } - - return returnType; - }, - - indent: function (state) { - if (state.indentStack == null) return state.indentation; - return state.indentStack.indent; - }, - - lineComment: ";;" - }; -}); - -CodeMirror.defineMIME("text/x-clojure", "clojure"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/clojure/index.html b/shared/html/libs/codemirror/5.0.0/mode/clojure/index.html deleted file mode 100644 index 3ecf4c4..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/clojure/index.html +++ /dev/null @@ -1,88 +0,0 @@ - - -CodeMirror: Clojure mode - - - - - - - - - -
-

Clojure mode

-
- - -

MIME types defined: text/x-clojure.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/cobol/cobol.js b/shared/html/libs/codemirror/5.0.0/mode/cobol/cobol.js deleted file mode 100644 index 897022b..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/cobol/cobol.js +++ /dev/null @@ -1,255 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Author: Gautam Mehta - * Branched from CodeMirror's Scheme mode - */ -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("cobol", function () { - var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", - ATOM = "atom", NUMBER = "number", KEYWORD = "keyword", MODTAG = "header", - COBOLLINENUM = "def", PERIOD = "link"; - function makeKeywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var atoms = makeKeywords("TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES "); - var keywords = makeKeywords( - "ACCEPT ACCESS ACQUIRE ADD ADDRESS " + - "ADVANCING AFTER ALIAS ALL ALPHABET " + - "ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED " + - "ALSO ALTER ALTERNATE AND ANY " + - "ARE AREA AREAS ARITHMETIC ASCENDING " + - "ASSIGN AT ATTRIBUTE AUTHOR AUTO " + - "AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS " + - "B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP " + - "BEFORE BELL BINARY BIT BITS " + - "BLANK BLINK BLOCK BOOLEAN BOTTOM " + - "BY CALL CANCEL CD CF " + - "CH CHARACTER CHARACTERS CLASS CLOCK-UNITS " + - "CLOSE COBOL CODE CODE-SET COL " + - "COLLATING COLUMN COMMA COMMIT COMMITMENT " + - "COMMON COMMUNICATION COMP COMP-0 COMP-1 " + - "COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 " + - "COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 " + - "COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 " + - "COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE " + - "CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS " + - "CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS " + - "CONVERTING COPY CORR CORRESPONDING COUNT " + - "CRT CRT-UNDER CURRENCY CURRENT CURSOR " + - "DATA DATE DATE-COMPILED DATE-WRITTEN DAY " + - "DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION " + - "DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS " + - "DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE " + - "DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING " + - "DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED " + - "DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION " + - "DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 " + - "DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 " + - "DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION " + - "DOWN DROP DUPLICATE DUPLICATES DYNAMIC " + - "EBCDIC EGI EJECT ELSE EMI " + - "EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. " + - "END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY " + - "END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY " + - "END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN " + - "END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT " + - "END-UNSTRING END-WRITE END-XML ENTER ENTRY " + - "ENVIRONMENT EOP EQUAL EQUALS ERASE " + - "ERROR ESI EVALUATE EVERY EXCEEDS " + - "EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL " + - "EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL " + - "FILE-STREAM FILES FILLER FINAL FIND " + - "FINISH FIRST FOOTING FOR FOREGROUND-COLOR " + - "FOREGROUND-COLOUR FORMAT FREE FROM FULL " + - "FUNCTION GENERATE GET GIVING GLOBAL " + - "GO GOBACK GREATER GROUP HEADING " + - "HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL " + - "ID IDENTIFICATION IF IN INDEX " + - "INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 " + - "INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED " + - "INDIC INDICATE INDICATOR INDICATORS INITIAL " + - "INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT " + - "INSTALLATION INTO INVALID INVOKE IS " + - "JUST JUSTIFIED KANJI KEEP KEY " + - "LABEL LAST LD LEADING LEFT " + - "LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY " + - "LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER " + - "LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE " + - "LOCALE LOCALLY LOCK " + - "MEMBER MEMORY MERGE MESSAGE METACLASS " + - "MODE MODIFIED MODIFY MODULES MOVE " + - "MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE " + - "NEXT NO NO-ECHO NONE NOT " + - "NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER " + - "NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS " + - "OF OFF OMITTED ON ONLY " + - "OPEN OPTIONAL OR ORDER ORGANIZATION " + - "OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL " + - "PADDING PAGE PAGE-COUNTER PARSE PERFORM " + - "PF PH PIC PICTURE PLUS " + - "POINTER POSITION POSITIVE PREFIX PRESENT " + - "PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES " + - "PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID " + - "PROMPT PROTECTED PURGE QUEUE QUOTE " + - "QUOTES RANDOM RD READ READY " + - "REALM RECEIVE RECONNECT RECORD RECORD-NAME " + - "RECORDS RECURSIVE REDEFINES REEL REFERENCE " + - "REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE " + - "REMAINDER REMOVAL RENAMES REPEATED REPLACE " + - "REPLACING REPORT REPORTING REPORTS REPOSITORY " + - "REQUIRED RERUN RESERVE RESET RETAINING " + - "RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO " + - "REVERSED REWIND REWRITE RF RH " + - "RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED " + - "RUN SAME SCREEN SD SEARCH " + - "SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT " + - "SELECT SEND SENTENCE SEPARATE SEQUENCE " + - "SEQUENTIAL SET SHARED SIGN SIZE " + - "SKIP1 SKIP2 SKIP3 SORT SORT-MERGE " + - "SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL " + - "SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 " + - "START STARTING STATUS STOP STORE " + - "STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA " + - "SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS " + - "SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT " + - "TABLE TALLYING TAPE TENANT TERMINAL " + - "TERMINATE TEST TEXT THAN THEN " + - "THROUGH THRU TIME TIMES TITLE " + - "TO TOP TRAILING TRAILING-SIGN TRANSACTION " + - "TYPE TYPEDEF UNDERLINE UNEQUAL UNIT " + - "UNSTRING UNTIL UP UPDATE UPON " + - "USAGE USAGE-MODE USE USING VALID " + - "VALIDATE VALUE VALUES VARYING VLR " + - "WAIT WHEN WHEN-COMPILED WITH WITHIN " + - "WORDS WORKING-STORAGE WRITE XML XML-CODE " + - "XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL " ); - - var builtins = makeKeywords("- * ** / + < <= = > >= "); - var tests = { - digit: /\d/, - digit_or_colon: /[\d:]/, - hex: /[0-9a-f]/i, - sign: /[+-]/, - exponent: /e/i, - keyword_char: /[^\s\(\[\;\)\]]/, - symbol: /[\w*+\-]/ - }; - function isNumber(ch, stream){ - // hex - if ( ch === '0' && stream.eat(/x/i) ) { - stream.eatWhile(tests.hex); - return true; - } - // leading sign - if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) { - stream.eat(tests.sign); - ch = stream.next(); - } - if ( tests.digit.test(ch) ) { - stream.eat(ch); - stream.eatWhile(tests.digit); - if ( '.' == stream.peek()) { - stream.eat('.'); - stream.eatWhile(tests.digit); - } - if ( stream.eat(tests.exponent) ) { - stream.eat(tests.sign); - stream.eatWhile(tests.digit); - } - return true; - } - return false; - } - return { - startState: function () { - return { - indentStack: null, - indentation: 0, - mode: false - }; - }, - token: function (stream, state) { - if (state.indentStack == null && stream.sol()) { - // update indentation, but only if indentStack is empty - state.indentation = 6 ; //stream.indentation(); - } - // skip spaces - if (stream.eatSpace()) { - return null; - } - var returnType = null; - switch(state.mode){ - case "string": // multi-line string parsing mode - var next = false; - while ((next = stream.next()) != null) { - if (next == "\"" || next == "\'") { - state.mode = false; - break; - } - } - returnType = STRING; // continue on in string mode - break; - default: // default parsing mode - var ch = stream.next(); - var col = stream.column(); - if (col >= 0 && col <= 5) { - returnType = COBOLLINENUM; - } else if (col >= 72 && col <= 79) { - stream.skipToEnd(); - returnType = MODTAG; - } else if (ch == "*" && col == 6) { // comment - stream.skipToEnd(); // rest of the line is a comment - returnType = COMMENT; - } else if (ch == "\"" || ch == "\'") { - state.mode = "string"; - returnType = STRING; - } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) { - returnType = ATOM; - } else if (ch == ".") { - returnType = PERIOD; - } else if (isNumber(ch,stream)){ - returnType = NUMBER; - } else { - if (stream.current().match(tests.symbol)) { - while (col < 71) { - if (stream.eat(tests.symbol) === undefined) { - break; - } else { - col++; - } - } - } - if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) { - returnType = KEYWORD; - } else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) { - returnType = BUILTIN; - } else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) { - returnType = ATOM; - } else returnType = null; - } - } - return returnType; - }, - indent: function (state) { - if (state.indentStack == null) return state.indentation; - return state.indentStack.indent; - } - }; -}); - -CodeMirror.defineMIME("text/x-cobol", "cobol"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/cobol/index.html b/shared/html/libs/codemirror/5.0.0/mode/cobol/index.html deleted file mode 100644 index 4352419..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/cobol/index.html +++ /dev/null @@ -1,210 +0,0 @@ - - -CodeMirror: COBOL mode - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

COBOL mode

- -

Select Theme Select Font Size - - - - -

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/coffeescript/coffeescript.js b/shared/html/libs/codemirror/5.0.0/mode/coffeescript/coffeescript.js deleted file mode 100644 index da0eb2d..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/coffeescript/coffeescript.js +++ /dev/null @@ -1,369 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Link to the project's GitHub page: - * https://github.com/pickhardt/coffeescript-codemirror-mode - */ -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("coffeescript", function(conf, parserConf) { - var ERRORCLASS = "error"; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); - } - - var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/; - var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/; - var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/; - var properties = /^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*/; - - var wordOperators = wordRegexp(["and", "or", "not", - "is", "isnt", "in", - "instanceof", "typeof"]); - var indentKeywords = ["for", "while", "loop", "if", "unless", "else", - "switch", "try", "catch", "finally", "class"]; - var commonKeywords = ["break", "by", "continue", "debugger", "delete", - "do", "in", "of", "new", "return", "then", - "this", "@", "throw", "when", "until", "extends"]; - - var keywords = wordRegexp(indentKeywords.concat(commonKeywords)); - - indentKeywords = wordRegexp(indentKeywords); - - - var stringPrefixes = /^('{3}|\"{3}|['\"])/; - var regexPrefixes = /^(\/{3}|\/)/; - var commonConstants = ["Infinity", "NaN", "undefined", "null", "true", "false", "on", "off", "yes", "no"]; - var constants = wordRegexp(commonConstants); - - // Tokenizers - function tokenBase(stream, state) { - // Handle scope changes - if (stream.sol()) { - if (state.scope.align === null) state.scope.align = false; - var scopeOffset = state.scope.offset; - if (stream.eatSpace()) { - var lineOffset = stream.indentation(); - if (lineOffset > scopeOffset && state.scope.type == "coffee") { - return "indent"; - } else if (lineOffset < scopeOffset) { - return "dedent"; - } - return null; - } else { - if (scopeOffset > 0) { - dedent(stream, state); - } - } - } - if (stream.eatSpace()) { - return null; - } - - var ch = stream.peek(); - - // Handle docco title comment (single line) - if (stream.match("####")) { - stream.skipToEnd(); - return "comment"; - } - - // Handle multi line comments - if (stream.match("###")) { - state.tokenize = longComment; - return state.tokenize(stream, state); - } - - // Single line comment - if (ch === "#") { - stream.skipToEnd(); - return "comment"; - } - - // Handle number literals - if (stream.match(/^-?[0-9\.]/, false)) { - var floatLiteral = false; - // Floats - if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) { - floatLiteral = true; - } - if (stream.match(/^-?\d+\.\d*/)) { - floatLiteral = true; - } - if (stream.match(/^-?\.\d+/)) { - floatLiteral = true; - } - - if (floatLiteral) { - // prevent from getting extra . on 1.. - if (stream.peek() == "."){ - stream.backUp(1); - } - return "number"; - } - // Integers - var intLiteral = false; - // Hex - if (stream.match(/^-?0x[0-9a-f]+/i)) { - intLiteral = true; - } - // Decimal - if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) { - intLiteral = true; - } - // Zero by itself with no other piece of number. - if (stream.match(/^-?0(?![\dx])/i)) { - intLiteral = true; - } - if (intLiteral) { - return "number"; - } - } - - // Handle strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenFactory(stream.current(), false, "string"); - return state.tokenize(stream, state); - } - // Handle regex literals - if (stream.match(regexPrefixes)) { - if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division - state.tokenize = tokenFactory(stream.current(), true, "string-2"); - return state.tokenize(stream, state); - } else { - stream.backUp(1); - } - } - - // Handle operators and delimiters - if (stream.match(operators) || stream.match(wordOperators)) { - return "operator"; - } - if (stream.match(delimiters)) { - return "punctuation"; - } - - if (stream.match(constants)) { - return "atom"; - } - - if (stream.match(keywords)) { - return "keyword"; - } - - if (stream.match(identifiers)) { - return "variable"; - } - - if (stream.match(properties)) { - return "property"; - } - - // Handle non-detected items - stream.next(); - return ERRORCLASS; - } - - function tokenFactory(delimiter, singleline, outclass) { - return function(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^'"\/\\]/); - if (stream.eat("\\")) { - stream.next(); - if (singleline && stream.eol()) { - return outclass; - } - } else if (stream.match(delimiter)) { - state.tokenize = tokenBase; - return outclass; - } else { - stream.eat(/['"\/]/); - } - } - if (singleline) { - if (parserConf.singleLineStringErrors) { - outclass = ERRORCLASS; - } else { - state.tokenize = tokenBase; - } - } - return outclass; - }; - } - - function longComment(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^#]/); - if (stream.match("###")) { - state.tokenize = tokenBase; - break; - } - stream.eatWhile("#"); - } - return "comment"; - } - - function indent(stream, state, type) { - type = type || "coffee"; - var offset = 0, align = false, alignOffset = null; - for (var scope = state.scope; scope; scope = scope.prev) { - if (scope.type === "coffee" || scope.type == "}") { - offset = scope.offset + conf.indentUnit; - break; - } - } - if (type !== "coffee") { - align = null; - alignOffset = stream.column() + stream.current().length; - } else if (state.scope.align) { - state.scope.align = false; - } - state.scope = { - offset: offset, - type: type, - prev: state.scope, - align: align, - alignOffset: alignOffset - }; - } - - function dedent(stream, state) { - if (!state.scope.prev) return; - if (state.scope.type === "coffee") { - var _indent = stream.indentation(); - var matched = false; - for (var scope = state.scope; scope; scope = scope.prev) { - if (_indent === scope.offset) { - matched = true; - break; - } - } - if (!matched) { - return true; - } - while (state.scope.prev && state.scope.offset !== _indent) { - state.scope = state.scope.prev; - } - return false; - } else { - state.scope = state.scope.prev; - return false; - } - } - - function tokenLexer(stream, state) { - var style = state.tokenize(stream, state); - var current = stream.current(); - - // Handle "." connected identifiers - if (current === ".") { - style = state.tokenize(stream, state); - current = stream.current(); - if (/^\.[\w$]+$/.test(current)) { - return "variable"; - } else { - return ERRORCLASS; - } - } - - // Handle scope changes. - if (current === "return") { - state.dedent = true; - } - if (((current === "->" || current === "=>") && - !state.lambda && - !stream.peek()) - || style === "indent") { - indent(stream, state); - } - var delimiter_index = "[({".indexOf(current); - if (delimiter_index !== -1) { - indent(stream, state, "])}".slice(delimiter_index, delimiter_index+1)); - } - if (indentKeywords.exec(current)){ - indent(stream, state); - } - if (current == "then"){ - dedent(stream, state); - } - - - if (style === "dedent") { - if (dedent(stream, state)) { - return ERRORCLASS; - } - } - delimiter_index = "])}".indexOf(current); - if (delimiter_index !== -1) { - while (state.scope.type == "coffee" && state.scope.prev) - state.scope = state.scope.prev; - if (state.scope.type == current) - state.scope = state.scope.prev; - } - if (state.dedent && stream.eol()) { - if (state.scope.type == "coffee" && state.scope.prev) - state.scope = state.scope.prev; - state.dedent = false; - } - - return style; - } - - var external = { - startState: function(basecolumn) { - return { - tokenize: tokenBase, - scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false}, - lastToken: null, - lambda: false, - dedent: 0 - }; - }, - - token: function(stream, state) { - var fillAlign = state.scope.align === null && state.scope; - if (fillAlign && stream.sol()) fillAlign.align = false; - - var style = tokenLexer(stream, state); - if (fillAlign && style && style != "comment") fillAlign.align = true; - - state.lastToken = {style:style, content: stream.current()}; - - if (stream.eol() && stream.lambda) { - state.lambda = false; - } - - return style; - }, - - indent: function(state, text) { - if (state.tokenize != tokenBase) return 0; - var scope = state.scope; - var closer = text && "])}".indexOf(text.charAt(0)) > -1; - if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev; - var closes = closer && scope.type === text.charAt(0); - if (scope.align) - return scope.alignOffset - (closes ? 1 : 0); - else - return (closes ? scope.prev : scope).offset; - }, - - lineComment: "#", - fold: "indent" - }; - return external; -}); - -CodeMirror.defineMIME("text/x-coffeescript", "coffeescript"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/coffeescript/index.html b/shared/html/libs/codemirror/5.0.0/mode/coffeescript/index.html deleted file mode 100644 index 93a5f4f..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/coffeescript/index.html +++ /dev/null @@ -1,740 +0,0 @@ - - -CodeMirror: CoffeeScript mode - - - - - - - - - -
-

CoffeeScript mode

-
- - -

MIME types defined: text/x-coffeescript.

- -

The CoffeeScript mode was written by Jeff Pickhardt.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/commonlisp/commonlisp.js b/shared/html/libs/codemirror/5.0.0/mode/commonlisp/commonlisp.js deleted file mode 100644 index 5f50b35..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/commonlisp/commonlisp.js +++ /dev/null @@ -1,122 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("commonlisp", function (config) { - var specialForm = /^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/; - var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/; - var numLiteral = /^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/; - var symbol = /[^\s'`,@()\[\]";]/; - var type; - - function readSym(stream) { - var ch; - while (ch = stream.next()) { - if (ch == "\\") stream.next(); - else if (!symbol.test(ch)) { stream.backUp(1); break; } - } - return stream.current(); - } - - function base(stream, state) { - if (stream.eatSpace()) {type = "ws"; return null;} - if (stream.match(numLiteral)) return "number"; - var ch = stream.next(); - if (ch == "\\") ch = stream.next(); - - if (ch == '"') return (state.tokenize = inString)(stream, state); - else if (ch == "(") { type = "open"; return "bracket"; } - else if (ch == ")" || ch == "]") { type = "close"; return "bracket"; } - else if (ch == ";") { stream.skipToEnd(); type = "ws"; return "comment"; } - else if (/['`,@]/.test(ch)) return null; - else if (ch == "|") { - if (stream.skipTo("|")) { stream.next(); return "symbol"; } - else { stream.skipToEnd(); return "error"; } - } else if (ch == "#") { - var ch = stream.next(); - if (ch == "[") { type = "open"; return "bracket"; } - else if (/[+\-=\.']/.test(ch)) return null; - else if (/\d/.test(ch) && stream.match(/^\d*#/)) return null; - else if (ch == "|") return (state.tokenize = inComment)(stream, state); - else if (ch == ":") { readSym(stream); return "meta"; } - else return "error"; - } else { - var name = readSym(stream); - if (name == ".") return null; - type = "symbol"; - if (name == "nil" || name == "t" || name.charAt(0) == ":") return "atom"; - if (state.lastType == "open" && (specialForm.test(name) || assumeBody.test(name))) return "keyword"; - if (name.charAt(0) == "&") return "variable-2"; - return "variable"; - } - } - - function inString(stream, state) { - var escaped = false, next; - while (next = stream.next()) { - if (next == '"' && !escaped) { state.tokenize = base; break; } - escaped = !escaped && next == "\\"; - } - return "string"; - } - - function inComment(stream, state) { - var next, last; - while (next = stream.next()) { - if (next == "#" && last == "|") { state.tokenize = base; break; } - last = next; - } - type = "ws"; - return "comment"; - } - - return { - startState: function () { - return {ctx: {prev: null, start: 0, indentTo: 0}, lastType: null, tokenize: base}; - }, - - token: function (stream, state) { - if (stream.sol() && typeof state.ctx.indentTo != "number") - state.ctx.indentTo = state.ctx.start + 1; - - type = null; - var style = state.tokenize(stream, state); - if (type != "ws") { - if (state.ctx.indentTo == null) { - if (type == "symbol" && assumeBody.test(stream.current())) - state.ctx.indentTo = state.ctx.start + config.indentUnit; - else - state.ctx.indentTo = "next"; - } else if (state.ctx.indentTo == "next") { - state.ctx.indentTo = stream.column(); - } - state.lastType = type; - } - if (type == "open") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null}; - else if (type == "close") state.ctx = state.ctx.prev || state.ctx; - return style; - }, - - indent: function (state, _textAfter) { - var i = state.ctx.indentTo; - return typeof i == "number" ? i : state.ctx.start + 1; - }, - - lineComment: ";;", - blockCommentStart: "#|", - blockCommentEnd: "|#" - }; -}); - -CodeMirror.defineMIME("text/x-common-lisp", "commonlisp"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/commonlisp/index.html b/shared/html/libs/codemirror/5.0.0/mode/commonlisp/index.html deleted file mode 100644 index f2bf452..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/commonlisp/index.html +++ /dev/null @@ -1,177 +0,0 @@ - - -CodeMirror: Common Lisp mode - - - - - - - - - -
-

Common Lisp mode

-
- - -

MIME types defined: text/x-common-lisp.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/css/index.html b/shared/html/libs/codemirror/5.0.0/mode/css/index.html deleted file mode 100644 index 2d2b9b0..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/css/index.html +++ /dev/null @@ -1,75 +0,0 @@ - - -CodeMirror: CSS mode - - - - - - - - - - - - -
-

CSS mode

-
- - -

MIME types defined: text/css, text/x-scss (demo), text/x-less (demo).

- -

Parsing/Highlighting Tests: normal, verbose.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/css/less.html b/shared/html/libs/codemirror/5.0.0/mode/css/less.html deleted file mode 100644 index 6ccb721..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/css/less.html +++ /dev/null @@ -1,152 +0,0 @@ - - -CodeMirror: LESS mode - - - - - - - - - - -
-

LESS mode

-
- - -

The LESS mode is a sub-mode of the CSS mode (defined in css.js.

- -

Parsing/Highlighting Tests: normal, verbose.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/css/less_test.js b/shared/html/libs/codemirror/5.0.0/mode/css/less_test.js deleted file mode 100644 index 2ba6998..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/css/less_test.js +++ /dev/null @@ -1,51 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - "use strict"; - - var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); } - - MT("variable", - "[variable-2 @base]: [atom #f04615];", - "[qualifier .class] {", - " [property width]: [variable percentage]([number 0.5]); [comment // returns `50%`]", - " [property color]: [variable saturate]([variable-2 @base], [number 5%]);", - "}"); - - MT("amp", - "[qualifier .child], [qualifier .sibling] {", - " [qualifier .parent] [atom &] {", - " [property color]: [keyword black];", - " }", - " [atom &] + [atom &] {", - " [property color]: [keyword red];", - " }", - "}"); - - MT("mixin", - "[qualifier .mixin] ([variable dark]; [variable-2 @color]) {", - " [property color]: [variable darken]([variable-2 @color], [number 10%]);", - "}", - "[qualifier .mixin] ([variable light]; [variable-2 @color]) {", - " [property color]: [variable lighten]([variable-2 @color], [number 10%]);", - "}", - "[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {", - " [property display]: [atom block];", - "}", - "[variable-2 @switch]: [variable light];", - "[qualifier .class] {", - " [qualifier .mixin]([variable-2 @switch]; [atom #888]);", - "}"); - - MT("nest", - "[qualifier .one] {", - " [def @media] ([property width]: [number 400px]) {", - " [property font-size]: [number 1.2em];", - " [def @media] [attribute print] [keyword and] [property color] {", - " [property color]: [keyword blue];", - " }", - " }", - "}"); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/css/scss.html b/shared/html/libs/codemirror/5.0.0/mode/css/scss.html deleted file mode 100644 index 21f20e0..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/css/scss.html +++ /dev/null @@ -1,157 +0,0 @@ - - -CodeMirror: SCSS mode - - - - - - - - - -
-

SCSS mode

-
- - -

The SCSS mode is a sub-mode of the CSS mode (defined in css.js.

- -

Parsing/Highlighting Tests: normal, verbose.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/css/scss_test.js b/shared/html/libs/codemirror/5.0.0/mode/css/scss_test.js deleted file mode 100644 index 8dcea9e..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/css/scss_test.js +++ /dev/null @@ -1,110 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } - - MT('url_with_quotation', - "[tag foo] { [property background]:[atom url]([string test.jpg]) }"); - - MT('url_with_double_quotes', - "[tag foo] { [property background]:[atom url]([string \"test.jpg\"]) }"); - - MT('url_with_single_quotes', - "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) }"); - - MT('string', - "[def @import] [string \"compass/css3\"]"); - - MT('important_keyword', - "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) [keyword !important] }"); - - MT('variable', - "[variable-2 $blue]:[atom #333]"); - - MT('variable_as_attribute', - "[tag foo] { [property color]:[variable-2 $blue] }"); - - MT('numbers', - "[tag foo] { [property padding]:[number 10px] [number 10] [number 10em] [number 8in] }"); - - MT('number_percentage', - "[tag foo] { [property width]:[number 80%] }"); - - MT('selector', - "[builtin #hello][qualifier .world]{}"); - - MT('singleline_comment', - "[comment // this is a comment]"); - - MT('multiline_comment', - "[comment /*foobar*/]"); - - MT('attribute_with_hyphen', - "[tag foo] { [property font-size]:[number 10px] }"); - - MT('string_after_attribute', - "[tag foo] { [property content]:[string \"::\"] }"); - - MT('directives', - "[def @include] [qualifier .mixin]"); - - MT('basic_structure', - "[tag p] { [property background]:[keyword red]; }"); - - MT('nested_structure', - "[tag p] { [tag a] { [property color]:[keyword red]; } }"); - - MT('mixin', - "[def @mixin] [tag table-base] {}"); - - MT('number_without_semicolon', - "[tag p] {[property width]:[number 12]}", - "[tag a] {[property color]:[keyword red];}"); - - MT('atom_in_nested_block', - "[tag p] { [tag a] { [property color]:[atom #000]; } }"); - - MT('interpolation_in_property', - "[tag foo] { #{[variable-2 $hello]}:[number 2]; }"); - - MT('interpolation_in_selector', - "[tag foo]#{[variable-2 $hello]} { [property color]:[atom #000]; }"); - - MT('interpolation_error', - "[tag foo]#{[error foo]} { [property color]:[atom #000]; }"); - - MT("divide_operator", - "[tag foo] { [property width]:[number 4] [operator /] [number 2] }"); - - MT('nested_structure_with_id_selector', - "[tag p] { [builtin #hello] { [property color]:[keyword red]; } }"); - - MT('indent_mixin', - "[def @mixin] [tag container] (", - " [variable-2 $a]: [number 10],", - " [variable-2 $b]: [number 10])", - "{}"); - - MT('indent_nested', - "[tag foo] {", - " [tag bar] {", - " }", - "}"); - - MT('indent_parentheses', - "[tag foo] {", - " [property color]: [variable darken]([variable-2 $blue],", - " [number 9%]);", - "}"); - - MT('indent_vardef', - "[variable-2 $name]:", - " [string 'val'];", - "[tag tag] {", - " [tag inner] {", - " [property margin]: [number 3px];", - " }", - "}"); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/css/test.js b/shared/html/libs/codemirror/5.0.0/mode/css/test.js deleted file mode 100644 index bef7156..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/css/test.js +++ /dev/null @@ -1,195 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "css"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - // Error, because "foobarhello" is neither a known type or property, but - // property was expected (after "and"), and it should be in parenthese. - MT("atMediaUnknownType", - "[def @media] [attribute screen] [keyword and] [error foobarhello] { }"); - - // Soft error, because "foobarhello" is not a known property or type. - MT("atMediaUnknownProperty", - "[def @media] [attribute screen] [keyword and] ([error foobarhello]) { }"); - - // Make sure nesting works with media queries - MT("atMediaMaxWidthNested", - "[def @media] [attribute screen] [keyword and] ([property max-width]: [number 25px]) { [tag foo] { } }"); - - MT("tagSelector", - "[tag foo] { }"); - - MT("classSelector", - "[qualifier .foo-bar_hello] { }"); - - MT("idSelector", - "[builtin #foo] { [error #foo] }"); - - MT("tagSelectorUnclosed", - "[tag foo] { [property margin]: [number 0] } [tag bar] { }"); - - MT("tagStringNoQuotes", - "[tag foo] { [property font-family]: [variable hello] [variable world]; }"); - - MT("tagStringDouble", - "[tag foo] { [property font-family]: [string \"hello world\"]; }"); - - MT("tagStringSingle", - "[tag foo] { [property font-family]: [string 'hello world']; }"); - - MT("tagColorKeyword", - "[tag foo] {", - " [property color]: [keyword black];", - " [property color]: [keyword navy];", - " [property color]: [keyword yellow];", - "}"); - - MT("tagColorHex3", - "[tag foo] { [property background]: [atom #fff]; }"); - - MT("tagColorHex6", - "[tag foo] { [property background]: [atom #ffffff]; }"); - - MT("tagColorHex4", - "[tag foo] { [property background]: [atom&error #ffff]; }"); - - MT("tagColorHexInvalid", - "[tag foo] { [property background]: [atom&error #ffg]; }"); - - MT("tagNegativeNumber", - "[tag foo] { [property margin]: [number -5px]; }"); - - MT("tagPositiveNumber", - "[tag foo] { [property padding]: [number 5px]; }"); - - MT("tagVendor", - "[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][atom border-box]; }"); - - MT("tagBogusProperty", - "[tag foo] { [property&error barhelloworld]: [number 0]; }"); - - MT("tagTwoProperties", - "[tag foo] { [property margin]: [number 0]; [property padding]: [number 0]; }"); - - MT("tagTwoPropertiesURL", - "[tag foo] { [property background]: [atom url]([string //example.com/foo.png]); [property padding]: [number 0]; }"); - - MT("commentSGML", - "[comment ]"); - - MT("commentSGML2", - "[comment ] [tag div] {}"); - - MT("indent_tagSelector", - "[tag strong], [tag em] {", - " [property background]: [atom rgba](", - " [number 255], [number 255], [number 0], [number .2]", - " );", - "}"); - - MT("indent_atMedia", - "[def @media] {", - " [tag foo] {", - " [property color]:", - " [keyword yellow];", - " }", - "}"); - - MT("indent_comma", - "[tag foo] {", - " [property font-family]: [variable verdana],", - " [atom sans-serif];", - "}"); - - MT("indent_parentheses", - "[tag foo]:[variable-3 before] {", - " [property background]: [atom url](", - "[string blahblah]", - "[string etc]", - "[string ]) [keyword !important];", - "}"); - - MT("font_face", - "[def @font-face] {", - " [property font-family]: [string 'myfont'];", - " [error nonsense]: [string 'abc'];", - " [property src]: [atom url]([string http://blah]),", - " [atom url]([string http://foo]);", - "}"); - - MT("empty_url", - "[def @import] [tag url]() [tag screen];"); - - MT("parens", - "[qualifier .foo] {", - " [property background-image]: [variable fade]([atom #000], [number 20%]);", - " [property border-image]: [atom linear-gradient](", - " [atom to] [atom bottom],", - " [variable fade]([atom #000], [number 20%]) [number 0%],", - " [variable fade]([atom #000], [number 20%]) [number 100%]", - " );", - "}"); - - MT("css_variable", - ":[variable-3 root] {", - " [variable-2 --main-color]: [atom #06c];", - "}", - "[tag h1][builtin #foo] {", - " [property color]: [atom var]([variable-2 --main-color]);", - "}"); - - MT("supports", - "[def @supports] ([keyword not] (([property text-align-last]: [atom justify]) [keyword or] ([meta -moz-][property text-align-last]: [atom justify])) {", - " [property text-align-last]: [atom justify];", - "}"); - - MT("document", - "[def @document] [tag url]([string http://blah]),", - " [tag url-prefix]([string https://]),", - " [tag domain]([string blah.com]),", - " [tag regexp]([string \".*blah.+\"]) {", - " [builtin #id] {", - " [property background-color]: [keyword white];", - " }", - " [tag foo] {", - " [property font-family]: [variable Verdana], [atom sans-serif];", - " }", - " }"); - - MT("document_url", - "[def @document] [tag url]([string http://blah]) { [qualifier .class] { } }"); - - MT("document_urlPrefix", - "[def @document] [tag url-prefix]([string https://]) { [builtin #id] { } }"); - - MT("document_domain", - "[def @document] [tag domain]([string blah.com]) { [tag foo] { } }"); - - MT("document_regexp", - "[def @document] [tag regexp]([string \".*blah.+\"]) { [builtin #id] { } }"); - - MT("counter-style", - "[def @counter-style] [variable binary] {", - " [property system]: [atom numeric];", - " [property symbols]: [number 0] [number 1];", - " [property suffix]: [string \".\"];", - " [property range]: [atom infinite];", - " [property speak-as]: [atom numeric];", - "}"); - - MT("counter-style-additive-symbols", - "[def @counter-style] [variable simple-roman] {", - " [property system]: [atom additive];", - " [property additive-symbols]: [number 10] [variable X], [number 5] [variable V], [number 1] [variable I];", - " [property range]: [number 1] [number 49];", - "}"); - - MT("counter-style-use", - "[tag ol][qualifier .roman] { [property list-style]: [variable simple-roman]; }"); - - MT("counter-style-symbols", - "[tag ol] { [property list-style]: [atom symbols]([atom cyclic] [string \"*\"] [string \"\\2020\"] [string \"\\2021\"] [string \"\\A7\"]); }"); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/cypher/cypher.js b/shared/html/libs/codemirror/5.0.0/mode/cypher/cypher.js deleted file mode 100644 index 9decf30..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/cypher/cypher.js +++ /dev/null @@ -1,146 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// By the Neo4j Team and contributors. -// https://github.com/neo4j-contrib/CodeMirror - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - var wordRegexp = function(words) { - return new RegExp("^(?:" + words.join("|") + ")$", "i"); - }; - - CodeMirror.defineMode("cypher", function(config) { - var tokenBase = function(stream/*, state*/) { - var ch = stream.next(), curPunc = null; - if (ch === "\"" || ch === "'") { - stream.match(/.+?["']/); - return "string"; - } - if (/[{}\(\),\.;\[\]]/.test(ch)) { - curPunc = ch; - return "node"; - } else if (ch === "/" && stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } else if (operatorChars.test(ch)) { - stream.eatWhile(operatorChars); - return null; - } else { - stream.eatWhile(/[_\w\d]/); - if (stream.eat(":")) { - stream.eatWhile(/[\w\d_\-]/); - return "atom"; - } - var word = stream.current(); - if (funcs.test(word)) return "builtin"; - if (preds.test(word)) return "def"; - if (keywords.test(word)) return "keyword"; - return "variable"; - } - }; - var pushContext = function(state, type, col) { - return state.context = { - prev: state.context, - indent: state.indent, - col: col, - type: type - }; - }; - var popContext = function(state) { - state.indent = state.context.indent; - return state.context = state.context.prev; - }; - var indentUnit = config.indentUnit; - var curPunc; - var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "right", "round", "rtrim", "shortestPath", "sign", "sin", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "trim", "type", "upper"]); - var preds = wordRegexp(["all", "and", "any", "has", "in", "none", "not", "or", "single", "xor"]); - var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]); - var operatorChars = /[*+\-<>=&|~%^]/; - - return { - startState: function(/*base*/) { - return { - tokenize: tokenBase, - context: null, - indent: 0, - col: 0 - }; - }, - token: function(stream, state) { - if (stream.sol()) { - if (state.context && (state.context.align == null)) { - state.context.align = false; - } - state.indent = stream.indentation(); - } - if (stream.eatSpace()) { - return null; - } - var style = state.tokenize(stream, state); - if (style !== "comment" && state.context && (state.context.align == null) && state.context.type !== "pattern") { - state.context.align = true; - } - if (curPunc === "(") { - pushContext(state, ")", stream.column()); - } else if (curPunc === "[") { - pushContext(state, "]", stream.column()); - } else if (curPunc === "{") { - pushContext(state, "}", stream.column()); - } else if (/[\]\}\)]/.test(curPunc)) { - while (state.context && state.context.type === "pattern") { - popContext(state); - } - if (state.context && curPunc === state.context.type) { - popContext(state); - } - } else if (curPunc === "." && state.context && state.context.type === "pattern") { - popContext(state); - } else if (/atom|string|variable/.test(style) && state.context) { - if (/[\}\]]/.test(state.context.type)) { - pushContext(state, "pattern", stream.column()); - } else if (state.context.type === "pattern" && !state.context.align) { - state.context.align = true; - state.context.col = stream.column(); - } - } - return style; - }, - indent: function(state, textAfter) { - var firstChar = textAfter && textAfter.charAt(0); - var context = state.context; - if (/[\]\}]/.test(firstChar)) { - while (context && context.type === "pattern") { - context = context.prev; - } - } - var closing = context && firstChar === context.type; - if (!context) return 0; - if (context.type === "keywords") return CodeMirror.commands.newlineAndIndent; - if (context.align) return context.col + (closing ? 0 : 1); - return context.indent + (closing ? 0 : indentUnit); - } - }; - }); - - CodeMirror.modeExtensions["cypher"] = { - autoFormatLineBreaks: function(text) { - var i, lines, reProcessedPortion; - var lines = text.split("\n"); - var reProcessedPortion = /\s+\b(return|where|order by|match|with|skip|limit|create|delete|set)\b\s/g; - for (var i = 0; i < lines.length; i++) - lines[i] = lines[i].replace(reProcessedPortion, " \n$1 ").trim(); - return lines.join("\n"); - } - }; - - CodeMirror.defineMIME("application/x-cypher-query", "cypher"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/cypher/index.html b/shared/html/libs/codemirror/5.0.0/mode/cypher/index.html deleted file mode 100644 index b8bd75c..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/cypher/index.html +++ /dev/null @@ -1,63 +0,0 @@ - - -CodeMirror: Cypher Mode for CodeMirror - - - - - - - - - - -
-

Cypher Mode for CodeMirror

-
- -
-

MIME types defined: - application/x-cypher-query -

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/d/d.js b/shared/html/libs/codemirror/5.0.0/mode/d/d.js deleted file mode 100644 index c927a7e..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/d/d.js +++ /dev/null @@ -1,218 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("d", function(config, parserConfig) { - var indentUnit = config.indentUnit, - statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, - keywords = parserConfig.keywords || {}, - builtin = parserConfig.builtin || {}, - blockKeywords = parserConfig.blockKeywords || {}, - atoms = parserConfig.atoms || {}, - hooks = parserConfig.hooks || {}, - multiLineStrings = parserConfig.multiLineStrings; - var isOperatorChar = /[+\-*&%=<>!?|\/]/; - - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (hooks[ch]) { - var result = hooks[ch](stream, state); - if (result !== false) return result; - } - if (ch == '"' || ch == "'" || ch == "`") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (ch == "/") { - if (stream.eat("+")) { - state.tokenize = tokenComment; - return tokenNestedComment(stream, state); - } - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; - } - if (builtin.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "builtin"; - } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = null; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function tokenNestedComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch == "+"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - var indent = state.indented; - if (state.context && state.context.type == "statement") - indent = state.context.indented; - return state.context = new Context(indent, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state); - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement")) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass; - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; - var closing = firstChar == ctx.type; - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "{}" - }; -}); - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var blockKeywords = "body catch class do else enum for foreach foreach_reverse if in interface mixin " + - "out scope struct switch try union unittest version while with"; - - CodeMirror.defineMIME("text/x-d", { - name: "d", - keywords: words("abstract alias align asm assert auto break case cast cdouble cent cfloat const continue " + - "debug default delegate delete deprecated export extern final finally function goto immutable " + - "import inout invariant is lazy macro module new nothrow override package pragma private " + - "protected public pure ref return shared short static super synchronized template this " + - "throw typedef typeid typeof volatile __FILE__ __LINE__ __gshared __traits __vector __parameters " + - blockKeywords), - blockKeywords: words(blockKeywords), - builtin: words("bool byte char creal dchar double float idouble ifloat int ireal long real short ubyte " + - "ucent uint ulong ushort wchar wstring void size_t sizediff_t"), - atoms: words("exit failure success true false null"), - hooks: { - "@": function(stream, _state) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - } - }); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/d/index.html b/shared/html/libs/codemirror/5.0.0/mode/d/index.html deleted file mode 100644 index 08cabd8..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/d/index.html +++ /dev/null @@ -1,273 +0,0 @@ - - -CodeMirror: D mode - - - - - - - - - - -
-

D mode

-
- - - -

Simple mode that handle D-Syntax (DLang Homepage).

- -

MIME types defined: text/x-d - .

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/dart/dart.js b/shared/html/libs/codemirror/5.0.0/mode/dart/dart.js deleted file mode 100644 index a49e218..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/dart/dart.js +++ /dev/null @@ -1,50 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../clike/clike")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../clike/clike"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var keywords = ("this super static final const abstract class extends external factory " + - "implements get native operator set typedef with enum throw rethrow " + - "assert break case continue default in return new deferred async await " + - "try catch finally do else for if switch while import library export " + - "part of show hide is").split(" "); - var blockKeywords = "try catch finally do else for if switch while".split(" "); - var atoms = "true false null".split(" "); - var builtins = "void bool num int double dynamic var String".split(" "); - - function set(words) { - var obj = {}; - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - CodeMirror.defineMIME("application/dart", { - name: "clike", - keywords: set(keywords), - multiLineStrings: true, - blockKeywords: set(blockKeywords), - builtin: set(builtins), - atoms: set(atoms), - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - } - }); - - CodeMirror.registerHelper("hintWords", "application/dart", keywords.concat(atoms).concat(builtins)); - - // This is needed to make loading through meta.js work. - CodeMirror.defineMode("dart", function(conf) { - return CodeMirror.getMode(conf, "application/dart"); - }, "clike"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/dart/index.html b/shared/html/libs/codemirror/5.0.0/mode/dart/index.html deleted file mode 100644 index e79da5a..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/dart/index.html +++ /dev/null @@ -1,71 +0,0 @@ - - -CodeMirror: Dart mode - - - - - - - - - -
-

Dart mode

-
- -
- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/diff/diff.js b/shared/html/libs/codemirror/5.0.0/mode/diff/diff.js deleted file mode 100644 index fe0305e..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/diff/diff.js +++ /dev/null @@ -1,47 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("diff", function() { - - var TOKEN_NAMES = { - '+': 'positive', - '-': 'negative', - '@': 'meta' - }; - - return { - token: function(stream) { - var tw_pos = stream.string.search(/[\t ]+?$/); - - if (!stream.sol() || tw_pos === 0) { - stream.skipToEnd(); - return ("error " + ( - TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, ''); - } - - var token_name = TOKEN_NAMES[stream.peek()] || stream.skipToEnd(); - - if (tw_pos === -1) { - stream.skipToEnd(); - } else { - stream.pos = tw_pos; - } - - return token_name; - } - }; -}); - -CodeMirror.defineMIME("text/x-diff", "diff"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/diff/index.html b/shared/html/libs/codemirror/5.0.0/mode/diff/index.html deleted file mode 100644 index 0af611f..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/diff/index.html +++ /dev/null @@ -1,117 +0,0 @@ - - -CodeMirror: Diff mode - - - - - - - - - -
-

Diff mode

-
- - -

MIME types defined: text/x-diff.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/django/django.js b/shared/html/libs/codemirror/5.0.0/mode/django/django.js deleted file mode 100644 index d70b2fe..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/django/django.js +++ /dev/null @@ -1,67 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), - require("../../addon/mode/overlay")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", - "../../addon/mode/overlay"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("django:inner", function() { - var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false", - "loop", "none", "self", "super", "if", "endif", "as", "not", "and", - "else", "import", "with", "endwith", "without", "context", "ifequal", "endifequal", - "ifnotequal", "endifnotequal", "extends", "include", "load", "length", "comment", - "endcomment", "empty"]; - keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b"); - - function tokenBase (stream, state) { - stream.eatWhile(/[^\{]/); - var ch = stream.next(); - if (ch == "{") { - if (ch = stream.eat(/\{|%|#/)) { - state.tokenize = inTag(ch); - return "tag"; - } - } - } - function inTag (close) { - if (close == "{") { - close = "}"; - } - return function (stream, state) { - var ch = stream.next(); - if ((ch == close) && stream.eat("}")) { - state.tokenize = tokenBase; - return "tag"; - } - if (stream.match(keywords)) { - return "keyword"; - } - return close == "#" ? "comment" : "string"; - }; - } - return { - startState: function () { - return {tokenize: tokenBase}; - }, - token: function (stream, state) { - return state.tokenize(stream, state); - } - }; - }); - - CodeMirror.defineMode("django", function(config) { - var htmlBase = CodeMirror.getMode(config, "text/html"); - var djangoInner = CodeMirror.getMode(config, "django:inner"); - return CodeMirror.overlayMode(htmlBase, djangoInner); - }); - - CodeMirror.defineMIME("text/x-django", "django"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/django/index.html b/shared/html/libs/codemirror/5.0.0/mode/django/index.html deleted file mode 100644 index 79d9a6a..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/django/index.html +++ /dev/null @@ -1,63 +0,0 @@ - - -CodeMirror: Django template mode - - - - - - - - - - - - -
-

Django template mode

-
- - - -

Mode for HTML with embedded Django template markup.

- -

MIME types defined: text/x-django

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/dockerfile/dockerfile.js b/shared/html/libs/codemirror/5.0.0/mode/dockerfile/dockerfile.js deleted file mode 100644 index 6d51775..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/dockerfile/dockerfile.js +++ /dev/null @@ -1,76 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../../addon/mode/simple")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../../addon/mode/simple"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - // Collect all Dockerfile directives - var instructions = ["from", "maintainer", "run", "cmd", "expose", "env", - "add", "copy", "entrypoint", "volume", "user", - "workdir", "onbuild"], - instructionRegex = "(" + instructions.join('|') + ")", - instructionOnlyLine = new RegExp(instructionRegex + "\\s*$", "i"), - instructionWithArguments = new RegExp(instructionRegex + "(\\s+)", "i"); - - CodeMirror.defineSimpleMode("dockerfile", { - start: [ - // Block comment: This is a line starting with a comment - { - regex: /#.*$/, - token: "comment" - }, - // Highlight an instruction without any arguments (for convenience) - { - regex: instructionOnlyLine, - token: "variable-2" - }, - // Highlight an instruction followed by arguments - { - regex: instructionWithArguments, - token: ["variable-2", null], - next: "arguments" - }, - { - regex: /./, - token: null - } - ], - arguments: [ - { - // Line comment without instruction arguments is an error - regex: /#.*$/, - token: "error", - next: "start" - }, - { - regex: /[^#]+\\$/, - token: null - }, - { - // Match everything except for the inline comment - regex: /[^#]+/, - token: null, - next: "start" - }, - { - regex: /$/, - token: null, - next: "start" - }, - // Fail safe return to start - { - token: null, - next: "start" - } - ] - }); - - CodeMirror.defineMIME("text/x-dockerfile", "dockerfile"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/dockerfile/index.html b/shared/html/libs/codemirror/5.0.0/mode/dockerfile/index.html deleted file mode 100644 index a31759b..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/dockerfile/index.html +++ /dev/null @@ -1,73 +0,0 @@ - - -CodeMirror: Dockerfile mode - - - - - - - - - - -
-

Dockerfile mode

-
- - - -

Dockerfile syntax highlighting for CodeMirror. Depends on - the simplemode addon.

- -

MIME types defined: text/x-dockerfile

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/dtd/dtd.js b/shared/html/libs/codemirror/5.0.0/mode/dtd/dtd.js deleted file mode 100644 index f37029a..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/dtd/dtd.js +++ /dev/null @@ -1,142 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* - DTD mode - Ported to CodeMirror by Peter Kroon - Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues - GitHub: @peterkroon -*/ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("dtd", function(config) { - var indentUnit = config.indentUnit, type; - function ret(style, tp) {type = tp; return style;} - - function tokenBase(stream, state) { - var ch = stream.next(); - - if (ch == "<" && stream.eat("!") ) { - if (stream.eatWhile(/[\-]/)) { - state.tokenize = tokenSGMLComment; - return tokenSGMLComment(stream, state); - } else if (stream.eatWhile(/[\w]/)) return ret("keyword", "doindent"); - } else if (ch == "<" && stream.eat("?")) { //xml declaration - state.tokenize = inBlock("meta", "?>"); - return ret("meta", ch); - } else if (ch == "#" && stream.eatWhile(/[\w]/)) return ret("atom", "tag"); - else if (ch == "|") return ret("keyword", "seperator"); - else if (ch.match(/[\(\)\[\]\-\.,\+\?>]/)) return ret(null, ch);//if(ch === ">") return ret(null, "endtag"); else - else if (ch.match(/[\[\]]/)) return ret("rule", ch); - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } else if (stream.eatWhile(/[a-zA-Z\?\+\d]/)) { - var sc = stream.current(); - if( sc.substr(sc.length-1,sc.length).match(/\?|\+/) !== null )stream.backUp(1); - return ret("tag", "tag"); - } else if (ch == "%" || ch == "*" ) return ret("number", "number"); - else { - stream.eatWhile(/[\w\\\-_%.{,]/); - return ret(null, null); - } - } - - function tokenSGMLComment(stream, state) { - var dashes = 0, ch; - while ((ch = stream.next()) != null) { - if (dashes >= 2 && ch == ">") { - state.tokenize = tokenBase; - break; - } - dashes = (ch == "-") ? dashes + 1 : 0; - } - return ret("comment", "comment"); - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && ch == "\\"; - } - return ret("string", "tag"); - }; - } - - function inBlock(style, terminator) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.match(terminator)) { - state.tokenize = tokenBase; - break; - } - stream.next(); - } - return style; - }; - } - - return { - startState: function(base) { - return {tokenize: tokenBase, - baseIndent: base || 0, - stack: []}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - - var context = state.stack[state.stack.length-1]; - if (stream.current() == "[" || type === "doindent" || type == "[") state.stack.push("rule"); - else if (type === "endtag") state.stack[state.stack.length-1] = "endtag"; - else if (stream.current() == "]" || type == "]" || (type == ">" && context == "rule")) state.stack.pop(); - else if (type == "[") state.stack.push("["); - return style; - }, - - indent: function(state, textAfter) { - var n = state.stack.length; - - if( textAfter.match(/\]\s+|\]/) )n=n-1; - else if(textAfter.substr(textAfter.length-1, textAfter.length) === ">"){ - if(textAfter.substr(0,1) === "<")n; - else if( type == "doindent" && textAfter.length > 1 )n; - else if( type == "doindent")n--; - else if( type == ">" && textAfter.length > 1)n; - else if( type == "tag" && textAfter !== ">")n; - else if( type == "tag" && state.stack[state.stack.length-1] == "rule")n--; - else if( type == "tag")n++; - else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule" && type === ">")n--; - else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule")n; - else if( textAfter.substr(0,1) !== "<" && textAfter.substr(0,1) === ">" )n=n-1; - else if( textAfter === ">")n; - else n=n-1; - //over rule them all - if(type == null || type == "]")n--; - } - - return state.baseIndent + n * indentUnit; - }, - - electricChars: "]>" - }; -}); - -CodeMirror.defineMIME("application/xml-dtd", "dtd"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/dtd/index.html b/shared/html/libs/codemirror/5.0.0/mode/dtd/index.html deleted file mode 100644 index e6798a7..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/dtd/index.html +++ /dev/null @@ -1,89 +0,0 @@ - - -CodeMirror: DTD mode - - - - - - - - - -
-

DTD mode

-
- - -

MIME types defined: application/xml-dtd.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/dylan/dylan.js b/shared/html/libs/codemirror/5.0.0/mode/dylan/dylan.js deleted file mode 100644 index be2986a..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/dylan/dylan.js +++ /dev/null @@ -1,299 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("dylan", function(_config) { - // Words - var words = { - // Words that introduce unnamed definitions like "define interface" - unnamedDefinition: ["interface"], - - // Words that introduce simple named definitions like "define library" - namedDefinition: ["module", "library", "macro", - "C-struct", "C-union", - "C-function", "C-callable-wrapper" - ], - - // Words that introduce type definitions like "define class". - // These are also parameterized like "define method" and are - // appended to otherParameterizedDefinitionWords - typeParameterizedDefinition: ["class", "C-subtype", "C-mapped-subtype"], - - // Words that introduce trickier definitions like "define method". - // These require special definitions to be added to startExpressions - otherParameterizedDefinition: ["method", "function", - "C-variable", "C-address" - ], - - // Words that introduce module constant definitions. - // These must also be simple definitions and are - // appended to otherSimpleDefinitionWords - constantSimpleDefinition: ["constant"], - - // Words that introduce module variable definitions. - // These must also be simple definitions and are - // appended to otherSimpleDefinitionWords - variableSimpleDefinition: ["variable"], - - // Other words that introduce simple definitions - // (without implicit bodies). - otherSimpleDefinition: ["generic", "domain", - "C-pointer-type", - "table" - ], - - // Words that begin statements with implicit bodies. - statement: ["if", "block", "begin", "method", "case", - "for", "select", "when", "unless", "until", - "while", "iterate", "profiling", "dynamic-bind" - ], - - // Patterns that act as separators in compound statements. - // This may include any general pattern that must be indented - // specially. - separator: ["finally", "exception", "cleanup", "else", - "elseif", "afterwards" - ], - - // Keywords that do not require special indentation handling, - // but which should be highlighted - other: ["above", "below", "by", "from", "handler", "in", - "instance", "let", "local", "otherwise", "slot", - "subclass", "then", "to", "keyed-by", "virtual" - ], - - // Condition signaling function calls - signalingCalls: ["signal", "error", "cerror", - "break", "check-type", "abort" - ] - }; - - words["otherDefinition"] = - words["unnamedDefinition"] - .concat(words["namedDefinition"]) - .concat(words["otherParameterizedDefinition"]); - - words["definition"] = - words["typeParameterizedDefinition"] - .concat(words["otherDefinition"]); - - words["parameterizedDefinition"] = - words["typeParameterizedDefinition"] - .concat(words["otherParameterizedDefinition"]); - - words["simpleDefinition"] = - words["constantSimpleDefinition"] - .concat(words["variableSimpleDefinition"]) - .concat(words["otherSimpleDefinition"]); - - words["keyword"] = - words["statement"] - .concat(words["separator"]) - .concat(words["other"]); - - // Patterns - var symbolPattern = "[-_a-zA-Z?!*@<>$%]+"; - var symbol = new RegExp("^" + symbolPattern); - var patterns = { - // Symbols with special syntax - symbolKeyword: symbolPattern + ":", - symbolClass: "<" + symbolPattern + ">", - symbolGlobal: "\\*" + symbolPattern + "\\*", - symbolConstant: "\\$" + symbolPattern - }; - var patternStyles = { - symbolKeyword: "atom", - symbolClass: "tag", - symbolGlobal: "variable-2", - symbolConstant: "variable-3" - }; - - // Compile all patterns to regular expressions - for (var patternName in patterns) - if (patterns.hasOwnProperty(patternName)) - patterns[patternName] = new RegExp("^" + patterns[patternName]); - - // Names beginning "with-" and "without-" are commonly - // used as statement macro - patterns["keyword"] = [/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/]; - - var styles = {}; - styles["keyword"] = "keyword"; - styles["definition"] = "def"; - styles["simpleDefinition"] = "def"; - styles["signalingCalls"] = "builtin"; - - // protected words lookup table - var wordLookup = {}; - var styleLookup = {}; - - [ - "keyword", - "definition", - "simpleDefinition", - "signalingCalls" - ].forEach(function(type) { - words[type].forEach(function(word) { - wordLookup[word] = type; - styleLookup[word] = styles[type]; - }); - }); - - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - var type, content; - - function ret(_type, style, _content) { - type = _type; - content = _content; - return style; - } - - function tokenBase(stream, state) { - // String - var ch = stream.peek(); - if (ch == "'" || ch == '"') { - stream.next(); - return chain(stream, state, tokenString(ch, "string", "string")); - } - // Comment - else if (ch == "/") { - stream.next(); - if (stream.eat("*")) { - return chain(stream, state, tokenComment); - } else if (stream.eat("/")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } else { - stream.skipTo(" "); - return ret("operator", "operator"); - } - } - // Decimal - else if (/\d/.test(ch)) { - stream.match(/^\d*(?:\.\d*)?(?:e[+\-]?\d+)?/); - return ret("number", "number"); - } - // Hash - else if (ch == "#") { - stream.next(); - // Symbol with string syntax - ch = stream.peek(); - if (ch == '"') { - stream.next(); - return chain(stream, state, tokenString('"', "symbol", "string-2")); - } - // Binary number - else if (ch == "b") { - stream.next(); - stream.eatWhile(/[01]/); - return ret("number", "number"); - } - // Hex number - else if (ch == "x") { - stream.next(); - stream.eatWhile(/[\da-f]/i); - return ret("number", "number"); - } - // Octal number - else if (ch == "o") { - stream.next(); - stream.eatWhile(/[0-7]/); - return ret("number", "number"); - } - // Hash symbol - else { - stream.eatWhile(/[-a-zA-Z]/); - return ret("hash", "keyword"); - } - } else if (stream.match("end")) { - return ret("end", "keyword"); - } - for (var name in patterns) { - if (patterns.hasOwnProperty(name)) { - var pattern = patterns[name]; - if ((pattern instanceof Array && pattern.some(function(p) { - return stream.match(p); - })) || stream.match(pattern)) - return ret(name, patternStyles[name], stream.current()); - } - } - if (stream.match("define")) { - return ret("definition", "def"); - } else { - stream.eatWhile(/[\w\-]/); - // Keyword - if (wordLookup[stream.current()]) { - return ret(wordLookup[stream.current()], styleLookup[stream.current()], stream.current()); - } else if (stream.current().match(symbol)) { - return ret("variable", "variable"); - } else { - stream.next(); - return ret("other", "variable-2"); - } - } - } - - function tokenComment(stream, state) { - var maybeEnd = false, - ch; - while ((ch = stream.next())) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - function tokenString(quote, type, style) { - return function(stream, state) { - var next, end = false; - while ((next = stream.next()) != null) { - if (next == quote) { - end = true; - break; - } - } - if (end) - state.tokenize = tokenBase; - return ret(type, style); - }; - } - - // Interface - return { - startState: function() { - return { - tokenize: tokenBase, - currentIndent: 0 - }; - }, - token: function(stream, state) { - if (stream.eatSpace()) - return null; - var style = state.tokenize(stream, state); - return style; - }, - blockCommentStart: "/*", - blockCommentEnd: "*/" - }; -}); - -CodeMirror.defineMIME("text/x-dylan", "dylan"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/dylan/index.html b/shared/html/libs/codemirror/5.0.0/mode/dylan/index.html deleted file mode 100644 index ddf5ad0..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/dylan/index.html +++ /dev/null @@ -1,407 +0,0 @@ - - -CodeMirror: Dylan mode - - - - - - - - - - - - -
-

Dylan mode

- - -
- - - -

MIME types defined: text/x-dylan.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/ebnf/ebnf.js b/shared/html/libs/codemirror/5.0.0/mode/ebnf/ebnf.js deleted file mode 100644 index 6b51aba..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/ebnf/ebnf.js +++ /dev/null @@ -1,195 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("ebnf", function (config) { - var commentType = {slash: 0, parenthesis: 1}; - var stateType = {comment: 0, _string: 1, characterClass: 2}; - var bracesMode = null; - - if (config.bracesMode) - bracesMode = CodeMirror.getMode(config, config.bracesMode); - - return { - startState: function () { - return { - stringType: null, - commentType: null, - braced: 0, - lhs: true, - localState: null, - stack: [], - inDefinition: false - }; - }, - token: function (stream, state) { - if (!stream) return; - - //check for state changes - if (state.stack.length === 0) { - //strings - if ((stream.peek() == '"') || (stream.peek() == "'")) { - state.stringType = stream.peek(); - stream.next(); // Skip quote - state.stack.unshift(stateType._string); - } else if (stream.match(/^\/\*/)) { //comments starting with /* - state.stack.unshift(stateType.comment); - state.commentType = commentType.slash; - } else if (stream.match(/^\(\*/)) { //comments starting with (* - state.stack.unshift(stateType.comment); - state.commentType = commentType.parenthesis; - } - } - - //return state - //stack has - switch (state.stack[0]) { - case stateType._string: - while (state.stack[0] === stateType._string && !stream.eol()) { - if (stream.peek() === state.stringType) { - stream.next(); // Skip quote - state.stack.shift(); // Clear flag - } else if (stream.peek() === "\\") { - stream.next(); - stream.next(); - } else { - stream.match(/^.[^\\\"\']*/); - } - } - return state.lhs ? "property string" : "string"; // Token style - - case stateType.comment: - while (state.stack[0] === stateType.comment && !stream.eol()) { - if (state.commentType === commentType.slash && stream.match(/\*\//)) { - state.stack.shift(); // Clear flag - state.commentType = null; - } else if (state.commentType === commentType.parenthesis && stream.match(/\*\)/)) { - state.stack.shift(); // Clear flag - state.commentType = null; - } else { - stream.match(/^.[^\*]*/); - } - } - return "comment"; - - case stateType.characterClass: - while (state.stack[0] === stateType.characterClass && !stream.eol()) { - if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) { - state.stack.shift(); - } - } - return "operator"; - } - - var peek = stream.peek(); - - if (bracesMode !== null && (state.braced || peek === "{")) { - if (state.localState === null) - state.localState = bracesMode.startState(); - - var token = bracesMode.token(stream, state.localState), - text = stream.current(); - - if (!token) { - for (var i = 0; i < text.length; i++) { - if (text[i] === "{") { - if (state.braced === 0) { - token = "matchingbracket"; - } - state.braced++; - } else if (text[i] === "}") { - state.braced--; - if (state.braced === 0) { - token = "matchingbracket"; - } - } - } - } - return token; - } - - //no stack - switch (peek) { - case "[": - stream.next(); - state.stack.unshift(stateType.characterClass); - return "bracket"; - case ":": - case "|": - case ";": - stream.next(); - return "operator"; - case "%": - if (stream.match("%%")) { - return "header"; - } else if (stream.match(/[%][A-Za-z]+/)) { - return "keyword"; - } else if (stream.match(/[%][}]/)) { - return "matchingbracket"; - } - break; - case "/": - if (stream.match(/[\/][A-Za-z]+/)) { - return "keyword"; - } - case "\\": - if (stream.match(/[\][a-z]+/)) { - return "string-2"; - } - case ".": - if (stream.match(".")) { - return "atom"; - } - case "*": - case "-": - case "+": - case "^": - if (stream.match(peek)) { - return "atom"; - } - case "$": - if (stream.match("$$")) { - return "builtin"; - } else if (stream.match(/[$][0-9]+/)) { - return "variable-3"; - } - case "<": - if (stream.match(/<<[a-zA-Z_]+>>/)) { - return "builtin"; - } - } - - if (stream.match(/^\/\//)) { - stream.skipToEnd(); - return "comment"; - } else if (stream.match(/return/)) { - return "operator"; - } else if (stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)) { - if (stream.match(/(?=[\(.])/)) { - return "variable"; - } else if (stream.match(/(?=[\s\n]*[:=])/)) { - return "def"; - } - return "variable-2"; - } else if (["[", "]", "(", ")"].indexOf(stream.peek()) != -1) { - stream.next(); - return "bracket"; - } else if (!stream.eatSpace()) { - stream.next(); - } - return null; - } - }; - }); - - CodeMirror.defineMIME("text/x-ebnf", "ebnf"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/ebnf/index.html b/shared/html/libs/codemirror/5.0.0/mode/ebnf/index.html deleted file mode 100644 index 1384562..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/ebnf/index.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - CodeMirror: EBNF Mode - - - - - - - - - - - - -
-

EBNF Mode (bracesMode setting = "javascript")

-
- -

The EBNF Mode

-

Created by Robert Plummer

-
- - diff --git a/shared/html/libs/codemirror/5.0.0/mode/ecl/ecl.js b/shared/html/libs/codemirror/5.0.0/mode/ecl/ecl.js deleted file mode 100644 index 18778f1..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/ecl/ecl.js +++ /dev/null @@ -1,207 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("ecl", function(config) { - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - function metaHook(stream, state) { - if (!state.startOfLine) return false; - stream.skipToEnd(); - return "meta"; - } - - var indentUnit = config.indentUnit; - var keyword = words("abs acos allnodes ascii asin asstring atan atan2 ave case choose choosen choosesets clustersize combine correlation cos cosh count covariance cron dataset dedup define denormalize distribute distributed distribution ebcdic enth error evaluate event eventextra eventname exists exp failcode failmessage fetch fromunicode getisvalid global graph group hash hash32 hash64 hashcrc hashmd5 having if index intformat isvalid iterate join keyunicode length library limit ln local log loop map matched matchlength matchposition matchtext matchunicode max merge mergejoin min nolocal nonempty normalize parse pipe power preload process project pull random range rank ranked realformat recordof regexfind regexreplace regroup rejected rollup round roundup row rowdiff sample set sin sinh sizeof soapcall sort sorted sqrt stepped stored sum table tan tanh thisnode topn tounicode transfer trim truncate typeof ungroup unicodeorder variance which workunit xmldecode xmlencode xmltext xmlunicode"); - var variable = words("apply assert build buildindex evaluate fail keydiff keypatch loadxml nothor notify output parallel sequential soapcall wait"); - var variable_2 = words("__compressed__ all and any as atmost before beginc++ best between case const counter csv descend encrypt end endc++ endmacro except exclusive expire export extend false few first flat from full function group header heading hole ifblock import in interface joined keep keyed last left limit load local locale lookup macro many maxcount maxlength min skew module named nocase noroot noscan nosort not of only opt or outer overwrite packed partition penalty physicallength pipe quote record relationship repeat return right scan self separator service shared skew skip sql store terminator thor threshold token transform trim true type unicodeorder unsorted validate virtual whole wild within xml xpath"); - var variable_3 = words("ascii big_endian boolean data decimal ebcdic integer pattern qstring real record rule set of string token udecimal unicode unsigned varstring varunicode"); - var builtin = words("checkpoint deprecated failcode failmessage failure global independent onwarning persist priority recovery stored success wait when"); - var blockKeywords = words("catch class do else finally for if switch try while"); - var atoms = words("true false null"); - var hooks = {"#": metaHook}; - var multiLineStrings; - var isOperatorChar = /[+\-*&%=<>!?|\/]/; - - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (hooks[ch]) { - var result = hooks[ch](stream, state); - if (result !== false) return result; - } - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - var cur = stream.current().toLowerCase(); - if (keyword.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; - } else if (variable.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "variable"; - } else if (variable_2.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "variable-2"; - } else if (variable_3.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "variable-3"; - } else if (builtin.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "builtin"; - } else { //Data types are of from KEYWORD## - var i = cur.length - 1; - while(i >= 0 && (!isNaN(cur[i]) || cur[i] == '_')) - --i; - - if (i > 0) { - var cur2 = cur.substr(0, i + 1); - if (variable_3.propertyIsEnumerable(cur2)) { - if (blockKeywords.propertyIsEnumerable(cur2)) curPunc = "newstatement"; - return "variable-3"; - } - } - } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return null; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state); - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return 0; - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; - var closing = firstChar == ctx.type; - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "{}" - }; -}); - -CodeMirror.defineMIME("text/x-ecl", "ecl"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/ecl/index.html b/shared/html/libs/codemirror/5.0.0/mode/ecl/index.html deleted file mode 100644 index 2306860..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/ecl/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - -CodeMirror: ECL mode - - - - - - - - - -
-

ECL mode

-
- - -

Based on CodeMirror's clike mode. For more information see HPCC Systems web site.

-

MIME types defined: text/x-ecl.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/eiffel/eiffel.js b/shared/html/libs/codemirror/5.0.0/mode/eiffel/eiffel.js deleted file mode 100644 index fcdf295..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/eiffel/eiffel.js +++ /dev/null @@ -1,162 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("eiffel", function() { - function wordObj(words) { - var o = {}; - for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true; - return o; - } - var keywords = wordObj([ - 'note', - 'across', - 'when', - 'variant', - 'until', - 'unique', - 'undefine', - 'then', - 'strip', - 'select', - 'retry', - 'rescue', - 'require', - 'rename', - 'reference', - 'redefine', - 'prefix', - 'once', - 'old', - 'obsolete', - 'loop', - 'local', - 'like', - 'is', - 'inspect', - 'infix', - 'include', - 'if', - 'frozen', - 'from', - 'external', - 'export', - 'ensure', - 'end', - 'elseif', - 'else', - 'do', - 'creation', - 'create', - 'check', - 'alias', - 'agent', - 'separate', - 'invariant', - 'inherit', - 'indexing', - 'feature', - 'expanded', - 'deferred', - 'class', - 'Void', - 'True', - 'Result', - 'Precursor', - 'False', - 'Current', - 'create', - 'attached', - 'detachable', - 'as', - 'and', - 'implies', - 'not', - 'or' - ]); - var operators = wordObj([":=", "and then","and", "or","<<",">>"]); - var curPunc; - - function chain(newtok, stream, state) { - state.tokenize.push(newtok); - return newtok(stream, state); - } - - function tokenBase(stream, state) { - curPunc = null; - if (stream.eatSpace()) return null; - var ch = stream.next(); - if (ch == '"'||ch == "'") { - return chain(readQuoted(ch, "string"), stream, state); - } else if (ch == "-"&&stream.eat("-")) { - stream.skipToEnd(); - return "comment"; - } else if (ch == ":"&&stream.eat("=")) { - return "operator"; - } else if (/[0-9]/.test(ch)) { - stream.eatWhile(/[xXbBCc0-9\.]/); - stream.eat(/[\?\!]/); - return "ident"; - } else if (/[a-zA-Z_0-9]/.test(ch)) { - stream.eatWhile(/[a-zA-Z_0-9]/); - stream.eat(/[\?\!]/); - return "ident"; - } else if (/[=+\-\/*^%<>~]/.test(ch)) { - stream.eatWhile(/[=+\-\/*^%<>~]/); - return "operator"; - } else { - return null; - } - } - - function readQuoted(quote, style, unescaped) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && (unescaped || !escaped)) { - state.tokenize.pop(); - break; - } - escaped = !escaped && ch == "%"; - } - return style; - }; - } - - return { - startState: function() { - return {tokenize: [tokenBase]}; - }, - - token: function(stream, state) { - var style = state.tokenize[state.tokenize.length-1](stream, state); - if (style == "ident") { - var word = stream.current(); - style = keywords.propertyIsEnumerable(stream.current()) ? "keyword" - : operators.propertyIsEnumerable(stream.current()) ? "operator" - : /^[A-Z][A-Z_0-9]*$/g.test(word) ? "tag" - : /^0[bB][0-1]+$/g.test(word) ? "number" - : /^0[cC][0-7]+$/g.test(word) ? "number" - : /^0[xX][a-fA-F0-9]+$/g.test(word) ? "number" - : /^([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+)$/g.test(word) ? "number" - : /^[0-9]+$/g.test(word) ? "number" - : "variable"; - } - return style; - }, - lineComment: "--" - }; -}); - -CodeMirror.defineMIME("text/x-eiffel", "eiffel"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/eiffel/index.html b/shared/html/libs/codemirror/5.0.0/mode/eiffel/index.html deleted file mode 100644 index 108a71b..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/eiffel/index.html +++ /dev/null @@ -1,429 +0,0 @@ - - -CodeMirror: Eiffel mode - - - - - - - - - - -
-

Eiffel mode

-
- - -

MIME types defined: text/x-eiffel.

- -

Created by YNH.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/erlang/erlang.js b/shared/html/libs/codemirror/5.0.0/mode/erlang/erlang.js deleted file mode 100644 index fbca292..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/erlang/erlang.js +++ /dev/null @@ -1,622 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/*jshint unused:true, eqnull:true, curly:true, bitwise:true */ -/*jshint undef:true, latedef:true, trailing:true */ -/*global CodeMirror:true */ - -// erlang mode. -// tokenizer -> token types -> CodeMirror styles -// tokenizer maintains a parse stack -// indenter uses the parse stack - -// TODO indenter: -// bit syntax -// old guard/bif/conversion clashes (e.g. "float/1") -// type/spec/opaque - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMIME("text/x-erlang", "erlang"); - -CodeMirror.defineMode("erlang", function(cmCfg) { - "use strict"; - -///////////////////////////////////////////////////////////////////////////// -// constants - - var typeWords = [ - "-type", "-spec", "-export_type", "-opaque"]; - - var keywordWords = [ - "after","begin","catch","case","cond","end","fun","if", - "let","of","query","receive","try","when"]; - - var separatorRE = /[\->,;]/; - var separatorWords = [ - "->",";",","]; - - var operatorAtomWords = [ - "and","andalso","band","bnot","bor","bsl","bsr","bxor", - "div","not","or","orelse","rem","xor"]; - - var operatorSymbolRE = /[\+\-\*\/<>=\|:!]/; - var operatorSymbolWords = [ - "=","+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-","!"]; - - var openParenRE = /[<\(\[\{]/; - var openParenWords = [ - "<<","(","[","{"]; - - var closeParenRE = /[>\)\]\}]/; - var closeParenWords = [ - "}","]",")",">>"]; - - var guardWords = [ - "is_atom","is_binary","is_bitstring","is_boolean","is_float", - "is_function","is_integer","is_list","is_number","is_pid", - "is_port","is_record","is_reference","is_tuple", - "atom","binary","bitstring","boolean","function","integer","list", - "number","pid","port","record","reference","tuple"]; - - var bifWords = [ - "abs","adler32","adler32_combine","alive","apply","atom_to_binary", - "atom_to_list","binary_to_atom","binary_to_existing_atom", - "binary_to_list","binary_to_term","bit_size","bitstring_to_list", - "byte_size","check_process_code","contact_binary","crc32", - "crc32_combine","date","decode_packet","delete_module", - "disconnect_node","element","erase","exit","float","float_to_list", - "garbage_collect","get","get_keys","group_leader","halt","hd", - "integer_to_list","internal_bif","iolist_size","iolist_to_binary", - "is_alive","is_atom","is_binary","is_bitstring","is_boolean", - "is_float","is_function","is_integer","is_list","is_number","is_pid", - "is_port","is_process_alive","is_record","is_reference","is_tuple", - "length","link","list_to_atom","list_to_binary","list_to_bitstring", - "list_to_existing_atom","list_to_float","list_to_integer", - "list_to_pid","list_to_tuple","load_module","make_ref","module_loaded", - "monitor_node","node","node_link","node_unlink","nodes","notalive", - "now","open_port","pid_to_list","port_close","port_command", - "port_connect","port_control","pre_loaded","process_flag", - "process_info","processes","purge_module","put","register", - "registered","round","self","setelement","size","spawn","spawn_link", - "spawn_monitor","spawn_opt","split_binary","statistics", - "term_to_binary","time","throw","tl","trunc","tuple_size", - "tuple_to_list","unlink","unregister","whereis"]; - -// upper case: [A-Z] [Ø-Þ] [À-Ö] -// lower case: [a-z] [ß-ö] [ø-ÿ] - var anumRE = /[\w@Ø-ÞÀ-Öß-öø-ÿ]/; - var escapesRE = - /[0-7]{1,3}|[bdefnrstv\\"']|\^[a-zA-Z]|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}/; - -///////////////////////////////////////////////////////////////////////////// -// tokenizer - - function tokenizer(stream,state) { - // in multi-line string - if (state.in_string) { - state.in_string = (!doubleQuote(stream)); - return rval(state,stream,"string"); - } - - // in multi-line atom - if (state.in_atom) { - state.in_atom = (!singleQuote(stream)); - return rval(state,stream,"atom"); - } - - // whitespace - if (stream.eatSpace()) { - return rval(state,stream,"whitespace"); - } - - // attributes and type specs - if (!peekToken(state) && - stream.match(/-\s*[a-zß-öø-ÿ][\wØ-ÞÀ-Öß-öø-ÿ]*/)) { - if (is_member(stream.current(),typeWords)) { - return rval(state,stream,"type"); - }else{ - return rval(state,stream,"attribute"); - } - } - - var ch = stream.next(); - - // comment - if (ch == '%') { - stream.skipToEnd(); - return rval(state,stream,"comment"); - } - - // colon - if (ch == ":") { - return rval(state,stream,"colon"); - } - - // macro - if (ch == '?') { - stream.eatSpace(); - stream.eatWhile(anumRE); - return rval(state,stream,"macro"); - } - - // record - if (ch == "#") { - stream.eatSpace(); - stream.eatWhile(anumRE); - return rval(state,stream,"record"); - } - - // dollar escape - if (ch == "$") { - if (stream.next() == "\\" && !stream.match(escapesRE)) { - return rval(state,stream,"error"); - } - return rval(state,stream,"number"); - } - - // dot - if (ch == ".") { - return rval(state,stream,"dot"); - } - - // quoted atom - if (ch == '\'') { - if (!(state.in_atom = (!singleQuote(stream)))) { - if (stream.match(/\s*\/\s*[0-9]/,false)) { - stream.match(/\s*\/\s*[0-9]/,true); - return rval(state,stream,"fun"); // 'f'/0 style fun - } - if (stream.match(/\s*\(/,false) || stream.match(/\s*:/,false)) { - return rval(state,stream,"function"); - } - } - return rval(state,stream,"atom"); - } - - // string - if (ch == '"') { - state.in_string = (!doubleQuote(stream)); - return rval(state,stream,"string"); - } - - // variable - if (/[A-Z_Ø-ÞÀ-Ö]/.test(ch)) { - stream.eatWhile(anumRE); - return rval(state,stream,"variable"); - } - - // atom/keyword/BIF/function - if (/[a-z_ß-öø-ÿ]/.test(ch)) { - stream.eatWhile(anumRE); - - if (stream.match(/\s*\/\s*[0-9]/,false)) { - stream.match(/\s*\/\s*[0-9]/,true); - return rval(state,stream,"fun"); // f/0 style fun - } - - var w = stream.current(); - - if (is_member(w,keywordWords)) { - return rval(state,stream,"keyword"); - }else if (is_member(w,operatorAtomWords)) { - return rval(state,stream,"operator"); - }else if (stream.match(/\s*\(/,false)) { - // 'put' and 'erlang:put' are bifs, 'foo:put' is not - if (is_member(w,bifWords) && - ((peekToken(state).token != ":") || - (peekToken(state,2).token == "erlang"))) { - return rval(state,stream,"builtin"); - }else if (is_member(w,guardWords)) { - return rval(state,stream,"guard"); - }else{ - return rval(state,stream,"function"); - } - }else if (is_member(w,operatorAtomWords)) { - return rval(state,stream,"operator"); - }else if (lookahead(stream) == ":") { - if (w == "erlang") { - return rval(state,stream,"builtin"); - } else { - return rval(state,stream,"function"); - } - }else if (is_member(w,["true","false"])) { - return rval(state,stream,"boolean"); - }else if (is_member(w,["true","false"])) { - return rval(state,stream,"boolean"); - }else{ - return rval(state,stream,"atom"); - } - } - - // number - var digitRE = /[0-9]/; - var radixRE = /[0-9a-zA-Z]/; // 36#zZ style int - if (digitRE.test(ch)) { - stream.eatWhile(digitRE); - if (stream.eat('#')) { // 36#aZ style integer - if (!stream.eatWhile(radixRE)) { - stream.backUp(1); //"36#" - syntax error - } - } else if (stream.eat('.')) { // float - if (!stream.eatWhile(digitRE)) { - stream.backUp(1); // "3." - probably end of function - } else { - if (stream.eat(/[eE]/)) { // float with exponent - if (stream.eat(/[-+]/)) { - if (!stream.eatWhile(digitRE)) { - stream.backUp(2); // "2e-" - syntax error - } - } else { - if (!stream.eatWhile(digitRE)) { - stream.backUp(1); // "2e" - syntax error - } - } - } - } - } - return rval(state,stream,"number"); // normal integer - } - - // open parens - if (nongreedy(stream,openParenRE,openParenWords)) { - return rval(state,stream,"open_paren"); - } - - // close parens - if (nongreedy(stream,closeParenRE,closeParenWords)) { - return rval(state,stream,"close_paren"); - } - - // separators - if (greedy(stream,separatorRE,separatorWords)) { - return rval(state,stream,"separator"); - } - - // operators - if (greedy(stream,operatorSymbolRE,operatorSymbolWords)) { - return rval(state,stream,"operator"); - } - - return rval(state,stream,null); - } - -///////////////////////////////////////////////////////////////////////////// -// utilities - function nongreedy(stream,re,words) { - if (stream.current().length == 1 && re.test(stream.current())) { - stream.backUp(1); - while (re.test(stream.peek())) { - stream.next(); - if (is_member(stream.current(),words)) { - return true; - } - } - stream.backUp(stream.current().length-1); - } - return false; - } - - function greedy(stream,re,words) { - if (stream.current().length == 1 && re.test(stream.current())) { - while (re.test(stream.peek())) { - stream.next(); - } - while (0 < stream.current().length) { - if (is_member(stream.current(),words)) { - return true; - }else{ - stream.backUp(1); - } - } - stream.next(); - } - return false; - } - - function doubleQuote(stream) { - return quote(stream, '"', '\\'); - } - - function singleQuote(stream) { - return quote(stream,'\'','\\'); - } - - function quote(stream,quoteChar,escapeChar) { - while (!stream.eol()) { - var ch = stream.next(); - if (ch == quoteChar) { - return true; - }else if (ch == escapeChar) { - stream.next(); - } - } - return false; - } - - function lookahead(stream) { - var m = stream.match(/([\n\s]+|%[^\n]*\n)*(.)/,false); - return m ? m.pop() : ""; - } - - function is_member(element,list) { - return (-1 < list.indexOf(element)); - } - - function rval(state,stream,type) { - - // parse stack - pushToken(state,realToken(type,stream)); - - // map erlang token type to CodeMirror style class - // erlang -> CodeMirror tag - switch (type) { - case "atom": return "atom"; - case "attribute": return "attribute"; - case "boolean": return "atom"; - case "builtin": return "builtin"; - case "close_paren": return null; - case "colon": return null; - case "comment": return "comment"; - case "dot": return null; - case "error": return "error"; - case "fun": return "meta"; - case "function": return "tag"; - case "guard": return "property"; - case "keyword": return "keyword"; - case "macro": return "variable-2"; - case "number": return "number"; - case "open_paren": return null; - case "operator": return "operator"; - case "record": return "bracket"; - case "separator": return null; - case "string": return "string"; - case "type": return "def"; - case "variable": return "variable"; - default: return null; - } - } - - function aToken(tok,col,ind,typ) { - return {token: tok, - column: col, - indent: ind, - type: typ}; - } - - function realToken(type,stream) { - return aToken(stream.current(), - stream.column(), - stream.indentation(), - type); - } - - function fakeToken(type) { - return aToken(type,0,0,type); - } - - function peekToken(state,depth) { - var len = state.tokenStack.length; - var dep = (depth ? depth : 1); - - if (len < dep) { - return false; - }else{ - return state.tokenStack[len-dep]; - } - } - - function pushToken(state,token) { - - if (!(token.type == "comment" || token.type == "whitespace")) { - state.tokenStack = maybe_drop_pre(state.tokenStack,token); - state.tokenStack = maybe_drop_post(state.tokenStack); - } - } - - function maybe_drop_pre(s,token) { - var last = s.length-1; - - if (0 < last && s[last].type === "record" && token.type === "dot") { - s.pop(); - }else if (0 < last && s[last].type === "group") { - s.pop(); - s.push(token); - }else{ - s.push(token); - } - return s; - } - - function maybe_drop_post(s) { - var last = s.length-1; - - if (s[last].type === "dot") { - return []; - } - if (s[last].type === "fun" && s[last-1].token === "fun") { - return s.slice(0,last-1); - } - switch (s[s.length-1].token) { - case "}": return d(s,{g:["{"]}); - case "]": return d(s,{i:["["]}); - case ")": return d(s,{i:["("]}); - case ">>": return d(s,{i:["<<"]}); - case "end": return d(s,{i:["begin","case","fun","if","receive","try"]}); - case ",": return d(s,{e:["begin","try","when","->", - ",","(","[","{","<<"]}); - case "->": return d(s,{r:["when"], - m:["try","if","case","receive"]}); - case ";": return d(s,{E:["case","fun","if","receive","try","when"]}); - case "catch":return d(s,{e:["try"]}); - case "of": return d(s,{e:["case"]}); - case "after":return d(s,{e:["receive","try"]}); - default: return s; - } - } - - function d(stack,tt) { - // stack is a stack of Token objects. - // tt is an object; {type:tokens} - // type is a char, tokens is a list of token strings. - // The function returns (possibly truncated) stack. - // It will descend the stack, looking for a Token such that Token.token - // is a member of tokens. If it does not find that, it will normally (but - // see "E" below) return stack. If it does find a match, it will remove - // all the Tokens between the top and the matched Token. - // If type is "m", that is all it does. - // If type is "i", it will also remove the matched Token and the top Token. - // If type is "g", like "i", but add a fake "group" token at the top. - // If type is "r", it will remove the matched Token, but not the top Token. - // If type is "e", it will keep the matched Token but not the top Token. - // If type is "E", it behaves as for type "e", except if there is no match, - // in which case it will return an empty stack. - - for (var type in tt) { - var len = stack.length-1; - var tokens = tt[type]; - for (var i = len-1; -1 < i ; i--) { - if (is_member(stack[i].token,tokens)) { - var ss = stack.slice(0,i); - switch (type) { - case "m": return ss.concat(stack[i]).concat(stack[len]); - case "r": return ss.concat(stack[len]); - case "i": return ss; - case "g": return ss.concat(fakeToken("group")); - case "E": return ss.concat(stack[i]); - case "e": return ss.concat(stack[i]); - } - } - } - } - return (type == "E" ? [] : stack); - } - -///////////////////////////////////////////////////////////////////////////// -// indenter - - function indenter(state,textAfter) { - var t; - var unit = cmCfg.indentUnit; - var wordAfter = wordafter(textAfter); - var currT = peekToken(state,1); - var prevT = peekToken(state,2); - - if (state.in_string || state.in_atom) { - return CodeMirror.Pass; - }else if (!prevT) { - return 0; - }else if (currT.token == "when") { - return currT.column+unit; - }else if (wordAfter === "when" && prevT.type === "function") { - return prevT.indent+unit; - }else if (wordAfter === "(" && currT.token === "fun") { - return currT.column+3; - }else if (wordAfter === "catch" && (t = getToken(state,["try"]))) { - return t.column; - }else if (is_member(wordAfter,["end","after","of"])) { - t = getToken(state,["begin","case","fun","if","receive","try"]); - return t ? t.column : CodeMirror.Pass; - }else if (is_member(wordAfter,closeParenWords)) { - t = getToken(state,openParenWords); - return t ? t.column : CodeMirror.Pass; - }else if (is_member(currT.token,[",","|","||"]) || - is_member(wordAfter,[",","|","||"])) { - t = postcommaToken(state); - return t ? t.column+t.token.length : unit; - }else if (currT.token == "->") { - if (is_member(prevT.token, ["receive","case","if","try"])) { - return prevT.column+unit+unit; - }else{ - return prevT.column+unit; - } - }else if (is_member(currT.token,openParenWords)) { - return currT.column+currT.token.length; - }else{ - t = defaultToken(state); - return truthy(t) ? t.column+unit : 0; - } - } - - function wordafter(str) { - var m = str.match(/,|[a-z]+|\}|\]|\)|>>|\|+|\(/); - - return truthy(m) && (m.index === 0) ? m[0] : ""; - } - - function postcommaToken(state) { - var objs = state.tokenStack.slice(0,-1); - var i = getTokenIndex(objs,"type",["open_paren"]); - - return truthy(objs[i]) ? objs[i] : false; - } - - function defaultToken(state) { - var objs = state.tokenStack; - var stop = getTokenIndex(objs,"type",["open_paren","separator","keyword"]); - var oper = getTokenIndex(objs,"type",["operator"]); - - if (truthy(stop) && truthy(oper) && stop < oper) { - return objs[stop+1]; - } else if (truthy(stop)) { - return objs[stop]; - } else { - return false; - } - } - - function getToken(state,tokens) { - var objs = state.tokenStack; - var i = getTokenIndex(objs,"token",tokens); - - return truthy(objs[i]) ? objs[i] : false; - } - - function getTokenIndex(objs,propname,propvals) { - - for (var i = objs.length-1; -1 < i ; i--) { - if (is_member(objs[i][propname],propvals)) { - return i; - } - } - return false; - } - - function truthy(x) { - return (x !== false) && (x != null); - } - -///////////////////////////////////////////////////////////////////////////// -// this object defines the mode - - return { - startState: - function() { - return {tokenStack: [], - in_string: false, - in_atom: false}; - }, - - token: - function(stream, state) { - return tokenizer(stream, state); - }, - - indent: - function(state, textAfter) { - return indenter(state,textAfter); - }, - - lineComment: "%" - }; -}); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/erlang/index.html b/shared/html/libs/codemirror/5.0.0/mode/erlang/index.html deleted file mode 100644 index 6d06a89..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/erlang/index.html +++ /dev/null @@ -1,76 +0,0 @@ - - -CodeMirror: Erlang mode - - - - - - - - - - - -
-

Erlang mode

-
- - - -

MIME types defined: text/x-erlang.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/forth/forth.js b/shared/html/libs/codemirror/5.0.0/mode/forth/forth.js deleted file mode 100644 index 1f519d8..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/forth/forth.js +++ /dev/null @@ -1,180 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Author: Aliaksei Chapyzhenka - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function toWordList(words) { - var ret = []; - words.split(' ').forEach(function(e){ - ret.push({name: e}); - }); - return ret; - } - - var coreWordList = toWordList( -'INVERT AND OR XOR\ - 2* 2/ LSHIFT RSHIFT\ - 0= = 0< < > U< MIN MAX\ - 2DROP 2DUP 2OVER 2SWAP ?DUP DEPTH DROP DUP OVER ROT SWAP\ - >R R> R@\ - + - 1+ 1- ABS NEGATE\ - S>D * M* UM*\ - FM/MOD SM/REM UM/MOD */ */MOD / /MOD MOD\ - HERE , @ ! CELL+ CELLS C, C@ C! CHARS 2@ 2!\ - ALIGN ALIGNED +! ALLOT\ - CHAR [CHAR] [ ] BL\ - FIND EXECUTE IMMEDIATE COUNT LITERAL STATE\ - ; DOES> >BODY\ - EVALUATE\ - SOURCE >IN\ - <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL\ - FILL MOVE\ - . CR EMIT SPACE SPACES TYPE U. .R U.R\ - ACCEPT\ - TRUE FALSE\ - <> U> 0<> 0>\ - NIP TUCK ROLL PICK\ - 2>R 2R@ 2R>\ - WITHIN UNUSED MARKER\ - I J\ - TO\ - COMPILE, [COMPILE]\ - SAVE-INPUT RESTORE-INPUT\ - PAD ERASE\ - 2LITERAL DNEGATE\ - D- D+ D0< D0= D2* D2/ D< D= DMAX DMIN D>S DABS\ - M+ M*/ D. D.R 2ROT DU<\ - CATCH THROW\ - FREE RESIZE ALLOCATE\ - CS-PICK CS-ROLL\ - GET-CURRENT SET-CURRENT FORTH-WORDLIST GET-ORDER SET-ORDER\ - PREVIOUS SEARCH-WORDLIST WORDLIST FIND ALSO ONLY FORTH DEFINITIONS ORDER\ - -TRAILING /STRING SEARCH COMPARE CMOVE CMOVE> BLANK SLITERAL'); - - var immediateWordList = toWordList('IF ELSE THEN BEGIN WHILE REPEAT UNTIL RECURSE [IF] [ELSE] [THEN] ?DO DO LOOP +LOOP UNLOOP LEAVE EXIT AGAIN CASE OF ENDOF ENDCASE'); - - CodeMirror.defineMode('forth', function() { - function searchWordList (wordList, word) { - var i; - for (i = wordList.length - 1; i >= 0; i--) { - if (wordList[i].name === word.toUpperCase()) { - return wordList[i]; - } - } - return undefined; - } - return { - startState: function() { - return { - state: '', - base: 10, - coreWordList: coreWordList, - immediateWordList: immediateWordList, - wordList: [] - }; - }, - token: function (stream, stt) { - var mat; - if (stream.eatSpace()) { - return null; - } - if (stt.state === '') { // interpretation - if (stream.match(/^(\]|:NONAME)(\s|$)/i)) { - stt.state = ' compilation'; - return 'builtin compilation'; - } - mat = stream.match(/^(\:)\s+(\S+)(\s|$)+/); - if (mat) { - stt.wordList.push({name: mat[2].toUpperCase()}); - stt.state = ' compilation'; - return 'def' + stt.state; - } - mat = stream.match(/^(VARIABLE|2VARIABLE|CONSTANT|2CONSTANT|CREATE|POSTPONE|VALUE|WORD)\s+(\S+)(\s|$)+/i); - if (mat) { - stt.wordList.push({name: mat[2].toUpperCase()}); - return 'def' + stt.state; - } - mat = stream.match(/^(\'|\[\'\])\s+(\S+)(\s|$)+/); - if (mat) { - return 'builtin' + stt.state; - } - } else { // compilation - // ; [ - if (stream.match(/^(\;|\[)(\s)/)) { - stt.state = ''; - stream.backUp(1); - return 'builtin compilation'; - } - if (stream.match(/^(\;|\[)($)/)) { - stt.state = ''; - return 'builtin compilation'; - } - if (stream.match(/^(POSTPONE)\s+\S+(\s|$)+/)) { - return 'builtin'; - } - } - - // dynamic wordlist - mat = stream.match(/^(\S+)(\s+|$)/); - if (mat) { - if (searchWordList(stt.wordList, mat[1]) !== undefined) { - return 'variable' + stt.state; - } - - // comments - if (mat[1] === '\\') { - stream.skipToEnd(); - return 'comment' + stt.state; - } - - // core words - if (searchWordList(stt.coreWordList, mat[1]) !== undefined) { - return 'builtin' + stt.state; - } - if (searchWordList(stt.immediateWordList, mat[1]) !== undefined) { - return 'keyword' + stt.state; - } - - if (mat[1] === '(') { - stream.eatWhile(function (s) { return s !== ')'; }); - stream.eat(')'); - return 'comment' + stt.state; - } - - // // strings - if (mat[1] === '.(') { - stream.eatWhile(function (s) { return s !== ')'; }); - stream.eat(')'); - return 'string' + stt.state; - } - if (mat[1] === 'S"' || mat[1] === '."' || mat[1] === 'C"') { - stream.eatWhile(function (s) { return s !== '"'; }); - stream.eat('"'); - return 'string' + stt.state; - } - - // numbers - if (mat[1] - 0xfffffffff) { - return 'number' + stt.state; - } - // if (mat[1].match(/^[-+]?[0-9]+\.[0-9]*/)) { - // return 'number' + stt.state; - // } - - return 'atom' + stt.state; - } - } - }; - }); - CodeMirror.defineMIME("text/x-forth", "forth"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/forth/index.html b/shared/html/libs/codemirror/5.0.0/mode/forth/index.html deleted file mode 100644 index ae8cd34..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/forth/index.html +++ /dev/null @@ -1,75 +0,0 @@ - - -CodeMirror: Forth mode - - - - - - - - - - - -
- -

Forth mode

- -
-
- - - -

Simple mode that handle Forth-Syntax (Forth on WikiPedia).

- -

MIME types defined: text/x-forth.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/fortran/fortran.js b/shared/html/libs/codemirror/5.0.0/mode/fortran/fortran.js deleted file mode 100644 index 4d88f00..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/fortran/fortran.js +++ /dev/null @@ -1,188 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("fortran", function() { - function words(array) { - var keys = {}; - for (var i = 0; i < array.length; ++i) { - keys[array[i]] = true; - } - return keys; - } - - var keywords = words([ - "abstract", "accept", "allocatable", "allocate", - "array", "assign", "asynchronous", "backspace", - "bind", "block", "byte", "call", "case", - "class", "close", "common", "contains", - "continue", "cycle", "data", "deallocate", - "decode", "deferred", "dimension", "do", - "elemental", "else", "encode", "end", - "endif", "entry", "enumerator", "equivalence", - "exit", "external", "extrinsic", "final", - "forall", "format", "function", "generic", - "go", "goto", "if", "implicit", "import", "include", - "inquire", "intent", "interface", "intrinsic", - "module", "namelist", "non_intrinsic", - "non_overridable", "none", "nopass", - "nullify", "open", "optional", "options", - "parameter", "pass", "pause", "pointer", - "print", "private", "program", "protected", - "public", "pure", "read", "recursive", "result", - "return", "rewind", "save", "select", "sequence", - "stop", "subroutine", "target", "then", "to", "type", - "use", "value", "volatile", "where", "while", - "write"]); - var builtins = words(["abort", "abs", "access", "achar", "acos", - "adjustl", "adjustr", "aimag", "aint", "alarm", - "all", "allocated", "alog", "amax", "amin", - "amod", "and", "anint", "any", "asin", - "associated", "atan", "besj", "besjn", "besy", - "besyn", "bit_size", "btest", "cabs", "ccos", - "ceiling", "cexp", "char", "chdir", "chmod", - "clog", "cmplx", "command_argument_count", - "complex", "conjg", "cos", "cosh", "count", - "cpu_time", "cshift", "csin", "csqrt", "ctime", - "c_funloc", "c_loc", "c_associated", "c_null_ptr", - "c_null_funptr", "c_f_pointer", "c_null_char", - "c_alert", "c_backspace", "c_form_feed", - "c_new_line", "c_carriage_return", - "c_horizontal_tab", "c_vertical_tab", "dabs", - "dacos", "dasin", "datan", "date_and_time", - "dbesj", "dbesj", "dbesjn", "dbesy", "dbesy", - "dbesyn", "dble", "dcos", "dcosh", "ddim", "derf", - "derfc", "dexp", "digits", "dim", "dint", "dlog", - "dlog", "dmax", "dmin", "dmod", "dnint", - "dot_product", "dprod", "dsign", "dsinh", - "dsin", "dsqrt", "dtanh", "dtan", "dtime", - "eoshift", "epsilon", "erf", "erfc", "etime", - "exit", "exp", "exponent", "extends_type_of", - "fdate", "fget", "fgetc", "float", "floor", - "flush", "fnum", "fputc", "fput", "fraction", - "fseek", "fstat", "ftell", "gerror", "getarg", - "get_command", "get_command_argument", - "get_environment_variable", "getcwd", - "getenv", "getgid", "getlog", "getpid", - "getuid", "gmtime", "hostnm", "huge", "iabs", - "iachar", "iand", "iargc", "ibclr", "ibits", - "ibset", "ichar", "idate", "idim", "idint", - "idnint", "ieor", "ierrno", "ifix", "imag", - "imagpart", "index", "int", "ior", "irand", - "isatty", "ishft", "ishftc", "isign", - "iso_c_binding", "is_iostat_end", "is_iostat_eor", - "itime", "kill", "kind", "lbound", "len", "len_trim", - "lge", "lgt", "link", "lle", "llt", "lnblnk", "loc", - "log", "logical", "long", "lshift", "lstat", "ltime", - "matmul", "max", "maxexponent", "maxloc", "maxval", - "mclock", "merge", "move_alloc", "min", "minexponent", - "minloc", "minval", "mod", "modulo", "mvbits", - "nearest", "new_line", "nint", "not", "or", "pack", - "perror", "precision", "present", "product", "radix", - "rand", "random_number", "random_seed", "range", - "real", "realpart", "rename", "repeat", "reshape", - "rrspacing", "rshift", "same_type_as", "scale", - "scan", "second", "selected_int_kind", - "selected_real_kind", "set_exponent", "shape", - "short", "sign", "signal", "sinh", "sin", "sleep", - "sngl", "spacing", "spread", "sqrt", "srand", "stat", - "sum", "symlnk", "system", "system_clock", "tan", - "tanh", "time", "tiny", "transfer", "transpose", - "trim", "ttynam", "ubound", "umask", "unlink", - "unpack", "verify", "xor", "zabs", "zcos", "zexp", - "zlog", "zsin", "zsqrt"]); - - var dataTypes = words(["c_bool", "c_char", "c_double", "c_double_complex", - "c_float", "c_float_complex", "c_funptr", "c_int", - "c_int16_t", "c_int32_t", "c_int64_t", "c_int8_t", - "c_int_fast16_t", "c_int_fast32_t", "c_int_fast64_t", - "c_int_fast8_t", "c_int_least16_t", "c_int_least32_t", - "c_int_least64_t", "c_int_least8_t", "c_intmax_t", - "c_intptr_t", "c_long", "c_long_double", - "c_long_double_complex", "c_long_long", "c_ptr", - "c_short", "c_signed_char", "c_size_t", "character", - "complex", "double", "integer", "logical", "real"]); - var isOperatorChar = /[+\-*&=<>\/\:]/; - var litOperator = new RegExp("(\.and\.|\.or\.|\.eq\.|\.lt\.|\.le\.|\.gt\.|\.ge\.|\.ne\.|\.not\.|\.eqv\.|\.neqv\.)", "i"); - - function tokenBase(stream, state) { - - if (stream.match(litOperator)){ - return 'operator'; - } - - var ch = stream.next(); - if (ch == "!") { - stream.skipToEnd(); - return "comment"; - } - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\[\]\(\),]/.test(ch)) { - return null; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - var word = stream.current().toLowerCase(); - - if (keywords.hasOwnProperty(word)){ - return 'keyword'; - } - if (builtins.hasOwnProperty(word) || dataTypes.hasOwnProperty(word)) { - return 'builtin'; - } - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) { - end = true; - break; - } - escaped = !escaped && next == "\\"; - } - if (end || !escaped) state.tokenize = null; - return "string"; - }; - } - - // Interface - - return { - startState: function() { - return {tokenize: null}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - return style; - } - }; -}); - -CodeMirror.defineMIME("text/x-fortran", "fortran"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/fortran/index.html b/shared/html/libs/codemirror/5.0.0/mode/fortran/index.html deleted file mode 100644 index 102e8f8..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/fortran/index.html +++ /dev/null @@ -1,81 +0,0 @@ - - -CodeMirror: Fortran mode - - - - - - - - - -
-

Fortran mode

- - -
- - - -

MIME types defined: text/x-Fortran.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/gas/gas.js b/shared/html/libs/codemirror/5.0.0/mode/gas/gas.js deleted file mode 100644 index 0c74bed..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/gas/gas.js +++ /dev/null @@ -1,345 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("gas", function(_config, parserConfig) { - 'use strict'; - - // If an architecture is specified, its initialization function may - // populate this array with custom parsing functions which will be - // tried in the event that the standard functions do not find a match. - var custom = []; - - // The symbol used to start a line comment changes based on the target - // architecture. - // If no architecture is pased in "parserConfig" then only multiline - // comments will have syntax support. - var lineCommentStartSymbol = ""; - - // These directives are architecture independent. - // Machine specific directives should go in their respective - // architecture initialization function. - // Reference: - // http://sourceware.org/binutils/docs/as/Pseudo-Ops.html#Pseudo-Ops - var directives = { - ".abort" : "builtin", - ".align" : "builtin", - ".altmacro" : "builtin", - ".ascii" : "builtin", - ".asciz" : "builtin", - ".balign" : "builtin", - ".balignw" : "builtin", - ".balignl" : "builtin", - ".bundle_align_mode" : "builtin", - ".bundle_lock" : "builtin", - ".bundle_unlock" : "builtin", - ".byte" : "builtin", - ".cfi_startproc" : "builtin", - ".comm" : "builtin", - ".data" : "builtin", - ".def" : "builtin", - ".desc" : "builtin", - ".dim" : "builtin", - ".double" : "builtin", - ".eject" : "builtin", - ".else" : "builtin", - ".elseif" : "builtin", - ".end" : "builtin", - ".endef" : "builtin", - ".endfunc" : "builtin", - ".endif" : "builtin", - ".equ" : "builtin", - ".equiv" : "builtin", - ".eqv" : "builtin", - ".err" : "builtin", - ".error" : "builtin", - ".exitm" : "builtin", - ".extern" : "builtin", - ".fail" : "builtin", - ".file" : "builtin", - ".fill" : "builtin", - ".float" : "builtin", - ".func" : "builtin", - ".global" : "builtin", - ".gnu_attribute" : "builtin", - ".hidden" : "builtin", - ".hword" : "builtin", - ".ident" : "builtin", - ".if" : "builtin", - ".incbin" : "builtin", - ".include" : "builtin", - ".int" : "builtin", - ".internal" : "builtin", - ".irp" : "builtin", - ".irpc" : "builtin", - ".lcomm" : "builtin", - ".lflags" : "builtin", - ".line" : "builtin", - ".linkonce" : "builtin", - ".list" : "builtin", - ".ln" : "builtin", - ".loc" : "builtin", - ".loc_mark_labels" : "builtin", - ".local" : "builtin", - ".long" : "builtin", - ".macro" : "builtin", - ".mri" : "builtin", - ".noaltmacro" : "builtin", - ".nolist" : "builtin", - ".octa" : "builtin", - ".offset" : "builtin", - ".org" : "builtin", - ".p2align" : "builtin", - ".popsection" : "builtin", - ".previous" : "builtin", - ".print" : "builtin", - ".protected" : "builtin", - ".psize" : "builtin", - ".purgem" : "builtin", - ".pushsection" : "builtin", - ".quad" : "builtin", - ".reloc" : "builtin", - ".rept" : "builtin", - ".sbttl" : "builtin", - ".scl" : "builtin", - ".section" : "builtin", - ".set" : "builtin", - ".short" : "builtin", - ".single" : "builtin", - ".size" : "builtin", - ".skip" : "builtin", - ".sleb128" : "builtin", - ".space" : "builtin", - ".stab" : "builtin", - ".string" : "builtin", - ".struct" : "builtin", - ".subsection" : "builtin", - ".symver" : "builtin", - ".tag" : "builtin", - ".text" : "builtin", - ".title" : "builtin", - ".type" : "builtin", - ".uleb128" : "builtin", - ".val" : "builtin", - ".version" : "builtin", - ".vtable_entry" : "builtin", - ".vtable_inherit" : "builtin", - ".warning" : "builtin", - ".weak" : "builtin", - ".weakref" : "builtin", - ".word" : "builtin" - }; - - var registers = {}; - - function x86(_parserConfig) { - lineCommentStartSymbol = "#"; - - registers.ax = "variable"; - registers.eax = "variable-2"; - registers.rax = "variable-3"; - - registers.bx = "variable"; - registers.ebx = "variable-2"; - registers.rbx = "variable-3"; - - registers.cx = "variable"; - registers.ecx = "variable-2"; - registers.rcx = "variable-3"; - - registers.dx = "variable"; - registers.edx = "variable-2"; - registers.rdx = "variable-3"; - - registers.si = "variable"; - registers.esi = "variable-2"; - registers.rsi = "variable-3"; - - registers.di = "variable"; - registers.edi = "variable-2"; - registers.rdi = "variable-3"; - - registers.sp = "variable"; - registers.esp = "variable-2"; - registers.rsp = "variable-3"; - - registers.bp = "variable"; - registers.ebp = "variable-2"; - registers.rbp = "variable-3"; - - registers.ip = "variable"; - registers.eip = "variable-2"; - registers.rip = "variable-3"; - - registers.cs = "keyword"; - registers.ds = "keyword"; - registers.ss = "keyword"; - registers.es = "keyword"; - registers.fs = "keyword"; - registers.gs = "keyword"; - } - - function armv6(_parserConfig) { - // Reference: - // http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf - // http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf - lineCommentStartSymbol = "@"; - directives.syntax = "builtin"; - - registers.r0 = "variable"; - registers.r1 = "variable"; - registers.r2 = "variable"; - registers.r3 = "variable"; - registers.r4 = "variable"; - registers.r5 = "variable"; - registers.r6 = "variable"; - registers.r7 = "variable"; - registers.r8 = "variable"; - registers.r9 = "variable"; - registers.r10 = "variable"; - registers.r11 = "variable"; - registers.r12 = "variable"; - - registers.sp = "variable-2"; - registers.lr = "variable-2"; - registers.pc = "variable-2"; - registers.r13 = registers.sp; - registers.r14 = registers.lr; - registers.r15 = registers.pc; - - custom.push(function(ch, stream) { - if (ch === '#') { - stream.eatWhile(/\w/); - return "number"; - } - }); - } - - var arch = (parserConfig.architecture || "x86").toLowerCase(); - if (arch === "x86") { - x86(parserConfig); - } else if (arch === "arm" || arch === "armv6") { - armv6(parserConfig); - } - - function nextUntilUnescaped(stream, end) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (next === end && !escaped) { - return false; - } - escaped = !escaped && next === "\\"; - } - return escaped; - } - - function clikeComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (ch === "/" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch === "*"); - } - return "comment"; - } - - return { - startState: function() { - return { - tokenize: null - }; - }, - - token: function(stream, state) { - if (state.tokenize) { - return state.tokenize(stream, state); - } - - if (stream.eatSpace()) { - return null; - } - - var style, cur, ch = stream.next(); - - if (ch === "/") { - if (stream.eat("*")) { - state.tokenize = clikeComment; - return clikeComment(stream, state); - } - } - - if (ch === lineCommentStartSymbol) { - stream.skipToEnd(); - return "comment"; - } - - if (ch === '"') { - nextUntilUnescaped(stream, '"'); - return "string"; - } - - if (ch === '.') { - stream.eatWhile(/\w/); - cur = stream.current().toLowerCase(); - style = directives[cur]; - return style || null; - } - - if (ch === '=') { - stream.eatWhile(/\w/); - return "tag"; - } - - if (ch === '{') { - return "braket"; - } - - if (ch === '}') { - return "braket"; - } - - if (/\d/.test(ch)) { - if (ch === "0" && stream.eat("x")) { - stream.eatWhile(/[0-9a-fA-F]/); - return "number"; - } - stream.eatWhile(/\d/); - return "number"; - } - - if (/\w/.test(ch)) { - stream.eatWhile(/\w/); - if (stream.eat(":")) { - return 'tag'; - } - cur = stream.current().toLowerCase(); - style = registers[cur]; - return style || null; - } - - for (var i = 0; i < custom.length; i++) { - style = custom[i](ch, stream, state); - if (style) { - return style; - } - } - }, - - lineComment: lineCommentStartSymbol, - blockCommentStart: "/*", - blockCommentEnd: "*/" - }; -}); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/gas/index.html b/shared/html/libs/codemirror/5.0.0/mode/gas/index.html deleted file mode 100644 index df75ca2..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/gas/index.html +++ /dev/null @@ -1,68 +0,0 @@ - - -CodeMirror: Gas mode - - - - - - - - - -
-

Gas mode

-
- -
- - - -

Handles AT&T assembler syntax (more specifically this handles - the GNU Assembler (gas) syntax.) - It takes a single optional configuration parameter: - architecture, which can be one of "ARM", - "ARMv6" or "x86". - Including the parameter adds syntax for the registers and special - directives for the supplied architecture. - -

MIME types defined: text/x-gas

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/gfm/gfm.js b/shared/html/libs/codemirror/5.0.0/mode/gfm/gfm.js deleted file mode 100644 index 80a8e2c..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/gfm/gfm.js +++ /dev/null @@ -1,123 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../markdown/markdown"), require("../../addon/mode/overlay")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../markdown/markdown", "../../addon/mode/overlay"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("gfm", function(config, modeConfig) { - var codeDepth = 0; - function blankLine(state) { - state.code = false; - return null; - } - var gfmOverlay = { - startState: function() { - return { - code: false, - codeBlock: false, - ateSpace: false - }; - }, - copyState: function(s) { - return { - code: s.code, - codeBlock: s.codeBlock, - ateSpace: s.ateSpace - }; - }, - token: function(stream, state) { - state.combineTokens = null; - - // Hack to prevent formatting override inside code blocks (block and inline) - if (state.codeBlock) { - if (stream.match(/^```/)) { - state.codeBlock = false; - return null; - } - stream.skipToEnd(); - return null; - } - if (stream.sol()) { - state.code = false; - } - if (stream.sol() && stream.match(/^```/)) { - stream.skipToEnd(); - state.codeBlock = true; - return null; - } - // If this block is changed, it may need to be updated in Markdown mode - if (stream.peek() === '`') { - stream.next(); - var before = stream.pos; - stream.eatWhile('`'); - var difference = 1 + stream.pos - before; - if (!state.code) { - codeDepth = difference; - state.code = true; - } else { - if (difference === codeDepth) { // Must be exact - state.code = false; - } - } - return null; - } else if (state.code) { - stream.next(); - return null; - } - // Check if space. If so, links can be formatted later on - if (stream.eatSpace()) { - state.ateSpace = true; - return null; - } - if (stream.sol() || state.ateSpace) { - state.ateSpace = false; - if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) { - // User/Project@SHA - // User@SHA - // SHA - state.combineTokens = true; - return "link"; - } else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) { - // User/Project#Num - // User#Num - // #Num - state.combineTokens = true; - return "link"; - } - } - if (stream.match(/^((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?«»“”‘’]))/i) && - stream.string.slice(stream.start - 2, stream.start) != "](") { - // URLs - // Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls - // And then (issue #1160) simplified to make it not crash the Chrome Regexp engine - state.combineTokens = true; - return "link"; - } - stream.next(); - return null; - }, - blankLine: blankLine - }; - - var markdownConfig = { - underscoresBreakWords: false, - taskLists: true, - fencedCodeBlocks: true, - strikethrough: true - }; - for (var attr in modeConfig) { - markdownConfig[attr] = modeConfig[attr]; - } - markdownConfig.name = "markdown"; - CodeMirror.defineMIME("gfmBase", markdownConfig); - return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay); -}, "markdown"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/gfm/index.html b/shared/html/libs/codemirror/5.0.0/mode/gfm/index.html deleted file mode 100644 index 7e38c52..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/gfm/index.html +++ /dev/null @@ -1,93 +0,0 @@ - - -CodeMirror: GFM mode - - - - - - - - - - - - - - - - - -
-

GFM mode

-
- - - -

Optionally depends on other modes for properly highlighted code blocks.

- -

Parsing/Highlighting Tests: normal, verbose.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/gfm/test.js b/shared/html/libs/codemirror/5.0.0/mode/gfm/test.js deleted file mode 100644 index c2bc38f..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/gfm/test.js +++ /dev/null @@ -1,213 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({tabSize: 4}, "gfm"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "gfm", highlightFormatting: true}); - function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); } - - FT("codeBackticks", - "[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]"); - - FT("doubleBackticks", - "[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]"); - - FT("codeBlock", - "[comment&formatting&formatting-code-block ```css]", - "[tag foo]", - "[comment&formatting&formatting-code-block ```]"); - - FT("taskList", - "[variable-2&formatting&formatting-list&formatting-list-ul - ][meta&formatting&formatting-task [ ]]][variable-2 foo]", - "[variable-2&formatting&formatting-list&formatting-list-ul - ][property&formatting&formatting-task [x]]][variable-2 foo]"); - - FT("formatting_strikethrough", - "[strikethrough&formatting&formatting-strikethrough ~~][strikethrough foo][strikethrough&formatting&formatting-strikethrough ~~]"); - - FT("formatting_strikethrough", - "foo [strikethrough&formatting&formatting-strikethrough ~~][strikethrough bar][strikethrough&formatting&formatting-strikethrough ~~]"); - - MT("emInWordAsterisk", - "foo[em *bar*]hello"); - - MT("emInWordUnderscore", - "foo_bar_hello"); - - MT("emStrongUnderscore", - "[strong __][em&strong _foo__][em _] bar"); - - MT("fencedCodeBlocks", - "[comment ```]", - "[comment foo]", - "", - "[comment ```]", - "bar"); - - MT("fencedCodeBlockModeSwitching", - "[comment ```javascript]", - "[variable foo]", - "", - "[comment ```]", - "bar"); - - MT("taskListAsterisk", - "[variable-2 * []] foo]", // Invalid; must have space or x between [] - "[variable-2 * [ ]]bar]", // Invalid; must have space after ] - "[variable-2 * [x]]hello]", // Invalid; must have space after ] - "[variable-2 * ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links - " [variable-3 * ][property [x]]][variable-3 foo]"); // Valid; can be nested - - MT("taskListPlus", - "[variable-2 + []] foo]", // Invalid; must have space or x between [] - "[variable-2 + [ ]]bar]", // Invalid; must have space after ] - "[variable-2 + [x]]hello]", // Invalid; must have space after ] - "[variable-2 + ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links - " [variable-3 + ][property [x]]][variable-3 foo]"); // Valid; can be nested - - MT("taskListDash", - "[variable-2 - []] foo]", // Invalid; must have space or x between [] - "[variable-2 - [ ]]bar]", // Invalid; must have space after ] - "[variable-2 - [x]]hello]", // Invalid; must have space after ] - "[variable-2 - ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links - " [variable-3 - ][property [x]]][variable-3 foo]"); // Valid; can be nested - - MT("taskListNumber", - "[variable-2 1. []] foo]", // Invalid; must have space or x between [] - "[variable-2 2. [ ]]bar]", // Invalid; must have space after ] - "[variable-2 3. [x]]hello]", // Invalid; must have space after ] - "[variable-2 4. ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links - " [variable-3 1. ][property [x]]][variable-3 foo]"); // Valid; can be nested - - MT("SHA", - "foo [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] bar"); - - MT("SHAEmphasis", - "[em *foo ][em&link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]"); - - MT("shortSHA", - "foo [link be6a8cc] bar"); - - MT("tooShortSHA", - "foo be6a8c bar"); - - MT("longSHA", - "foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd22 bar"); - - MT("badSHA", - "foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cg2 bar"); - - MT("userSHA", - "foo [link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] hello"); - - MT("userSHAEmphasis", - "[em *foo ][em&link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]"); - - MT("userProjectSHA", - "foo [link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] world"); - - MT("userProjectSHAEmphasis", - "[em *foo ][em&link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]"); - - MT("num", - "foo [link #1] bar"); - - MT("numEmphasis", - "[em *foo ][em&link #1][em *]"); - - MT("badNum", - "foo #1bar hello"); - - MT("userNum", - "foo [link bar#1] hello"); - - MT("userNumEmphasis", - "[em *foo ][em&link bar#1][em *]"); - - MT("userProjectNum", - "foo [link bar/hello#1] world"); - - MT("userProjectNumEmphasis", - "[em *foo ][em&link bar/hello#1][em *]"); - - MT("vanillaLink", - "foo [link http://www.example.com/] bar"); - - MT("vanillaLinkPunctuation", - "foo [link http://www.example.com/]. bar"); - - MT("vanillaLinkExtension", - "foo [link http://www.example.com/index.html] bar"); - - MT("vanillaLinkEmphasis", - "foo [em *][em&link http://www.example.com/index.html][em *] bar"); - - MT("notALink", - "[comment ```css]", - "[tag foo] {[property color]:[keyword black];}", - "[comment ```][link http://www.example.com/]"); - - MT("notALink", - "[comment ``foo `bar` http://www.example.com/``] hello"); - - MT("notALink", - "[comment `foo]", - "[link http://www.example.com/]", - "[comment `foo]", - "", - "[link http://www.example.com/]"); - - MT("headerCodeBlockGithub", - "[header&header-1 # heading]", - "", - "[comment ```]", - "[comment code]", - "[comment ```]", - "", - "Commit: [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2]", - "Issue: [link #1]", - "Link: [link http://www.example.com/]"); - - MT("strikethrough", - "[strikethrough ~~foo~~]"); - - MT("strikethroughWithStartingSpace", - "~~ foo~~"); - - MT("strikethroughUnclosedStrayTildes", - "[strikethrough ~~foo~~~]"); - - MT("strikethroughUnclosedStrayTildes", - "[strikethrough ~~foo ~~]"); - - MT("strikethroughUnclosedStrayTildes", - "[strikethrough ~~foo ~~ bar]"); - - MT("strikethroughUnclosedStrayTildes", - "[strikethrough ~~foo ~~ bar~~]hello"); - - MT("strikethroughOneLetter", - "[strikethrough ~~a~~]"); - - MT("strikethroughWrapped", - "[strikethrough ~~foo]", - "[strikethrough foo~~]"); - - MT("strikethroughParagraph", - "[strikethrough ~~foo]", - "", - "foo[strikethrough ~~bar]"); - - MT("strikethroughEm", - "[strikethrough ~~foo][em&strikethrough *bar*][strikethrough ~~]"); - - MT("strikethroughEm", - "[em *][em&strikethrough ~~foo~~][em *]"); - - MT("strikethroughStrong", - "[strikethrough ~~][strong&strikethrough **foo**][strikethrough ~~]"); - - MT("strikethroughStrong", - "[strong **][strong&strikethrough ~~foo~~][strong **]"); - -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/gherkin/gherkin.js b/shared/html/libs/codemirror/5.0.0/mode/gherkin/gherkin.js deleted file mode 100644 index fc2ebee..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/gherkin/gherkin.js +++ /dev/null @@ -1,178 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* -Gherkin mode - http://www.cukes.info/ -Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues -*/ - -// Following Objs from Brackets implementation: https://github.com/tregusti/brackets-gherkin/blob/master/main.js -//var Quotes = { -// SINGLE: 1, -// DOUBLE: 2 -//}; - -//var regex = { -// keywords: /(Feature| {2}(Scenario|In order to|As|I)| {4}(Given|When|Then|And))/ -//}; - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("gherkin", function () { - return { - startState: function () { - return { - lineNumber: 0, - tableHeaderLine: false, - allowFeature: true, - allowBackground: false, - allowScenario: false, - allowSteps: false, - allowPlaceholders: false, - allowMultilineArgument: false, - inMultilineString: false, - inMultilineTable: false, - inKeywordLine: false - }; - }, - token: function (stream, state) { - if (stream.sol()) { - state.lineNumber++; - state.inKeywordLine = false; - if (state.inMultilineTable) { - state.tableHeaderLine = false; - if (!stream.match(/\s*\|/, false)) { - state.allowMultilineArgument = false; - state.inMultilineTable = false; - } - } - } - - stream.eatSpace(); - - if (state.allowMultilineArgument) { - - // STRING - if (state.inMultilineString) { - if (stream.match('"""')) { - state.inMultilineString = false; - state.allowMultilineArgument = false; - } else { - stream.match(/.*/); - } - return "string"; - } - - // TABLE - if (state.inMultilineTable) { - if (stream.match(/\|\s*/)) { - return "bracket"; - } else { - stream.match(/[^\|]*/); - return state.tableHeaderLine ? "header" : "string"; - } - } - - // DETECT START - if (stream.match('"""')) { - // String - state.inMultilineString = true; - return "string"; - } else if (stream.match("|")) { - // Table - state.inMultilineTable = true; - state.tableHeaderLine = true; - return "bracket"; - } - - } - - // LINE COMMENT - if (stream.match(/#.*/)) { - return "comment"; - - // TAG - } else if (!state.inKeywordLine && stream.match(/@\S+/)) { - return "tag"; - - // FEATURE - } else if (!state.inKeywordLine && state.allowFeature && stream.match(/(機能|功能|フィーチャ|기능|โครงหลัก|ความสามารถ|ความต้องการทางธุรกิจ|ಹೆಚ್ಚಳ|గుణము|ਮੁਹਾਂਦਰਾ|ਨਕਸ਼ ਨੁਹਾਰ|ਖਾਸੀਅਤ|रूप लेख|وِیژگی|خاصية|תכונה|Функціонал|Функция|Функционалност|Функционал|Үзенчәлеклелек|Свойство|Особина|Мөмкинлек|Могућност|Λειτουργία|Δυνατότητα|Właściwość|Vlastnosť|Trajto|Tính năng|Savybė|Pretty much|Požiadavka|Požadavek|Potrzeba biznesowa|Özellik|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Hwæt|Hwaet|Funzionalità|Funktionalitéit|Funktionalität|Funkcja|Funkcionalnost|Funkcionalitāte|Funkcia|Fungsi|Functionaliteit|Funcționalitate|Funcţionalitate|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Fīča|Feature|Eiginleiki|Egenskap|Egenskab|Característica|Caracteristica|Business Need|Aspekt|Arwedd|Ahoy matey!|Ability):/)) { - state.allowScenario = true; - state.allowBackground = true; - state.allowPlaceholders = false; - state.allowSteps = false; - state.allowMultilineArgument = false; - state.inKeywordLine = true; - return "keyword"; - - // BACKGROUND - } else if (!state.inKeywordLine && state.allowBackground && stream.match(/(背景|배경|แนวคิด|ಹಿನ್ನೆಲೆ|నేపథ్యం|ਪਿਛੋਕੜ|पृष्ठभूमि|زمینه|الخلفية|רקע|Тарих|Предыстория|Предистория|Позадина|Передумова|Основа|Контекст|Кереш|Υπόβαθρο|Założenia|Yo\-ho\-ho|Tausta|Taust|Situācija|Rerefons|Pozadina|Pozadie|Pozadí|Osnova|Latar Belakang|Kontext|Konteksts|Kontekstas|Kontekst|Háttér|Hannergrond|Grundlage|Geçmiş|Fundo|Fono|First off|Dis is what went down|Dasar|Contexto|Contexte|Context|Contesto|Cenário de Fundo|Cenario de Fundo|Cefndir|Bối cảnh|Bakgrunnur|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|Ær|Aer|Achtergrond):/)) { - state.allowPlaceholders = false; - state.allowSteps = true; - state.allowBackground = false; - state.allowMultilineArgument = false; - state.inKeywordLine = true; - return "keyword"; - - // SCENARIO OUTLINE - } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景大綱|场景大纲|劇本大綱|剧本大纲|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|시나리오 개요|สรุปเหตุการณ์|โครงสร้างของเหตุการณ์|ವಿವರಣೆ|కథనం|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ|ਪਟਕਥਾ ਢਾਂਚਾ|परिदृश्य रूपरेखा|سيناريو مخطط|الگوی سناریو|תבנית תרחיש|Сценарийның төзелеше|Сценарий структураси|Структура сценарію|Структура сценария|Структура сценарија|Скица|Рамка на сценарий|Концепт|Περιγραφή Σεναρίου|Wharrimean is|Template Situai|Template Senario|Template Keadaan|Tapausaihio|Szenariogrundriss|Szablon scenariusza|Swa hwær swa|Swa hwaer swa|Struktura scenarija|Structură scenariu|Structura scenariu|Skica|Skenario konsep|Shiver me timbers|Senaryo taslağı|Schema dello scenario|Scenariomall|Scenariomal|Scenario Template|Scenario Outline|Scenario Amlinellol|Scenārijs pēc parauga|Scenarijaus šablonas|Reckon it's like|Raamstsenaarium|Plang vum Szenario|Plan du Scénario|Plan du scénario|Osnova scénáře|Osnova Scenára|Náčrt Scenáru|Náčrt Scénáře|Náčrt Scenára|MISHUN SRSLY|Menggariskan Senario|Lýsing Dæma|Lýsing Atburðarásar|Konturo de la scenaro|Koncept|Khung tình huống|Khung kịch bản|Forgatókönyv vázlat|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Esbozo do escenario|Delineação do Cenário|Delineacao do Cenario|All y'all|Abstrakt Scenario|Abstract Scenario):/)) { - state.allowPlaceholders = true; - state.allowSteps = true; - state.allowMultilineArgument = false; - state.inKeywordLine = true; - return "keyword"; - - // EXAMPLES - } else if (state.allowScenario && stream.match(/(例子|例|サンプル|예|ชุดของเหตุการณ์|ชุดของตัวอย่าง|ಉದಾಹರಣೆಗಳು|ఉదాహరణలు|ਉਦਾਹਰਨਾਂ|उदाहरण|نمونه ها|امثلة|דוגמאות|Үрнәкләр|Сценарији|Примеры|Примери|Приклади|Мисоллар|Мисаллар|Σενάρια|Παραδείγματα|You'll wanna|Voorbeelden|Variantai|Tapaukset|Se þe|Se the|Se ðe|Scenarios|Scenariji|Scenarijai|Przykłady|Primjeri|Primeri|Příklady|Príklady|Piemēri|Példák|Pavyzdžiai|Paraugs|Örnekler|Juhtumid|Exemplos|Exemples|Exemple|Exempel|EXAMPLZ|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|Dữ liệu|Dead men tell no tales|Dæmi|Contoh|Cenários|Cenarios|Beispiller|Beispiele|Atburðarásir):/)) { - state.allowPlaceholders = false; - state.allowSteps = true; - state.allowBackground = false; - state.allowMultilineArgument = true; - return "keyword"; - - // SCENARIO - } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景|场景|劇本|剧本|シナリオ|시나리오|เหตุการณ์|ಕಥಾಸಾರಾಂಶ|సన్నివేశం|ਪਟਕਥਾ|परिदृश्य|سيناريو|سناریو|תרחיש|Сценарій|Сценарио|Сценарий|Пример|Σενάριο|Tình huống|The thing of it is|Tapaus|Szenario|Swa|Stsenaarium|Skenario|Situai|Senaryo|Senario|Scenaro|Scenariusz|Scenariu|Scénario|Scenario|Scenarijus|Scenārijs|Scenarij|Scenarie|Scénář|Scenár|Primer|MISHUN|Kịch bản|Keadaan|Heave to|Forgatókönyv|Escenario|Escenari|Cenário|Cenario|Awww, look mate|Atburðarás):/)) { - state.allowPlaceholders = false; - state.allowSteps = true; - state.allowBackground = false; - state.allowMultilineArgument = false; - state.inKeywordLine = true; - return "keyword"; - - // STEPS - } else if (!state.inKeywordLine && state.allowSteps && stream.match(/(那麼|那么|而且|當|当|并且|同時|同时|前提|假设|假設|假定|假如|但是|但し|並且|もし|ならば|ただし|しかし|かつ|하지만|조건|먼저|만일|만약|단|그리고|그러면|และ |เมื่อ |แต่ |ดังนั้น |กำหนดให้ |ಸ್ಥಿತಿಯನ್ನು |ಮತ್ತು |ನೀಡಿದ |ನಂತರ |ಆದರೆ |మరియు |చెప్పబడినది |కాని |ఈ పరిస్థితిలో |అప్పుడు |ਪਰ |ਤਦ |ਜੇਕਰ |ਜਿਵੇਂ ਕਿ |ਜਦੋਂ |ਅਤੇ |यदि |परन्तु |पर |तब |तदा |तथा |जब |चूंकि |किन्तु |कदा |और |अगर |و |هنگامی |متى |لكن |عندما |ثم |بفرض |با فرض |اما |اذاً |آنگاه |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Һәм |Унда |Тоді |Тогда |То |Также |Та |Пусть |Припустимо, що |Припустимо |Онда |Но |Нехай |Нәтиҗәдә |Лекин |Ләкин |Коли |Когда |Когато |Када |Кад |К тому же |І |И |Задато |Задати |Задате |Если |Допустим |Дано |Дадено |Вә |Ва |Бирок |Әмма |Әйтик |Әгәр |Аммо |Али |Але |Агар |А також |А |Τότε |Όταν |Και |Δεδομένου |Αλλά |Þurh |Þegar |Þa þe |Þá |Þa |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Za předpokladu |Za predpokladu |Youse know when youse got |Youse know like when |Yna |Yeah nah |Y'know |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |wann |Ve |Và |Und |Un |ugeholl |Too right |Thurh |Thì |Then y'all |Then |Tha the |Tha |Tetapi |Tapi |Tak |Tada |Tad |Stel |Soit |Siis |Și |Şi |Si |Sed |Se |Så |Quando |Quand |Quan |Pryd |Potom |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Niin |Nhưng |När |Når |Mutta |Men |Mas |Maka |Majd |Mając |Mais |Maar |mä |Ma |Lorsque |Lorsqu'|Logo |Let go and haul |Kun |Kuid |Kui |Kiedy |Khi |Ketika |Kemudian |Keď |Když |Kaj |Kai |Kada |Kad |Jeżeli |Jeśli |Ja |It's just unbelievable |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben seien |Gegeben sei |Gdy |Gangway! |Fakat |Étant donnés |Etant donnés |Étant données |Etant données |Étant donnée |Etant donnée |Étant donné |Etant donné |Et |És |Entonces |Entón |Então |Entao |En |Eğer ki |Ef |Eeldades |E |Ðurh |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Diberi |Dengan |Den youse gotta |DEN |De |Dato |Dați fiind |Daţi fiind |Dati fiind |Dati |Date fiind |Date |Data |Dat fiind |Dar |Dann |dann |Dan |Dados |Dado |Dadas |Dada |Ða ðe |Ða |Cuando |Cho |Cando |Când |Cand |Cal |But y'all |But at the end of the day I reckon |BUT |But |Buh |Blimey! |Biết |Bet |Bagi |Aye |awer |Avast! |Atunci |Atesa |Atès |Apabila |Anrhegedig a |Angenommen |And y'all |And |AN |An |an |Amikor |Amennyiben |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Ak |Adott |Ac |Aber |A zároveň |A tiež |A taktiež |A také |A |a |7 |\* )/)) { - state.inStep = true; - state.allowPlaceholders = true; - state.allowMultilineArgument = true; - state.inKeywordLine = true; - return "keyword"; - - // INLINE STRING - } else if (stream.match(/"[^"]*"?/)) { - return "string"; - - // PLACEHOLDER - } else if (state.allowPlaceholders && stream.match(/<[^>]*>?/)) { - return "variable"; - - // Fall through - } else { - stream.next(); - stream.eatWhile(/[^@"<#]/); - return null; - } - } - }; -}); - -CodeMirror.defineMIME("text/x-feature", "gherkin"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/gherkin/index.html b/shared/html/libs/codemirror/5.0.0/mode/gherkin/index.html deleted file mode 100644 index af8184c..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/gherkin/index.html +++ /dev/null @@ -1,48 +0,0 @@ - - -CodeMirror: Gherkin mode - - - - - - - - - -
-

Gherkin mode

-
- - -

MIME types defined: text/x-feature.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/go/go.js b/shared/html/libs/codemirror/5.0.0/mode/go/go.js deleted file mode 100644 index b121f4e..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/go/go.js +++ /dev/null @@ -1,185 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("go", function(config) { - var indentUnit = config.indentUnit; - - var keywords = { - "break":true, "case":true, "chan":true, "const":true, "continue":true, - "default":true, "defer":true, "else":true, "fallthrough":true, "for":true, - "func":true, "go":true, "goto":true, "if":true, "import":true, - "interface":true, "map":true, "package":true, "range":true, "return":true, - "select":true, "struct":true, "switch":true, "type":true, "var":true, - "bool":true, "byte":true, "complex64":true, "complex128":true, - "float32":true, "float64":true, "int8":true, "int16":true, "int32":true, - "int64":true, "string":true, "uint8":true, "uint16":true, "uint32":true, - "uint64":true, "int":true, "uint":true, "uintptr":true - }; - - var atoms = { - "true":true, "false":true, "iota":true, "nil":true, "append":true, - "cap":true, "close":true, "complex":true, "copy":true, "imag":true, - "len":true, "make":true, "new":true, "panic":true, "print":true, - "println":true, "real":true, "recover":true - }; - - var isOperatorChar = /[+\-*&^%:=<>!|\/]/; - - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'" || ch == "`") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\d\.]/.test(ch)) { - if (ch == ".") { - stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/); - } else if (ch == "0") { - stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/); - } else { - stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/); - } - return "number"; - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) { - if (cur == "case" || cur == "default") curPunc = "case"; - return "keyword"; - } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || quote == "`")) - state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - function popContext(state) { - if (!state.context.prev) return; - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - if (ctx.type == "case") ctx.type = "}"; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment") return style; - if (ctx.align == null) ctx.align = true; - - if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "case") ctx.type = "case"; - else if (curPunc == "}" && ctx.type == "}") ctx = popContext(state); - else if (curPunc == ctx.type) popContext(state); - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return 0; - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) { - state.context.type = "}"; - return ctx.indented; - } - var closing = firstChar == ctx.type; - if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "{}):", - fold: "brace", - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//" - }; -}); - -CodeMirror.defineMIME("text/x-go", "go"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/go/index.html b/shared/html/libs/codemirror/5.0.0/mode/go/index.html deleted file mode 100644 index 72e3b36..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/go/index.html +++ /dev/null @@ -1,85 +0,0 @@ - - -CodeMirror: Go mode - - - - - - - - - - - -
-

Go mode

-
- - - -

MIME type: text/x-go

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/groovy/groovy.js b/shared/html/libs/codemirror/5.0.0/mode/groovy/groovy.js deleted file mode 100644 index 89b8224..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/groovy/groovy.js +++ /dev/null @@ -1,226 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("groovy", function(config) { - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var keywords = words( - "abstract as assert boolean break byte case catch char class const continue def default " + - "do double else enum extends final finally float for goto if implements import in " + - "instanceof int interface long native new package private protected public return " + - "short static strictfp super switch synchronized threadsafe throw throws transient " + - "try void volatile while"); - var blockKeywords = words("catch class do else finally for if switch try while enum interface def"); - var atoms = words("null true false this"); - - var curPunc; - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") { - return startString(ch, stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - if (stream.eat(/eE/)) { stream.eat(/\+\-/); stream.eatWhile(/\d/); } - return "number"; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize.push(tokenComment); - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - if (expectExpression(state.lastToken)) { - return startString(ch, stream, state); - } - } - if (ch == "-" && stream.eat(">")) { - curPunc = "->"; - return null; - } - if (/[+\-*&%=<>!?|\/~]/.test(ch)) { - stream.eatWhile(/[+\-*&%=<>|~]/); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - if (ch == "@") { stream.eatWhile(/[\w\$_\.]/); return "meta"; } - if (state.lastToken == ".") return "property"; - if (stream.eat(":")) { curPunc = "proplabel"; return "property"; } - var cur = stream.current(); - if (atoms.propertyIsEnumerable(cur)) { return "atom"; } - if (keywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; - } - return "variable"; - } - tokenBase.isBase = true; - - function startString(quote, stream, state) { - var tripleQuoted = false; - if (quote != "/" && stream.eat(quote)) { - if (stream.eat(quote)) tripleQuoted = true; - else return "string"; - } - function t(stream, state) { - var escaped = false, next, end = !tripleQuoted; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) { - if (!tripleQuoted) { break; } - if (stream.match(quote + quote)) { end = true; break; } - } - if (quote == '"' && next == "$" && !escaped && stream.eat("{")) { - state.tokenize.push(tokenBaseUntilBrace()); - return "string"; - } - escaped = !escaped && next == "\\"; - } - if (end) state.tokenize.pop(); - return "string"; - } - state.tokenize.push(t); - return t(stream, state); - } - - function tokenBaseUntilBrace() { - var depth = 1; - function t(stream, state) { - if (stream.peek() == "}") { - depth--; - if (depth == 0) { - state.tokenize.pop(); - return state.tokenize[state.tokenize.length-1](stream, state); - } - } else if (stream.peek() == "{") { - depth++; - } - return tokenBase(stream, state); - } - t.isBase = true; - return t; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize.pop(); - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function expectExpression(last) { - return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) || - last == "newstatement" || last == "keyword" || last == "proplabel"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: [tokenBase], - context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false), - indented: 0, - startOfLine: true, - lastToken: null - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - // Automatic semicolon insertion - if (ctx.type == "statement" && !expectExpression(state.lastToken)) { - popContext(state); ctx = state.context; - } - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = state.tokenize[state.tokenize.length-1](stream, state); - if (style == "comment") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state); - // Handle indentation for {x -> \n ... } - else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") { - popContext(state); - state.context.align = false; - } - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - state.lastToken = curPunc || style; - return style; - }, - - indent: function(state, textAfter) { - if (!state.tokenize[state.tokenize.length-1].isBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), ctx = state.context; - if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev; - var closing = firstChar == ctx.type; - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : config.indentUnit); - }, - - electricChars: "{}", - fold: "brace" - }; -}); - -CodeMirror.defineMIME("text/x-groovy", "groovy"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/groovy/index.html b/shared/html/libs/codemirror/5.0.0/mode/groovy/index.html deleted file mode 100644 index bb0df07..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/groovy/index.html +++ /dev/null @@ -1,84 +0,0 @@ - - -CodeMirror: Groovy mode - - - - - - - - - - -
-

Groovy mode

-
- - - -

MIME types defined: text/x-groovy

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/haml/haml.js b/shared/html/libs/codemirror/5.0.0/mode/haml/haml.js deleted file mode 100644 index 8fe63b0..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/haml/haml.js +++ /dev/null @@ -1,159 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - - // full haml mode. This handled embeded ruby and html fragments too - CodeMirror.defineMode("haml", function(config) { - var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"}); - var rubyMode = CodeMirror.getMode(config, "ruby"); - - function rubyInQuote(endQuote) { - return function(stream, state) { - var ch = stream.peek(); - if (ch == endQuote && state.rubyState.tokenize.length == 1) { - // step out of ruby context as it seems to complete processing all the braces - stream.next(); - state.tokenize = html; - return "closeAttributeTag"; - } else { - return ruby(stream, state); - } - }; - } - - function ruby(stream, state) { - if (stream.match("-#")) { - stream.skipToEnd(); - return "comment"; - } - return rubyMode.token(stream, state.rubyState); - } - - function html(stream, state) { - var ch = stream.peek(); - - // handle haml declarations. All declarations that cant be handled here - // will be passed to html mode - if (state.previousToken.style == "comment" ) { - if (state.indented > state.previousToken.indented) { - stream.skipToEnd(); - return "commentLine"; - } - } - - if (state.startOfLine) { - if (ch == "!" && stream.match("!!")) { - stream.skipToEnd(); - return "tag"; - } else if (stream.match(/^%[\w:#\.]+=/)) { - state.tokenize = ruby; - return "hamlTag"; - } else if (stream.match(/^%[\w:]+/)) { - return "hamlTag"; - } else if (ch == "/" ) { - stream.skipToEnd(); - return "comment"; - } - } - - if (state.startOfLine || state.previousToken.style == "hamlTag") { - if ( ch == "#" || ch == ".") { - stream.match(/[\w-#\.]*/); - return "hamlAttribute"; - } - } - - // donot handle --> as valid ruby, make it HTML close comment instead - if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) { - state.tokenize = ruby; - return state.tokenize(stream, state); - } - - if (state.previousToken.style == "hamlTag" || - state.previousToken.style == "closeAttributeTag" || - state.previousToken.style == "hamlAttribute") { - if (ch == "(") { - state.tokenize = rubyInQuote(")"); - return state.tokenize(stream, state); - } else if (ch == "{") { - state.tokenize = rubyInQuote("}"); - return state.tokenize(stream, state); - } - } - - return htmlMode.token(stream, state.htmlState); - } - - return { - // default to html mode - startState: function() { - var htmlState = htmlMode.startState(); - var rubyState = rubyMode.startState(); - return { - htmlState: htmlState, - rubyState: rubyState, - indented: 0, - previousToken: { style: null, indented: 0}, - tokenize: html - }; - }, - - copyState: function(state) { - return { - htmlState : CodeMirror.copyState(htmlMode, state.htmlState), - rubyState: CodeMirror.copyState(rubyMode, state.rubyState), - indented: state.indented, - previousToken: state.previousToken, - tokenize: state.tokenize - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - state.startOfLine = false; - // dont record comment line as we only want to measure comment line with - // the opening comment block - if (style && style != "commentLine") { - state.previousToken = { style: style, indented: state.indented }; - } - // if current state is ruby and the previous token is not `,` reset the - // tokenize to html - if (stream.eol() && state.tokenize == ruby) { - stream.backUp(1); - var ch = stream.peek(); - stream.next(); - if (ch && ch != ",") { - state.tokenize = html; - } - } - // reprocess some of the specific style tag when finish setting previousToken - if (style == "hamlTag") { - style = "tag"; - } else if (style == "commentLine") { - style = "comment"; - } else if (style == "hamlAttribute") { - style = "attribute"; - } else if (style == "closeAttributeTag") { - style = null; - } - return style; - } - }; - }, "htmlmixed", "ruby"); - - CodeMirror.defineMIME("text/x-haml", "haml"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/haml/index.html b/shared/html/libs/codemirror/5.0.0/mode/haml/index.html deleted file mode 100644 index 2894a93..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/haml/index.html +++ /dev/null @@ -1,79 +0,0 @@ - - -CodeMirror: HAML mode - - - - - - - - - - - - - -
-

HAML mode

-
- - -

MIME types defined: text/x-haml.

- -

Parsing/Highlighting Tests: normal, verbose.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/haml/test.js b/shared/html/libs/codemirror/5.0.0/mode/haml/test.js deleted file mode 100644 index 508458a..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/haml/test.js +++ /dev/null @@ -1,97 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "haml"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - // Requires at least one media query - MT("elementName", - "[tag %h1] Hey There"); - - MT("oneElementPerLine", - "[tag %h1] Hey There %h2"); - - MT("idSelector", - "[tag %h1][attribute #test] Hey There"); - - MT("classSelector", - "[tag %h1][attribute .hello] Hey There"); - - MT("docType", - "[tag !!! XML]"); - - MT("comment", - "[comment / Hello WORLD]"); - - MT("notComment", - "[tag %h1] This is not a / comment "); - - MT("attributes", - "[tag %a]([variable title][operator =][string \"test\"]){[atom :title] [operator =>] [string \"test\"]}"); - - MT("htmlCode", - "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket ]"); - - MT("rubyBlock", - "[operator =][variable-2 @item]"); - - MT("selectorRubyBlock", - "[tag %a.selector=] [variable-2 @item]"); - - MT("nestedRubyBlock", - "[tag %a]", - " [operator =][variable puts] [string \"test\"]"); - - MT("multilinePlaintext", - "[tag %p]", - " Hello,", - " World"); - - MT("multilineRuby", - "[tag %p]", - " [comment -# this is a comment]", - " [comment and this is a comment too]", - " Date/Time", - " [operator -] [variable now] [operator =] [tag DateTime][operator .][property now]", - " [tag %strong=] [variable now]", - " [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])", - " [operator =][string \"Happy\"]", - " [operator =][string \"Belated\"]", - " [operator =][string \"Birthday\"]"); - - MT("multilineComment", - "[comment /]", - " [comment Multiline]", - " [comment Comment]"); - - MT("hamlComment", - "[comment -# this is a comment]"); - - MT("multilineHamlComment", - "[comment -# this is a comment]", - " [comment and this is a comment too]"); - - MT("multilineHTMLComment", - "[comment ]"); - - MT("hamlAfterRubyTag", - "[attribute .block]", - " [tag %strong=] [variable now]", - " [attribute .test]", - " [operator =][variable now]", - " [attribute .right]"); - - MT("stretchedRuby", - "[operator =] [variable puts] [string \"Hello\"],", - " [string \"World\"]"); - - MT("interpolationInHashAttribute", - //"[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test"); - "[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test"); - - MT("interpolationInHTMLAttribute", - "[tag %div]([variable title][operator =][string \"#{][variable test][string }_#{][variable ting]()[string }\"]) Test"); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/haskell/haskell.js b/shared/html/libs/codemirror/5.0.0/mode/haskell/haskell.js deleted file mode 100644 index fe0bab6..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/haskell/haskell.js +++ /dev/null @@ -1,267 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("haskell", function(_config, modeConfig) { - - function switchState(source, setState, f) { - setState(f); - return f(source, setState); - } - - // These should all be Unicode extended, as per the Haskell 2010 report - var smallRE = /[a-z_]/; - var largeRE = /[A-Z]/; - var digitRE = /\d/; - var hexitRE = /[0-9A-Fa-f]/; - var octitRE = /[0-7]/; - var idRE = /[a-z_A-Z0-9'\xa1-\uffff]/; - var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/; - var specialRE = /[(),;[\]`{}]/; - var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer - - function normal(source, setState) { - if (source.eatWhile(whiteCharRE)) { - return null; - } - - var ch = source.next(); - if (specialRE.test(ch)) { - if (ch == '{' && source.eat('-')) { - var t = "comment"; - if (source.eat('#')) { - t = "meta"; - } - return switchState(source, setState, ncomment(t, 1)); - } - return null; - } - - if (ch == '\'') { - if (source.eat('\\')) { - source.next(); // should handle other escapes here - } - else { - source.next(); - } - if (source.eat('\'')) { - return "string"; - } - return "error"; - } - - if (ch == '"') { - return switchState(source, setState, stringLiteral); - } - - if (largeRE.test(ch)) { - source.eatWhile(idRE); - if (source.eat('.')) { - return "qualifier"; - } - return "variable-2"; - } - - if (smallRE.test(ch)) { - source.eatWhile(idRE); - return "variable"; - } - - if (digitRE.test(ch)) { - if (ch == '0') { - if (source.eat(/[xX]/)) { - source.eatWhile(hexitRE); // should require at least 1 - return "integer"; - } - if (source.eat(/[oO]/)) { - source.eatWhile(octitRE); // should require at least 1 - return "number"; - } - } - source.eatWhile(digitRE); - var t = "number"; - if (source.match(/^\.\d+/)) { - t = "number"; - } - if (source.eat(/[eE]/)) { - t = "number"; - source.eat(/[-+]/); - source.eatWhile(digitRE); // should require at least 1 - } - return t; - } - - if (ch == "." && source.eat(".")) - return "keyword"; - - if (symbolRE.test(ch)) { - if (ch == '-' && source.eat(/-/)) { - source.eatWhile(/-/); - if (!source.eat(symbolRE)) { - source.skipToEnd(); - return "comment"; - } - } - var t = "variable"; - if (ch == ':') { - t = "variable-2"; - } - source.eatWhile(symbolRE); - return t; - } - - return "error"; - } - - function ncomment(type, nest) { - if (nest == 0) { - return normal; - } - return function(source, setState) { - var currNest = nest; - while (!source.eol()) { - var ch = source.next(); - if (ch == '{' && source.eat('-')) { - ++currNest; - } - else if (ch == '-' && source.eat('}')) { - --currNest; - if (currNest == 0) { - setState(normal); - return type; - } - } - } - setState(ncomment(type, currNest)); - return type; - }; - } - - function stringLiteral(source, setState) { - while (!source.eol()) { - var ch = source.next(); - if (ch == '"') { - setState(normal); - return "string"; - } - if (ch == '\\') { - if (source.eol() || source.eat(whiteCharRE)) { - setState(stringGap); - return "string"; - } - if (source.eat('&')) { - } - else { - source.next(); // should handle other escapes here - } - } - } - setState(normal); - return "error"; - } - - function stringGap(source, setState) { - if (source.eat('\\')) { - return switchState(source, setState, stringLiteral); - } - source.next(); - setState(normal); - return "error"; - } - - - var wellKnownWords = (function() { - var wkw = {}; - function setType(t) { - return function () { - for (var i = 0; i < arguments.length; i++) - wkw[arguments[i]] = t; - }; - } - - setType("keyword")( - "case", "class", "data", "default", "deriving", "do", "else", "foreign", - "if", "import", "in", "infix", "infixl", "infixr", "instance", "let", - "module", "newtype", "of", "then", "type", "where", "_"); - - setType("keyword")( - "\.\.", ":", "::", "=", "\\", "\"", "<-", "->", "@", "~", "=>"); - - setType("builtin")( - "!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<=", "=<<", - "==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", "**"); - - setType("builtin")( - "Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", "Eq", - "False", "FilePath", "Float", "Floating", "Fractional", "Functor", "GT", - "IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left", - "Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read", - "ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS", - "String", "True"); - - setType("builtin")( - "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf", - "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling", - "compare", "concat", "concatMap", "const", "cos", "cosh", "curry", - "cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either", - "elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo", - "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter", - "flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap", - "foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger", - "fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents", - "getLine", "head", "id", "init", "interact", "ioError", "isDenormalized", - "isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last", - "lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map", - "mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound", - "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or", - "otherwise", "pi", "pred", "print", "product", "properFraction", - "putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile", - "readIO", "readList", "readLn", "readParen", "reads", "readsPrec", - "realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse", - "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", - "sequence", "sequence_", "show", "showChar", "showList", "showParen", - "showString", "shows", "showsPrec", "significand", "signum", "sin", - "sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum", - "tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger", - "toRational", "truncate", "uncurry", "undefined", "unlines", "until", - "unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip", - "zip3", "zipWith", "zipWith3"); - - var override = modeConfig.overrideKeywords; - if (override) for (var word in override) if (override.hasOwnProperty(word)) - wkw[word] = override[word]; - - return wkw; - })(); - - - - return { - startState: function () { return { f: normal }; }, - copyState: function (s) { return { f: s.f }; }, - - token: function(stream, state) { - var t = state.f(stream, function(s) { state.f = s; }); - var w = stream.current(); - return wellKnownWords.hasOwnProperty(w) ? wellKnownWords[w] : t; - }, - - blockCommentStart: "{-", - blockCommentEnd: "-}", - lineComment: "--" - }; - -}); - -CodeMirror.defineMIME("text/x-haskell", "haskell"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/haskell/index.html b/shared/html/libs/codemirror/5.0.0/mode/haskell/index.html deleted file mode 100644 index 42240b0..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/haskell/index.html +++ /dev/null @@ -1,73 +0,0 @@ - - -CodeMirror: Haskell mode - - - - - - - - - - - -
-

Haskell mode

-
- - - -

MIME types defined: text/x-haskell.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/haxe/haxe.js b/shared/html/libs/codemirror/5.0.0/mode/haxe/haxe.js deleted file mode 100644 index d49ad70..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/haxe/haxe.js +++ /dev/null @@ -1,518 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("haxe", function(config, parserConfig) { - var indentUnit = config.indentUnit; - - // Tokenizer - - var keywords = function(){ - function kw(type) {return {type: type, style: "keyword"};} - var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); - var operator = kw("operator"), atom = {type: "atom", style: "atom"}, attribute = {type:"attribute", style: "attribute"}; - var type = kw("typedef"); - return { - "if": A, "while": A, "else": B, "do": B, "try": B, - "return": C, "break": C, "continue": C, "new": C, "throw": C, - "var": kw("var"), "inline":attribute, "static": attribute, "using":kw("import"), - "public": attribute, "private": attribute, "cast": kw("cast"), "import": kw("import"), "macro": kw("macro"), - "function": kw("function"), "catch": kw("catch"), "untyped": kw("untyped"), "callback": kw("cb"), - "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), - "in": operator, "never": kw("property_access"), "trace":kw("trace"), - "class": type, "abstract":type, "enum":type, "interface":type, "typedef":type, "extends":type, "implements":type, "dynamic":type, - "true": atom, "false": atom, "null": atom - }; - }(); - - var isOperatorChar = /[+\-*&%=<>!?|]/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - function nextUntilUnescaped(stream, end) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (next == end && !escaped) - return false; - escaped = !escaped && next == "\\"; - } - return escaped; - } - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - function ret(tp, style, cont) { - type = tp; content = cont; - return style; - } - - function haxeTokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") - return chain(stream, state, haxeTokenString(ch)); - else if (/[\[\]{}\(\),;\:\.]/.test(ch)) - return ret(ch); - else if (ch == "0" && stream.eat(/x/i)) { - stream.eatWhile(/[\da-f]/i); - return ret("number", "number"); - } - else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) { - stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); - return ret("number", "number"); - } - else if (state.reAllowed && (ch == "~" && stream.eat(/\//))) { - nextUntilUnescaped(stream, "/"); - stream.eatWhile(/[gimsu]/); - return ret("regexp", "string-2"); - } - else if (ch == "/") { - if (stream.eat("*")) { - return chain(stream, state, haxeTokenComment); - } - else if (stream.eat("/")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } - else { - stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); - } - } - else if (ch == "#") { - stream.skipToEnd(); - return ret("conditional", "meta"); - } - else if (ch == "@") { - stream.eat(/:/); - stream.eatWhile(/[\w_]/); - return ret ("metadata", "meta"); - } - else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); - } - else { - var word; - if(/[A-Z]/.test(ch)) - { - stream.eatWhile(/[\w_<>]/); - word = stream.current(); - return ret("type", "variable-3", word); - } - else - { - stream.eatWhile(/[\w_]/); - var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; - return (known && state.kwAllowed) ? ret(known.type, known.style, word) : - ret("variable", "variable", word); - } - } - } - - function haxeTokenString(quote) { - return function(stream, state) { - if (!nextUntilUnescaped(stream, quote)) - state.tokenize = haxeTokenBase; - return ret("string", "string"); - }; - } - - function haxeTokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = haxeTokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - // Parser - - var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true}; - - function HaxeLexical(indented, column, type, align, prev, info) { - this.indented = indented; - this.column = column; - this.type = type; - this.prev = prev; - this.info = info; - if (align != null) this.align = align; - } - - function inScope(state, varname) { - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return true; - } - - function parseHaxe(state, style, type, content, stream) { - var cc = state.cc; - // Communicate our context to the combinators. - // (Less wasteful than consing up a hundred closures on every call.) - cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; - - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - - while(true) { - var combinator = cc.length ? cc.pop() : statement; - if (combinator(type, content)) { - while(cc.length && cc[cc.length - 1].lex) - cc.pop()(); - if (cx.marked) return cx.marked; - if (type == "variable" && inScope(state, content)) return "variable-2"; - if (type == "variable" && imported(state, content)) return "variable-3"; - return style; - } - } - } - - function imported(state, typename) - { - if (/[a-z]/.test(typename.charAt(0))) - return false; - var len = state.importedtypes.length; - for (var i = 0; i= 0; i--) cx.cc.push(arguments[i]); - } - function cont() { - pass.apply(null, arguments); - return true; - } - function register(varname) { - var state = cx.state; - if (state.context) { - cx.marked = "def"; - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return; - state.localVars = {name: varname, next: state.localVars}; - } - } - - // Combinators - - var defaultVars = {name: "this", next: null}; - function pushcontext() { - if (!cx.state.context) cx.state.localVars = defaultVars; - cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; - } - function popcontext() { - cx.state.localVars = cx.state.context.vars; - cx.state.context = cx.state.context.prev; - } - function pushlex(type, info) { - var result = function() { - var state = cx.state; - state.lexical = new HaxeLexical(state.indented, cx.stream.column(), type, null, state.lexical, info); - }; - result.lex = true; - return result; - } - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type == ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - poplex.lex = true; - - function expect(wanted) { - function f(type) { - if (type == wanted) return cont(); - else if (wanted == ";") return pass(); - else return cont(f); - }; - return f; - } - - function statement(type) { - if (type == "@") return cont(metadef); - if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex); - if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); - if (type == "keyword b") return cont(pushlex("form"), statement, poplex); - if (type == "{") return cont(pushlex("}"), pushcontext, block, poplex, popcontext); - if (type == ";") return cont(); - if (type == "attribute") return cont(maybeattribute); - if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), - poplex, statement, poplex); - if (type == "variable") return cont(pushlex("stat"), maybelabel); - if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), - block, poplex, poplex); - if (type == "case") return cont(expression, expect(":")); - if (type == "default") return cont(expect(":")); - if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), - statement, poplex, popcontext); - if (type == "import") return cont(importdef, expect(";")); - if (type == "typedef") return cont(typedef); - return pass(pushlex("stat"), expression, expect(";"), poplex); - } - function expression(type) { - if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator); - if (type == "function") return cont(functiondef); - if (type == "keyword c") return cont(maybeexpression); - if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator); - if (type == "operator") return cont(expression); - if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator); - if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator); - return cont(); - } - function maybeexpression(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expression); - } - - function maybeoperator(type, value) { - if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator); - if (type == "operator" || type == ":") return cont(expression); - if (type == ";") return; - if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator); - if (type == ".") return cont(property, maybeoperator); - if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); - } - - function maybeattribute(type) { - if (type == "attribute") return cont(maybeattribute); - if (type == "function") return cont(functiondef); - if (type == "var") return cont(vardef1); - } - - function metadef(type) { - if(type == ":") return cont(metadef); - if(type == "variable") return cont(metadef); - if(type == "(") return cont(pushlex(")"), commasep(metaargs, ")"), poplex, statement); - } - function metaargs(type) { - if(type == "variable") return cont(); - } - - function importdef (type, value) { - if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); } - else if(type == "variable" || type == "property" || type == "." || value == "*") return cont(importdef); - } - - function typedef (type, value) - { - if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); } - else if (type == "type" && /[A-Z]/.test(value.charAt(0))) { return cont(); } - } - - function maybelabel(type) { - if (type == ":") return cont(poplex, statement); - return pass(maybeoperator, expect(";"), poplex); - } - function property(type) { - if (type == "variable") {cx.marked = "property"; return cont();} - } - function objprop(type) { - if (type == "variable") cx.marked = "property"; - if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression); - } - function commasep(what, end) { - function proceed(type) { - if (type == ",") return cont(what, proceed); - if (type == end) return cont(); - return cont(expect(end)); - } - return function(type) { - if (type == end) return cont(); - else return pass(what, proceed); - }; - } - function block(type) { - if (type == "}") return cont(); - return pass(statement, block); - } - function vardef1(type, value) { - if (type == "variable"){register(value); return cont(typeuse, vardef2);} - return cont(); - } - function vardef2(type, value) { - if (value == "=") return cont(expression, vardef2); - if (type == ",") return cont(vardef1); - } - function forspec1(type, value) { - if (type == "variable") { - register(value); - } - return cont(pushlex(")"), pushcontext, forin, expression, poplex, statement, popcontext); - } - function forin(_type, value) { - if (value == "in") return cont(); - } - function functiondef(type, value) { - if (type == "variable") {register(value); return cont(functiondef);} - if (value == "new") return cont(functiondef); - if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, typeuse, statement, popcontext); - } - function typeuse(type) { - if(type == ":") return cont(typestring); - } - function typestring(type) { - if(type == "type") return cont(); - if(type == "variable") return cont(); - if(type == "{") return cont(pushlex("}"), commasep(typeprop, "}"), poplex); - } - function typeprop(type) { - if(type == "variable") return cont(typeuse); - } - function funarg(type, value) { - if (type == "variable") {register(value); return cont(typeuse);} - } - - // Interface - - return { - startState: function(basecolumn) { - var defaulttypes = ["Int", "Float", "String", "Void", "Std", "Bool", "Dynamic", "Array"]; - return { - tokenize: haxeTokenBase, - reAllowed: true, - kwAllowed: true, - cc: [], - lexical: new HaxeLexical((basecolumn || 0) - indentUnit, 0, "block", false), - localVars: parserConfig.localVars, - importedtypes: defaulttypes, - context: parserConfig.localVars && {vars: parserConfig.localVars}, - indented: 0 - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (type == "comment") return style; - state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/)); - state.kwAllowed = type != '.'; - return parseHaxe(state, style, type, content, stream); - }, - - indent: function(state, textAfter) { - if (state.tokenize != haxeTokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; - if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; - var type = lexical.type, closing = firstChar == type; - if (type == "vardef") return lexical.indented + 4; - else if (type == "form" && firstChar == "{") return lexical.indented; - else if (type == "stat" || type == "form") return lexical.indented + indentUnit; - else if (lexical.info == "switch" && !closing) - return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); - else if (lexical.align) return lexical.column + (closing ? 0 : 1); - else return lexical.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "{}", - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//" - }; -}); - -CodeMirror.defineMIME("text/x-haxe", "haxe"); - -CodeMirror.defineMode("hxml", function () { - - return { - startState: function () { - return { - define: false, - inString: false - }; - }, - token: function (stream, state) { - var ch = stream.peek(); - var sol = stream.sol(); - - ///* comments */ - if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - if (sol && ch == "-") { - var style = "variable-2"; - - stream.eat(/-/); - - if (stream.peek() == "-") { - stream.eat(/-/); - style = "keyword a"; - } - - if (stream.peek() == "D") { - stream.eat(/[D]/); - style = "keyword c"; - state.define = true; - } - - stream.eatWhile(/[A-Z]/i); - return style; - } - - var ch = stream.peek(); - - if (state.inString == false && ch == "'") { - state.inString = true; - ch = stream.next(); - } - - if (state.inString == true) { - if (stream.skipTo("'")) { - - } else { - stream.skipToEnd(); - } - - if (stream.peek() == "'") { - stream.next(); - state.inString = false; - } - - return "string"; - } - - stream.next(); - return null; - }, - lineComment: "#" - }; -}); - -CodeMirror.defineMIME("text/x-hxml", "hxml"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/haxe/index.html b/shared/html/libs/codemirror/5.0.0/mode/haxe/index.html deleted file mode 100644 index d415b5e..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/haxe/index.html +++ /dev/null @@ -1,124 +0,0 @@ - - -CodeMirror: Haxe mode - - - - - - - - - -
-

Haxe mode

- - -

- -

Hxml mode:

- -

-
- - - -

MIME types defined: text/x-haxe, text/x-hxml.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/htmlembedded/htmlembedded.js b/shared/html/libs/codemirror/5.0.0/mode/htmlembedded/htmlembedded.js deleted file mode 100644 index e8f7ba8..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/htmlembedded/htmlembedded.js +++ /dev/null @@ -1,86 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("htmlembedded", function(config, parserConfig) { - - //config settings - var scriptStartRegex = parserConfig.scriptStartRegex || /^<%/i, - scriptEndRegex = parserConfig.scriptEndRegex || /^%>/i; - - //inner modes - var scriptingMode, htmlMixedMode; - - //tokenizer when in html mode - function htmlDispatch(stream, state) { - if (stream.match(scriptStartRegex, false)) { - state.token=scriptingDispatch; - return scriptingMode.token(stream, state.scriptState); - } - else - return htmlMixedMode.token(stream, state.htmlState); - } - - //tokenizer when in scripting mode - function scriptingDispatch(stream, state) { - if (stream.match(scriptEndRegex, false)) { - state.token=htmlDispatch; - return htmlMixedMode.token(stream, state.htmlState); - } - else - return scriptingMode.token(stream, state.scriptState); - } - - - return { - startState: function() { - scriptingMode = scriptingMode || CodeMirror.getMode(config, parserConfig.scriptingModeSpec); - htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, "htmlmixed"); - return { - token : parserConfig.startOpen ? scriptingDispatch : htmlDispatch, - htmlState : CodeMirror.startState(htmlMixedMode), - scriptState : CodeMirror.startState(scriptingMode) - }; - }, - - token: function(stream, state) { - return state.token(stream, state); - }, - - indent: function(state, textAfter) { - if (state.token == htmlDispatch) - return htmlMixedMode.indent(state.htmlState, textAfter); - else if (scriptingMode.indent) - return scriptingMode.indent(state.scriptState, textAfter); - }, - - copyState: function(state) { - return { - token : state.token, - htmlState : CodeMirror.copyState(htmlMixedMode, state.htmlState), - scriptState : CodeMirror.copyState(scriptingMode, state.scriptState) - }; - }, - - innerMode: function(state) { - if (state.token == scriptingDispatch) return {state: state.scriptState, mode: scriptingMode}; - else return {state: state.htmlState, mode: htmlMixedMode}; - } - }; -}, "htmlmixed"); - -CodeMirror.defineMIME("application/x-ejs", { name: "htmlembedded", scriptingModeSpec:"javascript"}); -CodeMirror.defineMIME("application/x-aspx", { name: "htmlembedded", scriptingModeSpec:"text/x-csharp"}); -CodeMirror.defineMIME("application/x-jsp", { name: "htmlembedded", scriptingModeSpec:"text/x-java"}); -CodeMirror.defineMIME("application/x-erb", { name: "htmlembedded", scriptingModeSpec:"ruby"}); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/htmlembedded/index.html b/shared/html/libs/codemirror/5.0.0/mode/htmlembedded/index.html deleted file mode 100644 index 93d01c4..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/htmlembedded/index.html +++ /dev/null @@ -1,58 +0,0 @@ - - -CodeMirror: Html Embedded Scripts mode - - - - - - - - - - - - - -
-

Html Embedded Scripts mode

-
- - - -

Mode for html embedded scripts like JSP and ASP.NET. Depends on HtmlMixed which in turn depends on - JavaScript, CSS and XML.
Other dependancies include those of the scriping language chosen.

- -

MIME types defined: application/x-aspx (ASP.NET), - application/x-ejs (Embedded Javascript), application/x-jsp (JavaServer Pages)

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/htmlmixed/htmlmixed.js b/shared/html/libs/codemirror/5.0.0/mode/htmlmixed/htmlmixed.js deleted file mode 100644 index 1cc438f..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/htmlmixed/htmlmixed.js +++ /dev/null @@ -1,121 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("htmlmixed", function(config, parserConfig) { - var htmlMode = CodeMirror.getMode(config, {name: "xml", - htmlMode: true, - multilineTagIndentFactor: parserConfig.multilineTagIndentFactor, - multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag}); - var cssMode = CodeMirror.getMode(config, "css"); - - var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes; - scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, - mode: CodeMirror.getMode(config, "javascript")}); - if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) { - var conf = scriptTypesConf[i]; - scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)}); - } - scriptTypes.push({matches: /./, - mode: CodeMirror.getMode(config, "text/plain")}); - - function html(stream, state) { - var tagName = state.htmlState.tagName; - if (tagName) tagName = tagName.toLowerCase(); - var style = htmlMode.token(stream, state.htmlState); - if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") { - // Script block: mode to change to depends on type attribute - var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i); - scriptType = scriptType ? scriptType[1] : ""; - if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1); - for (var i = 0; i < scriptTypes.length; ++i) { - var tp = scriptTypes[i]; - if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) { - if (tp.mode) { - state.token = script; - state.localMode = tp.mode; - state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, "")); - } - break; - } - } - } else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") { - state.token = css; - state.localMode = cssMode; - state.localState = cssMode.startState(htmlMode.indent(state.htmlState, "")); - } - return style; - } - function maybeBackup(stream, pat, style) { - var cur = stream.current(); - var close = cur.search(pat), m; - if (close > -1) stream.backUp(cur.length - close); - else if (m = cur.match(/<\/?$/)) { - stream.backUp(cur.length); - if (!stream.match(pat, false)) stream.match(cur); - } - return style; - } - function script(stream, state) { - if (stream.match(/^<\/\s*script\s*>/i, false)) { - state.token = html; - state.localState = state.localMode = null; - return null; - } - return maybeBackup(stream, /<\/\s*script\s*>/, - state.localMode.token(stream, state.localState)); - } - function css(stream, state) { - if (stream.match(/^<\/\s*style\s*>/i, false)) { - state.token = html; - state.localState = state.localMode = null; - return null; - } - return maybeBackup(stream, /<\/\s*style\s*>/, - cssMode.token(stream, state.localState)); - } - - return { - startState: function() { - var state = htmlMode.startState(); - return {token: html, localMode: null, localState: null, htmlState: state}; - }, - - copyState: function(state) { - if (state.localState) - var local = CodeMirror.copyState(state.localMode, state.localState); - return {token: state.token, localMode: state.localMode, localState: local, - htmlState: CodeMirror.copyState(htmlMode, state.htmlState)}; - }, - - token: function(stream, state) { - return state.token(stream, state); - }, - - indent: function(state, textAfter) { - if (!state.localMode || /^\s*<\//.test(textAfter)) - return htmlMode.indent(state.htmlState, textAfter); - else if (state.localMode.indent) - return state.localMode.indent(state.localState, textAfter); - else - return CodeMirror.Pass; - }, - - innerMode: function(state) { - return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode}; - } - }; -}, "xml", "javascript", "css"); - -CodeMirror.defineMIME("text/html", "htmlmixed"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/htmlmixed/index.html b/shared/html/libs/codemirror/5.0.0/mode/htmlmixed/index.html deleted file mode 100644 index f94df9e..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/htmlmixed/index.html +++ /dev/null @@ -1,89 +0,0 @@ - - -CodeMirror: HTML mixed mode - - - - - - - - - - - - - - -
-

HTML mixed mode

-
- - -

The HTML mixed mode depends on the XML, JavaScript, and CSS modes.

- -

It takes an optional mode configuration - option, scriptTypes, which can be used to add custom - behavior for specific <script type="..."> tags. If - given, it should hold an array of {matches, mode} - objects, where matches is a string or regexp that - matches the script type, and mode is - either null, for script types that should stay in - HTML mode, or a mode - spec corresponding to the mode that should be used for the - script.

- -

MIME types defined: text/html - (redefined, only takes effect if you load this parser after the - XML parser).

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/http/http.js b/shared/html/libs/codemirror/5.0.0/mode/http/http.js deleted file mode 100644 index 9a3c5f9..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/http/http.js +++ /dev/null @@ -1,113 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("http", function() { - function failFirstLine(stream, state) { - stream.skipToEnd(); - state.cur = header; - return "error"; - } - - function start(stream, state) { - if (stream.match(/^HTTP\/\d\.\d/)) { - state.cur = responseStatusCode; - return "keyword"; - } else if (stream.match(/^[A-Z]+/) && /[ \t]/.test(stream.peek())) { - state.cur = requestPath; - return "keyword"; - } else { - return failFirstLine(stream, state); - } - } - - function responseStatusCode(stream, state) { - var code = stream.match(/^\d+/); - if (!code) return failFirstLine(stream, state); - - state.cur = responseStatusText; - var status = Number(code[0]); - if (status >= 100 && status < 200) { - return "positive informational"; - } else if (status >= 200 && status < 300) { - return "positive success"; - } else if (status >= 300 && status < 400) { - return "positive redirect"; - } else if (status >= 400 && status < 500) { - return "negative client-error"; - } else if (status >= 500 && status < 600) { - return "negative server-error"; - } else { - return "error"; - } - } - - function responseStatusText(stream, state) { - stream.skipToEnd(); - state.cur = header; - return null; - } - - function requestPath(stream, state) { - stream.eatWhile(/\S/); - state.cur = requestProtocol; - return "string-2"; - } - - function requestProtocol(stream, state) { - if (stream.match(/^HTTP\/\d\.\d$/)) { - state.cur = header; - return "keyword"; - } else { - return failFirstLine(stream, state); - } - } - - function header(stream) { - if (stream.sol() && !stream.eat(/[ \t]/)) { - if (stream.match(/^.*?:/)) { - return "atom"; - } else { - stream.skipToEnd(); - return "error"; - } - } else { - stream.skipToEnd(); - return "string"; - } - } - - function body(stream) { - stream.skipToEnd(); - return null; - } - - return { - token: function(stream, state) { - var cur = state.cur; - if (cur != header && cur != body && stream.eatSpace()) return null; - return cur(stream, state); - }, - - blankLine: function(state) { - state.cur = body; - }, - - startState: function() { - return {cur: start}; - } - }; -}); - -CodeMirror.defineMIME("message/http", "http"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/http/index.html b/shared/html/libs/codemirror/5.0.0/mode/http/index.html deleted file mode 100644 index 0b8d531..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/http/index.html +++ /dev/null @@ -1,45 +0,0 @@ - - -CodeMirror: HTTP mode - - - - - - - - - -
-

HTTP mode

- - -
- - - -

MIME types defined: message/http.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/idl/idl.js b/shared/html/libs/codemirror/5.0.0/mode/idl/idl.js deleted file mode 100644 index 07308d7..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/idl/idl.js +++ /dev/null @@ -1,290 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function wordRegexp(words) { - return new RegExp('^((' + words.join(')|(') + '))\\b', 'i'); - }; - - var builtinArray = [ - 'a_correlate', 'abs', 'acos', 'adapt_hist_equal', 'alog', - 'alog2', 'alog10', 'amoeba', 'annotate', 'app_user_dir', - 'app_user_dir_query', 'arg_present', 'array_equal', 'array_indices', - 'arrow', 'ascii_template', 'asin', 'assoc', 'atan', - 'axis', 'axis', 'bandpass_filter', 'bandreject_filter', 'barplot', - 'bar_plot', 'beseli', 'beselj', 'beselk', 'besely', - 'beta', 'biginteger', 'bilinear', 'bin_date', 'binary_template', - 'bindgen', 'binomial', 'bit_ffs', 'bit_population', 'blas_axpy', - 'blk_con', 'boolarr', 'boolean', 'boxplot', 'box_cursor', - 'breakpoint', 'broyden', 'bubbleplot', 'butterworth', 'bytarr', - 'byte', 'byteorder', 'bytscl', 'c_correlate', 'calendar', - 'caldat', 'call_external', 'call_function', 'call_method', - 'call_procedure', 'canny', 'catch', 'cd', 'cdf', 'ceil', - 'chebyshev', 'check_math', 'chisqr_cvf', 'chisqr_pdf', 'choldc', - 'cholsol', 'cindgen', 'cir_3pnt', 'clipboard', 'close', - 'clust_wts', 'cluster', 'cluster_tree', 'cmyk_convert', 'code_coverage', - 'color_convert', 'color_exchange', 'color_quan', 'color_range_map', - 'colorbar', 'colorize_sample', 'colormap_applicable', - 'colormap_gradient', 'colormap_rotation', 'colortable', - 'comfit', 'command_line_args', 'common', 'compile_opt', 'complex', - 'complexarr', 'complexround', 'compute_mesh_normals', 'cond', 'congrid', - 'conj', 'constrained_min', 'contour', 'contour', 'convert_coord', - 'convol', 'convol_fft', 'coord2to3', 'copy_lun', 'correlate', - 'cos', 'cosh', 'cpu', 'cramer', 'createboxplotdata', - 'create_cursor', 'create_struct', 'create_view', 'crossp', 'crvlength', - 'ct_luminance', 'cti_test', 'cursor', 'curvefit', 'cv_coord', - 'cvttobm', 'cw_animate', 'cw_animate_getp', 'cw_animate_load', - 'cw_animate_run', 'cw_arcball', 'cw_bgroup', 'cw_clr_index', - 'cw_colorsel', 'cw_defroi', 'cw_field', 'cw_filesel', 'cw_form', - 'cw_fslider', 'cw_light_editor', 'cw_light_editor_get', - 'cw_light_editor_set', 'cw_orient', 'cw_palette_editor', - 'cw_palette_editor_get', 'cw_palette_editor_set', 'cw_pdmenu', - 'cw_rgbslider', 'cw_tmpl', 'cw_zoom', 'db_exists', - 'dblarr', 'dcindgen', 'dcomplex', 'dcomplexarr', 'define_key', - 'define_msgblk', 'define_msgblk_from_file', 'defroi', 'defsysv', - 'delvar', 'dendro_plot', 'dendrogram', 'deriv', 'derivsig', - 'determ', 'device', 'dfpmin', 'diag_matrix', 'dialog_dbconnect', - 'dialog_message', 'dialog_pickfile', 'dialog_printersetup', - 'dialog_printjob', 'dialog_read_image', - 'dialog_write_image', 'dictionary', 'digital_filter', 'dilate', 'dindgen', - 'dissolve', 'dist', 'distance_measure', 'dlm_load', 'dlm_register', - 'doc_library', 'double', 'draw_roi', 'edge_dog', 'efont', - 'eigenql', 'eigenvec', 'ellipse', 'elmhes', 'emboss', - 'empty', 'enable_sysrtn', 'eof', 'eos', 'erase', - 'erf', 'erfc', 'erfcx', 'erode', 'errorplot', - 'errplot', 'estimator_filter', 'execute', 'exit', 'exp', - 'expand', 'expand_path', 'expint', 'extrac', 'extract_slice', - 'f_cvf', 'f_pdf', 'factorial', 'fft', 'file_basename', - 'file_chmod', 'file_copy', 'file_delete', 'file_dirname', - 'file_expand_path', 'file_gunzip', 'file_gzip', 'file_info', - 'file_lines', 'file_link', 'file_mkdir', 'file_move', - 'file_poll_input', 'file_readlink', 'file_same', - 'file_search', 'file_tar', 'file_test', 'file_untar', 'file_unzip', - 'file_which', 'file_zip', 'filepath', 'findgen', 'finite', - 'fix', 'flick', 'float', 'floor', 'flow3', - 'fltarr', 'flush', 'format_axis_values', 'forward_function', 'free_lun', - 'fstat', 'fulstr', 'funct', 'function', 'fv_test', - 'fx_root', 'fz_roots', 'gamma', 'gamma_ct', 'gauss_cvf', - 'gauss_pdf', 'gauss_smooth', 'gauss2dfit', 'gaussfit', - 'gaussian_function', 'gaussint', 'get_drive_list', 'get_dxf_objects', - 'get_kbrd', 'get_login_info', - 'get_lun', 'get_screen_size', 'getenv', 'getwindows', 'greg2jul', - 'grib', 'grid_input', 'grid_tps', 'grid3', 'griddata', - 'gs_iter', 'h_eq_ct', 'h_eq_int', 'hanning', 'hash', - 'hdf', 'hdf5', 'heap_free', 'heap_gc', 'heap_nosave', - 'heap_refcount', 'heap_save', 'help', 'hilbert', 'hist_2d', - 'hist_equal', 'histogram', 'hls', 'hough', 'hqr', - 'hsv', 'i18n_multibytetoutf8', - 'i18n_multibytetowidechar', 'i18n_utf8tomultibyte', - 'i18n_widechartomultibyte', - 'ibeta', 'icontour', 'iconvertcoord', 'idelete', 'identity', - 'idl_base64', 'idl_container', 'idl_validname', - 'idlexbr_assistant', 'idlitsys_createtool', - 'idlunit', 'iellipse', 'igamma', 'igetcurrent', 'igetdata', - 'igetid', 'igetproperty', 'iimage', 'image', 'image_cont', - 'image_statistics', 'image_threshold', 'imaginary', 'imap', 'indgen', - 'int_2d', 'int_3d', 'int_tabulated', 'intarr', 'interpol', - 'interpolate', 'interval_volume', 'invert', 'ioctl', 'iopen', - 'ir_filter', 'iplot', 'ipolygon', 'ipolyline', 'iputdata', - 'iregister', 'ireset', 'iresolve', 'irotate', 'isa', - 'isave', 'iscale', 'isetcurrent', 'isetproperty', 'ishft', - 'isocontour', 'isosurface', 'isurface', 'itext', 'itranslate', - 'ivector', 'ivolume', 'izoom', 'journal', 'json_parse', - 'json_serialize', 'jul2greg', 'julday', 'keyword_set', 'krig2d', - 'kurtosis', 'kw_test', 'l64indgen', 'la_choldc', 'la_cholmprove', - 'la_cholsol', 'la_determ', 'la_eigenproblem', 'la_eigenql', 'la_eigenvec', - 'la_elmhes', 'la_gm_linear_model', 'la_hqr', 'la_invert', - 'la_least_square_equality', 'la_least_squares', 'la_linear_equation', - 'la_ludc', 'la_lumprove', 'la_lusol', - 'la_svd', 'la_tridc', 'la_trimprove', 'la_triql', 'la_trired', - 'la_trisol', 'label_date', 'label_region', 'ladfit', 'laguerre', - 'lambda', 'lambdap', 'lambertw', 'laplacian', 'least_squares_filter', - 'leefilt', 'legend', 'legendre', 'linbcg', 'lindgen', - 'linfit', 'linkimage', 'list', 'll_arc_distance', 'lmfit', - 'lmgr', 'lngamma', 'lnp_test', 'loadct', 'locale_get', - 'logical_and', 'logical_or', 'logical_true', 'lon64arr', 'lonarr', - 'long', 'long64', 'lsode', 'lu_complex', 'ludc', - 'lumprove', 'lusol', 'm_correlate', 'machar', 'make_array', - 'make_dll', 'make_rt', 'map', 'mapcontinents', 'mapgrid', - 'map_2points', 'map_continents', 'map_grid', 'map_image', 'map_patch', - 'map_proj_forward', 'map_proj_image', 'map_proj_info', - 'map_proj_init', 'map_proj_inverse', - 'map_set', 'matrix_multiply', 'matrix_power', 'max', 'md_test', - 'mean', 'meanabsdev', 'mean_filter', 'median', 'memory', - 'mesh_clip', 'mesh_decimate', 'mesh_issolid', - 'mesh_merge', 'mesh_numtriangles', - 'mesh_obj', 'mesh_smooth', 'mesh_surfacearea', - 'mesh_validate', 'mesh_volume', - 'message', 'min', 'min_curve_surf', 'mk_html_help', 'modifyct', - 'moment', 'morph_close', 'morph_distance', - 'morph_gradient', 'morph_hitormiss', - 'morph_open', 'morph_thin', 'morph_tophat', 'multi', 'n_elements', - 'n_params', 'n_tags', 'ncdf', 'newton', 'noise_hurl', - 'noise_pick', 'noise_scatter', 'noise_slur', 'norm', 'obj_class', - 'obj_destroy', 'obj_hasmethod', 'obj_isa', 'obj_new', 'obj_valid', - 'objarr', 'on_error', 'on_ioerror', 'online_help', 'openr', - 'openu', 'openw', 'oplot', 'oploterr', 'orderedhash', - 'p_correlate', 'parse_url', 'particle_trace', 'path_cache', 'path_sep', - 'pcomp', 'plot', 'plot3d', 'plot', 'plot_3dbox', - 'plot_field', 'ploterr', 'plots', 'polar_contour', 'polar_surface', - 'polyfill', 'polyshade', 'pnt_line', 'point_lun', 'polarplot', - 'poly', 'poly_2d', 'poly_area', 'poly_fit', 'polyfillv', - 'polygon', 'polyline', 'polywarp', 'popd', 'powell', - 'pref_commit', 'pref_get', 'pref_set', 'prewitt', 'primes', - 'print', 'printf', 'printd', 'pro', 'product', - 'profile', 'profiler', 'profiles', 'project_vol', 'ps_show_fonts', - 'psafm', 'pseudo', 'ptr_free', 'ptr_new', 'ptr_valid', - 'ptrarr', 'pushd', 'qgrid3', 'qhull', 'qromb', - 'qromo', 'qsimp', 'query_*', 'query_ascii', 'query_bmp', - 'query_csv', 'query_dicom', 'query_gif', 'query_image', 'query_jpeg', - 'query_jpeg2000', 'query_mrsid', 'query_pict', 'query_png', 'query_ppm', - 'query_srf', 'query_tiff', 'query_video', 'query_wav', 'r_correlate', - 'r_test', 'radon', 'randomn', 'randomu', 'ranks', - 'rdpix', 'read', 'readf', 'read_ascii', 'read_binary', - 'read_bmp', 'read_csv', 'read_dicom', 'read_gif', 'read_image', - 'read_interfile', 'read_jpeg', 'read_jpeg2000', 'read_mrsid', 'read_pict', - 'read_png', 'read_ppm', 'read_spr', 'read_srf', 'read_sylk', - 'read_tiff', 'read_video', 'read_wav', 'read_wave', 'read_x11_bitmap', - 'read_xwd', 'reads', 'readu', 'real_part', 'rebin', - 'recall_commands', 'recon3', 'reduce_colors', 'reform', 'region_grow', - 'register_cursor', 'regress', 'replicate', - 'replicate_inplace', 'resolve_all', - 'resolve_routine', 'restore', 'retall', 'return', 'reverse', - 'rk4', 'roberts', 'rot', 'rotate', 'round', - 'routine_filepath', 'routine_info', 'rs_test', 's_test', 'save', - 'savgol', 'scale3', 'scale3d', 'scatterplot', 'scatterplot3d', - 'scope_level', 'scope_traceback', 'scope_varfetch', - 'scope_varname', 'search2d', - 'search3d', 'sem_create', 'sem_delete', 'sem_lock', 'sem_release', - 'set_plot', 'set_shading', 'setenv', 'sfit', 'shade_surf', - 'shade_surf_irr', 'shade_volume', 'shift', 'shift_diff', 'shmdebug', - 'shmmap', 'shmunmap', 'shmvar', 'show3', 'showfont', - 'signum', 'simplex', 'sin', 'sindgen', 'sinh', - 'size', 'skewness', 'skip_lun', 'slicer3', 'slide_image', - 'smooth', 'sobel', 'socket', 'sort', 'spawn', - 'sph_4pnt', 'sph_scat', 'spher_harm', 'spl_init', 'spl_interp', - 'spline', 'spline_p', 'sprsab', 'sprsax', 'sprsin', - 'sprstp', 'sqrt', 'standardize', 'stddev', 'stop', - 'strarr', 'strcmp', 'strcompress', 'streamline', 'streamline', - 'stregex', 'stretch', 'string', 'strjoin', 'strlen', - 'strlowcase', 'strmatch', 'strmessage', 'strmid', 'strpos', - 'strput', 'strsplit', 'strtrim', 'struct_assign', 'struct_hide', - 'strupcase', 'surface', 'surface', 'surfr', 'svdc', - 'svdfit', 'svsol', 'swap_endian', 'swap_endian_inplace', 'symbol', - 'systime', 't_cvf', 't_pdf', 't3d', 'tag_names', - 'tan', 'tanh', 'tek_color', 'temporary', 'terminal_size', - 'tetra_clip', 'tetra_surface', 'tetra_volume', 'text', 'thin', - 'thread', 'threed', 'tic', 'time_test2', 'timegen', - 'timer', 'timestamp', 'timestamptovalues', 'tm_test', 'toc', - 'total', 'trace', 'transpose', 'tri_surf', 'triangulate', - 'trigrid', 'triql', 'trired', 'trisol', 'truncate_lun', - 'ts_coef', 'ts_diff', 'ts_fcast', 'ts_smooth', 'tv', - 'tvcrs', 'tvlct', 'tvrd', 'tvscl', 'typename', - 'uindgen', 'uint', 'uintarr', 'ul64indgen', 'ulindgen', - 'ulon64arr', 'ulonarr', 'ulong', 'ulong64', 'uniq', - 'unsharp_mask', 'usersym', 'value_locate', 'variance', 'vector', - 'vector_field', 'vel', 'velovect', 'vert_t3d', 'voigt', - 'volume', 'voronoi', 'voxel_proj', 'wait', 'warp_tri', - 'watershed', 'wdelete', 'wf_draw', 'where', 'widget_base', - 'widget_button', 'widget_combobox', 'widget_control', - 'widget_displaycontextmenu', 'widget_draw', - 'widget_droplist', 'widget_event', 'widget_info', - 'widget_label', 'widget_list', - 'widget_propertysheet', 'widget_slider', 'widget_tab', - 'widget_table', 'widget_text', - 'widget_tree', 'widget_tree_move', 'widget_window', - 'wiener_filter', 'window', - 'window', 'write_bmp', 'write_csv', 'write_gif', 'write_image', - 'write_jpeg', 'write_jpeg2000', 'write_nrif', 'write_pict', 'write_png', - 'write_ppm', 'write_spr', 'write_srf', 'write_sylk', 'write_tiff', - 'write_video', 'write_wav', 'write_wave', 'writeu', 'wset', - 'wshow', 'wtn', 'wv_applet', 'wv_cwt', 'wv_cw_wavelet', - 'wv_denoise', 'wv_dwt', 'wv_fn_coiflet', - 'wv_fn_daubechies', 'wv_fn_gaussian', - 'wv_fn_haar', 'wv_fn_morlet', 'wv_fn_paul', - 'wv_fn_symlet', 'wv_import_data', - 'wv_import_wavelet', 'wv_plot3d_wps', 'wv_plot_multires', - 'wv_pwt', 'wv_tool_denoise', - 'xbm_edit', 'xdisplayfile', 'xdxf', 'xfont', 'xinteranimate', - 'xloadct', 'xmanager', 'xmng_tmpl', 'xmtool', 'xobjview', - 'xobjview_rotate', 'xobjview_write_image', - 'xpalette', 'xpcolor', 'xplot3d', - 'xregistered', 'xroi', 'xsq_test', 'xsurface', 'xvaredit', - 'xvolume', 'xvolume_rotate', 'xvolume_write_image', - 'xyouts', 'zlib_compress', 'zlib_uncompress', 'zoom', 'zoom_24' - ]; - var builtins = wordRegexp(builtinArray); - - var keywordArray = [ - 'begin', 'end', 'endcase', 'endfor', - 'endwhile', 'endif', 'endrep', 'endforeach', - 'break', 'case', 'continue', 'for', - 'foreach', 'goto', 'if', 'then', 'else', - 'repeat', 'until', 'switch', 'while', - 'do', 'pro', 'function' - ]; - var keywords = wordRegexp(keywordArray); - - CodeMirror.registerHelper("hintWords", "idl", builtinArray.concat(keywordArray)); - - var identifiers = new RegExp('^[_a-z\xa1-\uffff][_a-z0-9\xa1-\uffff]*', 'i'); - - var singleOperators = /[+\-*&=<>\/@#~$]/; - var boolOperators = new RegExp('(and|or|eq|lt|le|gt|ge|ne|not)', 'i'); - - function tokenBase(stream) { - // whitespaces - if (stream.eatSpace()) return null; - - // Handle one line Comments - if (stream.match(';')) { - stream.skipToEnd(); - return 'comment'; - } - - // Handle Number Literals - if (stream.match(/^[0-9\.+-]/, false)) { - if (stream.match(/^[+-]?0x[0-9a-fA-F]+/)) - return 'number'; - if (stream.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?/)) - return 'number'; - if (stream.match(/^[+-]?\d+([EeDd][+-]?\d+)?/)) - return 'number'; - } - - // Handle Strings - if (stream.match(/^"([^"]|(""))*"/)) { return 'string'; } - if (stream.match(/^'([^']|(''))*'/)) { return 'string'; } - - // Handle words - if (stream.match(keywords)) { return 'keyword'; } - if (stream.match(builtins)) { return 'builtin'; } - if (stream.match(identifiers)) { return 'variable'; } - - if (stream.match(singleOperators) || stream.match(boolOperators)) { - return 'operator'; } - - // Handle non-detected items - stream.next(); - return null; - }; - - CodeMirror.defineMode('idl', function() { - return { - token: function(stream) { - return tokenBase(stream); - } - }; - }); - - CodeMirror.defineMIME('text/x-idl', 'idl'); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/idl/index.html b/shared/html/libs/codemirror/5.0.0/mode/idl/index.html deleted file mode 100644 index 4c169e2..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/idl/index.html +++ /dev/null @@ -1,64 +0,0 @@ - - -CodeMirror: IDL mode - - - - - - - - - -
-

IDL mode

- -
- - -

MIME types defined: text/x-idl.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/index.html b/shared/html/libs/codemirror/5.0.0/mode/index.html deleted file mode 100644 index 04167a5..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/index.html +++ /dev/null @@ -1,134 +0,0 @@ - - -CodeMirror: Language Modes - - - - - -
- -

Language modes

- -

This is a list of every mode in the distribution. Each mode lives -in a subdirectory of the mode/ directory, and typically -defines a single JavaScript file that implements the mode. Loading -such file will make the language available to CodeMirror, through -the mode -option.

- -
- -
- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/jade/index.html b/shared/html/libs/codemirror/5.0.0/mode/jade/index.html deleted file mode 100644 index e534981..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/jade/index.html +++ /dev/null @@ -1,70 +0,0 @@ - - -CodeMirror: Jade Templating Mode - - - - - - - - - - - - - -
-

Jade Templating Mode

-
- -

The Jade Templating Mode

-

Created by Forbes Lindesay. Managed as part of a Brackets extension at https://github.com/ForbesLindesay/jade-brackets.

-

MIME type defined: text/x-jade.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/jade/jade.js b/shared/html/libs/codemirror/5.0.0/mode/jade/jade.js deleted file mode 100644 index 96fadb1..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/jade/jade.js +++ /dev/null @@ -1,590 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../javascript/javascript"), require("../css/css"), require("../htmlmixed/htmlmixed")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../javascript/javascript", "../css/css", "../htmlmixed/htmlmixed"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('jade', function (config) { - // token types - var KEYWORD = 'keyword'; - var DOCTYPE = 'meta'; - var ID = 'builtin'; - var CLASS = 'qualifier'; - - var ATTRS_NEST = { - '{': '}', - '(': ')', - '[': ']' - }; - - var jsMode = CodeMirror.getMode(config, 'javascript'); - - function State() { - this.javaScriptLine = false; - this.javaScriptLineExcludesColon = false; - - this.javaScriptArguments = false; - this.javaScriptArgumentsDepth = 0; - - this.isInterpolating = false; - this.interpolationNesting = 0; - - this.jsState = jsMode.startState(); - - this.restOfLine = ''; - - this.isIncludeFiltered = false; - this.isEach = false; - - this.lastTag = ''; - this.scriptType = ''; - - // Attributes Mode - this.isAttrs = false; - this.attrsNest = []; - this.inAttributeName = true; - this.attributeIsType = false; - this.attrValue = ''; - - // Indented Mode - this.indentOf = Infinity; - this.indentToken = ''; - - this.innerMode = null; - this.innerState = null; - - this.innerModeForLine = false; - } - /** - * Safely copy a state - * - * @return {State} - */ - State.prototype.copy = function () { - var res = new State(); - res.javaScriptLine = this.javaScriptLine; - res.javaScriptLineExcludesColon = this.javaScriptLineExcludesColon; - res.javaScriptArguments = this.javaScriptArguments; - res.javaScriptArgumentsDepth = this.javaScriptArgumentsDepth; - res.isInterpolating = this.isInterpolating; - res.interpolationNesting = this.intpolationNesting; - - res.jsState = CodeMirror.copyState(jsMode, this.jsState); - - res.innerMode = this.innerMode; - if (this.innerMode && this.innerState) { - res.innerState = CodeMirror.copyState(this.innerMode, this.innerState); - } - - res.restOfLine = this.restOfLine; - - res.isIncludeFiltered = this.isIncludeFiltered; - res.isEach = this.isEach; - res.lastTag = this.lastTag; - res.scriptType = this.scriptType; - res.isAttrs = this.isAttrs; - res.attrsNest = this.attrsNest.slice(); - res.inAttributeName = this.inAttributeName; - res.attributeIsType = this.attributeIsType; - res.attrValue = this.attrValue; - res.indentOf = this.indentOf; - res.indentToken = this.indentToken; - - res.innerModeForLine = this.innerModeForLine; - - return res; - }; - - function javaScript(stream, state) { - if (stream.sol()) { - // if javaScriptLine was set at end of line, ignore it - state.javaScriptLine = false; - state.javaScriptLineExcludesColon = false; - } - if (state.javaScriptLine) { - if (state.javaScriptLineExcludesColon && stream.peek() === ':') { - state.javaScriptLine = false; - state.javaScriptLineExcludesColon = false; - return; - } - var tok = jsMode.token(stream, state.jsState); - if (stream.eol()) state.javaScriptLine = false; - return tok || true; - } - } - function javaScriptArguments(stream, state) { - if (state.javaScriptArguments) { - if (state.javaScriptArgumentsDepth === 0 && stream.peek() !== '(') { - state.javaScriptArguments = false; - return; - } - if (stream.peek() === '(') { - state.javaScriptArgumentsDepth++; - } else if (stream.peek() === ')') { - state.javaScriptArgumentsDepth--; - } - if (state.javaScriptArgumentsDepth === 0) { - state.javaScriptArguments = false; - return; - } - - var tok = jsMode.token(stream, state.jsState); - return tok || true; - } - } - - function yieldStatement(stream) { - if (stream.match(/^yield\b/)) { - return 'keyword'; - } - } - - function doctype(stream) { - if (stream.match(/^(?:doctype) *([^\n]+)?/)) { - return DOCTYPE; - } - } - - function interpolation(stream, state) { - if (stream.match('#{')) { - state.isInterpolating = true; - state.interpolationNesting = 0; - return 'punctuation'; - } - } - - function interpolationContinued(stream, state) { - if (state.isInterpolating) { - if (stream.peek() === '}') { - state.interpolationNesting--; - if (state.interpolationNesting < 0) { - stream.next(); - state.isInterpolating = false; - return 'puncutation'; - } - } else if (stream.peek() === '{') { - state.interpolationNesting++; - } - return jsMode.token(stream, state.jsState) || true; - } - } - - function caseStatement(stream, state) { - if (stream.match(/^case\b/)) { - state.javaScriptLine = true; - return KEYWORD; - } - } - - function when(stream, state) { - if (stream.match(/^when\b/)) { - state.javaScriptLine = true; - state.javaScriptLineExcludesColon = true; - return KEYWORD; - } - } - - function defaultStatement(stream) { - if (stream.match(/^default\b/)) { - return KEYWORD; - } - } - - function extendsStatement(stream, state) { - if (stream.match(/^extends?\b/)) { - state.restOfLine = 'string'; - return KEYWORD; - } - } - - function append(stream, state) { - if (stream.match(/^append\b/)) { - state.restOfLine = 'variable'; - return KEYWORD; - } - } - function prepend(stream, state) { - if (stream.match(/^prepend\b/)) { - state.restOfLine = 'variable'; - return KEYWORD; - } - } - function block(stream, state) { - if (stream.match(/^block\b *(?:(prepend|append)\b)?/)) { - state.restOfLine = 'variable'; - return KEYWORD; - } - } - - function include(stream, state) { - if (stream.match(/^include\b/)) { - state.restOfLine = 'string'; - return KEYWORD; - } - } - - function includeFiltered(stream, state) { - if (stream.match(/^include:([a-zA-Z0-9\-]+)/, false) && stream.match('include')) { - state.isIncludeFiltered = true; - return KEYWORD; - } - } - - function includeFilteredContinued(stream, state) { - if (state.isIncludeFiltered) { - var tok = filter(stream, state); - state.isIncludeFiltered = false; - state.restOfLine = 'string'; - return tok; - } - } - - function mixin(stream, state) { - if (stream.match(/^mixin\b/)) { - state.javaScriptLine = true; - return KEYWORD; - } - } - - function call(stream, state) { - if (stream.match(/^\+([-\w]+)/)) { - if (!stream.match(/^\( *[-\w]+ *=/, false)) { - state.javaScriptArguments = true; - state.javaScriptArgumentsDepth = 0; - } - return 'variable'; - } - if (stream.match(/^\+#{/, false)) { - stream.next(); - state.mixinCallAfter = true; - return interpolation(stream, state); - } - } - function callArguments(stream, state) { - if (state.mixinCallAfter) { - state.mixinCallAfter = false; - if (!stream.match(/^\( *[-\w]+ *=/, false)) { - state.javaScriptArguments = true; - state.javaScriptArgumentsDepth = 0; - } - return true; - } - } - - function conditional(stream, state) { - if (stream.match(/^(if|unless|else if|else)\b/)) { - state.javaScriptLine = true; - return KEYWORD; - } - } - - function each(stream, state) { - if (stream.match(/^(- *)?(each|for)\b/)) { - state.isEach = true; - return KEYWORD; - } - } - function eachContinued(stream, state) { - if (state.isEach) { - if (stream.match(/^ in\b/)) { - state.javaScriptLine = true; - state.isEach = false; - return KEYWORD; - } else if (stream.sol() || stream.eol()) { - state.isEach = false; - } else if (stream.next()) { - while (!stream.match(/^ in\b/, false) && stream.next()); - return 'variable'; - } - } - } - - function whileStatement(stream, state) { - if (stream.match(/^while\b/)) { - state.javaScriptLine = true; - return KEYWORD; - } - } - - function tag(stream, state) { - var captures; - if (captures = stream.match(/^(\w(?:[-:\w]*\w)?)\/?/)) { - state.lastTag = captures[1].toLowerCase(); - if (state.lastTag === 'script') { - state.scriptType = 'application/javascript'; - } - return 'tag'; - } - } - - function filter(stream, state) { - if (stream.match(/^:([\w\-]+)/)) { - var innerMode; - if (config && config.innerModes) { - innerMode = config.innerModes(stream.current().substring(1)); - } - if (!innerMode) { - innerMode = stream.current().substring(1); - } - if (typeof innerMode === 'string') { - innerMode = CodeMirror.getMode(config, innerMode); - } - setInnerMode(stream, state, innerMode); - return 'atom'; - } - } - - function code(stream, state) { - if (stream.match(/^(!?=|-)/)) { - state.javaScriptLine = true; - return 'punctuation'; - } - } - - function id(stream) { - if (stream.match(/^#([\w-]+)/)) { - return ID; - } - } - - function className(stream) { - if (stream.match(/^\.([\w-]+)/)) { - return CLASS; - } - } - - function attrs(stream, state) { - if (stream.peek() == '(') { - stream.next(); - state.isAttrs = true; - state.attrsNest = []; - state.inAttributeName = true; - state.attrValue = ''; - state.attributeIsType = false; - return 'punctuation'; - } - } - - function attrsContinued(stream, state) { - if (state.isAttrs) { - if (ATTRS_NEST[stream.peek()]) { - state.attrsNest.push(ATTRS_NEST[stream.peek()]); - } - if (state.attrsNest[state.attrsNest.length - 1] === stream.peek()) { - state.attrsNest.pop(); - } else if (stream.eat(')')) { - state.isAttrs = false; - return 'punctuation'; - } - if (state.inAttributeName && stream.match(/^[^=,\)!]+/)) { - if (stream.peek() === '=' || stream.peek() === '!') { - state.inAttributeName = false; - state.jsState = jsMode.startState(); - if (state.lastTag === 'script' && stream.current().trim().toLowerCase() === 'type') { - state.attributeIsType = true; - } else { - state.attributeIsType = false; - } - } - return 'attribute'; - } - - var tok = jsMode.token(stream, state.jsState); - if (state.attributeIsType && tok === 'string') { - state.scriptType = stream.current().toString(); - } - if (state.attrsNest.length === 0 && (tok === 'string' || tok === 'variable' || tok === 'keyword')) { - try { - Function('', 'var x ' + state.attrValue.replace(/,\s*$/, '').replace(/^!/, '')); - state.inAttributeName = true; - state.attrValue = ''; - stream.backUp(stream.current().length); - return attrsContinued(stream, state); - } catch (ex) { - //not the end of an attribute - } - } - state.attrValue += stream.current(); - return tok || true; - } - } - - function attributesBlock(stream, state) { - if (stream.match(/^&attributes\b/)) { - state.javaScriptArguments = true; - state.javaScriptArgumentsDepth = 0; - return 'keyword'; - } - } - - function indent(stream) { - if (stream.sol() && stream.eatSpace()) { - return 'indent'; - } - } - - function comment(stream, state) { - if (stream.match(/^ *\/\/(-)?([^\n]*)/)) { - state.indentOf = stream.indentation(); - state.indentToken = 'comment'; - return 'comment'; - } - } - - function colon(stream) { - if (stream.match(/^: */)) { - return 'colon'; - } - } - - function text(stream, state) { - if (stream.match(/^(?:\| ?| )([^\n]+)/)) { - return 'string'; - } - if (stream.match(/^(<[^\n]*)/, false)) { - // html string - setInnerMode(stream, state, 'htmlmixed'); - state.innerModeForLine = true; - return innerMode(stream, state, true); - } - } - - function dot(stream, state) { - if (stream.eat('.')) { - var innerMode = null; - if (state.lastTag === 'script' && state.scriptType.toLowerCase().indexOf('javascript') != -1) { - innerMode = state.scriptType.toLowerCase().replace(/"|'/g, ''); - } else if (state.lastTag === 'style') { - innerMode = 'css'; - } - setInnerMode(stream, state, innerMode); - return 'dot'; - } - } - - function fail(stream) { - stream.next(); - return null; - } - - - function setInnerMode(stream, state, mode) { - mode = CodeMirror.mimeModes[mode] || mode; - mode = config.innerModes ? config.innerModes(mode) || mode : mode; - mode = CodeMirror.mimeModes[mode] || mode; - mode = CodeMirror.getMode(config, mode); - state.indentOf = stream.indentation(); - - if (mode && mode.name !== 'null') { - state.innerMode = mode; - } else { - state.indentToken = 'string'; - } - } - function innerMode(stream, state, force) { - if (stream.indentation() > state.indentOf || (state.innerModeForLine && !stream.sol()) || force) { - if (state.innerMode) { - if (!state.innerState) { - state.innerState = state.innerMode.startState ? state.innerMode.startState(stream.indentation()) : {}; - } - return stream.hideFirstChars(state.indentOf + 2, function () { - return state.innerMode.token(stream, state.innerState) || true; - }); - } else { - stream.skipToEnd(); - return state.indentToken; - } - } else if (stream.sol()) { - state.indentOf = Infinity; - state.indentToken = null; - state.innerMode = null; - state.innerState = null; - } - } - function restOfLine(stream, state) { - if (stream.sol()) { - // if restOfLine was set at end of line, ignore it - state.restOfLine = ''; - } - if (state.restOfLine) { - stream.skipToEnd(); - var tok = state.restOfLine; - state.restOfLine = ''; - return tok; - } - } - - - function startState() { - return new State(); - } - function copyState(state) { - return state.copy(); - } - /** - * Get the next token in the stream - * - * @param {Stream} stream - * @param {State} state - */ - function nextToken(stream, state) { - var tok = innerMode(stream, state) - || restOfLine(stream, state) - || interpolationContinued(stream, state) - || includeFilteredContinued(stream, state) - || eachContinued(stream, state) - || attrsContinued(stream, state) - || javaScript(stream, state) - || javaScriptArguments(stream, state) - || callArguments(stream, state) - - || yieldStatement(stream, state) - || doctype(stream, state) - || interpolation(stream, state) - || caseStatement(stream, state) - || when(stream, state) - || defaultStatement(stream, state) - || extendsStatement(stream, state) - || append(stream, state) - || prepend(stream, state) - || block(stream, state) - || include(stream, state) - || includeFiltered(stream, state) - || mixin(stream, state) - || call(stream, state) - || conditional(stream, state) - || each(stream, state) - || whileStatement(stream, state) - || tag(stream, state) - || filter(stream, state) - || code(stream, state) - || id(stream, state) - || className(stream, state) - || attrs(stream, state) - || attributesBlock(stream, state) - || indent(stream, state) - || text(stream, state) - || comment(stream, state) - || colon(stream, state) - || dot(stream, state) - || fail(stream, state); - - return tok === true ? null : tok; - } - return { - startState: startState, - copyState: copyState, - token: nextToken - }; -}); - -CodeMirror.defineMIME('text/x-jade', 'jade'); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/javascript/index.html b/shared/html/libs/codemirror/5.0.0/mode/javascript/index.html deleted file mode 100644 index 592a133..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/javascript/index.html +++ /dev/null @@ -1,114 +0,0 @@ - - -CodeMirror: JavaScript mode - - - - - - - - - - - - -
-

JavaScript mode

- - -
- - - -

- JavaScript mode supports several configuration options: -

    -
  • json which will set the mode to expect JSON - data rather than a JavaScript program.
  • -
  • jsonld which will set the mode to expect - JSON-LD linked data rather - than a JavaScript program (demo).
  • -
  • typescript which will activate additional - syntax highlighting and some other things for TypeScript code - (demo).
  • -
  • statementIndent which (given a number) will - determine the amount of indentation to use for statements - continued on a new line.
  • -
  • wordCharacters, a regexp that indicates which - characters should be considered part of an identifier. - Defaults to /[\w$]/, which does not handle - non-ASCII identifiers. Can be set to something more elaborate - to improve Unicode support.
  • -
-

- -

MIME types defined: text/javascript, application/json, application/ld+json, text/typescript, application/typescript.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/javascript/javascript.js b/shared/html/libs/codemirror/5.0.0/mode/javascript/javascript.js deleted file mode 100644 index 3f05ac4..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/javascript/javascript.js +++ /dev/null @@ -1,692 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// TODO actually recognize syntax of TypeScript constructs - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("javascript", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var statementIndent = parserConfig.statementIndent; - var jsonldMode = parserConfig.jsonld; - var jsonMode = parserConfig.json || jsonldMode; - var isTS = parserConfig.typescript; - var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; - - // Tokenizer - - var keywords = function(){ - function kw(type) {return {type: type, style: "keyword"};} - var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); - var operator = kw("operator"), atom = {type: "atom", style: "atom"}; - - var jsKeywords = { - "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C, - "var": kw("var"), "const": kw("var"), "let": kw("var"), - "function": kw("function"), "catch": kw("catch"), - "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), - "in": operator, "typeof": operator, "instanceof": operator, - "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, - "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"), - "yield": C, "export": kw("export"), "import": kw("import"), "extends": C - }; - - // Extend the 'normal' keywords with the TypeScript language extensions - if (isTS) { - var type = {type: "variable", style: "variable-3"}; - var tsKeywords = { - // object-like things - "interface": kw("interface"), - "extends": kw("extends"), - "constructor": kw("constructor"), - - // scope modifiers - "public": kw("public"), - "private": kw("private"), - "protected": kw("protected"), - "static": kw("static"), - - // types - "string": type, "number": type, "bool": type, "any": type - }; - - for (var attr in tsKeywords) { - jsKeywords[attr] = tsKeywords[attr]; - } - } - - return jsKeywords; - }(); - - var isOperatorChar = /[+\-*&%=<>!?|~^]/; - var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/; - - function readRegexp(stream) { - var escaped = false, next, inSet = false; - while ((next = stream.next()) != null) { - if (!escaped) { - if (next == "/" && !inSet) return; - if (next == "[") inSet = true; - else if (inSet && next == "]") inSet = false; - } - escaped = !escaped && next == "\\"; - } - } - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - function ret(tp, style, cont) { - type = tp; content = cont; - return style; - } - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { - return ret("number", "number"); - } else if (ch == "." && stream.match("..")) { - return ret("spread", "meta"); - } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - return ret(ch); - } else if (ch == "=" && stream.eat(">")) { - return ret("=>", "operator"); - } else if (ch == "0" && stream.eat(/x/i)) { - stream.eatWhile(/[\da-f]/i); - return ret("number", "number"); - } else if (/\d/.test(ch)) { - stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); - return ret("number", "number"); - } else if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } else if (stream.eat("/")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } else if (state.lastType == "operator" || state.lastType == "keyword c" || - state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) { - readRegexp(stream); - stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); - return ret("regexp", "string-2"); - } else { - stream.eatWhile(isOperatorChar); - return ret("operator", "operator", stream.current()); - } - } else if (ch == "`") { - state.tokenize = tokenQuasi; - return tokenQuasi(stream, state); - } else if (ch == "#") { - stream.skipToEnd(); - return ret("error", "error"); - } else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return ret("operator", "operator", stream.current()); - } else if (wordRE.test(ch)) { - stream.eatWhile(wordRE); - var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; - return (known && state.lastType != ".") ? ret(known.type, known.style, word) : - ret("variable", "variable", word); - } - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next; - if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){ - state.tokenize = tokenBase; - return ret("jsonld-keyword", "meta"); - } - while ((next = stream.next()) != null) { - if (next == quote && !escaped) break; - escaped = !escaped && next == "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return ret("string", "string"); - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - function tokenQuasi(stream, state) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && next == "\\"; - } - return ret("quasi", "string-2", stream.current()); - } - - var brackets = "([{}])"; - // This is a crude lookahead trick to try and notice that we're - // parsing the argument patterns for a fat-arrow function before we - // actually hit the arrow token. It only works if the arrow is on - // the same line as the arguments and there's no strange noise - // (comments) in between. Fallback is to only notice when we hit the - // arrow, and not declare the arguments as locals for the arrow - // body. - function findFatArrow(stream, state) { - if (state.fatArrowAt) state.fatArrowAt = null; - var arrow = stream.string.indexOf("=>", stream.start); - if (arrow < 0) return; - - var depth = 0, sawSomething = false; - for (var pos = arrow - 1; pos >= 0; --pos) { - var ch = stream.string.charAt(pos); - var bracket = brackets.indexOf(ch); - if (bracket >= 0 && bracket < 3) { - if (!depth) { ++pos; break; } - if (--depth == 0) break; - } else if (bracket >= 3 && bracket < 6) { - ++depth; - } else if (wordRE.test(ch)) { - sawSomething = true; - } else if (/["'\/]/.test(ch)) { - return; - } else if (sawSomething && !depth) { - ++pos; - break; - } - } - if (sawSomething && !depth) state.fatArrowAt = pos; - } - - // Parser - - var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true}; - - function JSLexical(indented, column, type, align, prev, info) { - this.indented = indented; - this.column = column; - this.type = type; - this.prev = prev; - this.info = info; - if (align != null) this.align = align; - } - - function inScope(state, varname) { - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return true; - for (var cx = state.context; cx; cx = cx.prev) { - for (var v = cx.vars; v; v = v.next) - if (v.name == varname) return true; - } - } - - function parseJS(state, style, type, content, stream) { - var cc = state.cc; - // Communicate our context to the combinators. - // (Less wasteful than consing up a hundred closures on every call.) - cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style; - - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - - while(true) { - var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; - if (combinator(type, content)) { - while(cc.length && cc[cc.length - 1].lex) - cc.pop()(); - if (cx.marked) return cx.marked; - if (type == "variable" && inScope(state, content)) return "variable-2"; - return style; - } - } - } - - // Combinator utils - - var cx = {state: null, column: null, marked: null, cc: null}; - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); - } - function cont() { - pass.apply(null, arguments); - return true; - } - function register(varname) { - function inList(list) { - for (var v = list; v; v = v.next) - if (v.name == varname) return true; - return false; - } - var state = cx.state; - if (state.context) { - cx.marked = "def"; - if (inList(state.localVars)) return; - state.localVars = {name: varname, next: state.localVars}; - } else { - if (inList(state.globalVars)) return; - if (parserConfig.globalVars) - state.globalVars = {name: varname, next: state.globalVars}; - } - } - - // Combinators - - var defaultVars = {name: "this", next: {name: "arguments"}}; - function pushcontext() { - cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; - cx.state.localVars = defaultVars; - } - function popcontext() { - cx.state.localVars = cx.state.context.vars; - cx.state.context = cx.state.context.prev; - } - function pushlex(type, info) { - var result = function() { - var state = cx.state, indent = state.indented; - if (state.lexical.type == "stat") indent = state.lexical.indented; - else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev) - indent = outer.indented; - state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info); - }; - result.lex = true; - return result; - } - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type == ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - poplex.lex = true; - - function expect(wanted) { - function exp(type) { - if (type == wanted) return cont(); - else if (wanted == ";") return pass(); - else return cont(exp); - }; - return exp; - } - - function statement(type, value) { - if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); - if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); - if (type == "keyword b") return cont(pushlex("form"), statement, poplex); - if (type == "{") return cont(pushlex("}"), block, poplex); - if (type == ";") return cont(); - if (type == "if") { - if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) - cx.state.cc.pop()(); - return cont(pushlex("form"), expression, statement, poplex, maybeelse); - } - if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); - if (type == "variable") return cont(pushlex("stat"), maybelabel); - if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), - block, poplex, poplex); - if (type == "case") return cont(expression, expect(":")); - if (type == "default") return cont(expect(":")); - if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), - statement, poplex, popcontext); - if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex); - if (type == "class") return cont(pushlex("form"), className, poplex); - if (type == "export") return cont(pushlex("form"), afterExport, poplex); - if (type == "import") return cont(pushlex("form"), afterImport, poplex); - return pass(pushlex("stat"), expression, expect(";"), poplex); - } - function expression(type) { - return expressionInner(type, false); - } - function expressionNoComma(type) { - return expressionInner(type, true); - } - function expressionInner(type, noComma) { - if (cx.state.fatArrowAt == cx.stream.start) { - var body = noComma ? arrowBodyNoComma : arrowBody; - if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); - else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); - } - - var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; - if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); - if (type == "function") return cont(functiondef, maybeop); - if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); - if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop); - if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); - if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); - if (type == "{") return contCommasep(objprop, "}", null, maybeop); - if (type == "quasi") { return pass(quasi, maybeop); } - return cont(); - } - function maybeexpression(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expression); - } - function maybeexpressionNoComma(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expressionNoComma); - } - - function maybeoperatorComma(type, value) { - if (type == ",") return cont(expression); - return maybeoperatorNoComma(type, value, false); - } - function maybeoperatorNoComma(type, value, noComma) { - var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; - var expr = noComma == false ? expression : expressionNoComma; - if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); - if (type == "operator") { - if (/\+\+|--/.test(value)) return cont(me); - if (value == "?") return cont(expression, expect(":"), expr); - return cont(expr); - } - if (type == "quasi") { return pass(quasi, me); } - if (type == ";") return; - if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); - if (type == ".") return cont(property, me); - if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); - } - function quasi(type, value) { - if (type != "quasi") return pass(); - if (value.slice(value.length - 2) != "${") return cont(quasi); - return cont(expression, continueQuasi); - } - function continueQuasi(type) { - if (type == "}") { - cx.marked = "string-2"; - cx.state.tokenize = tokenQuasi; - return cont(quasi); - } - } - function arrowBody(type) { - findFatArrow(cx.stream, cx.state); - return pass(type == "{" ? statement : expression); - } - function arrowBodyNoComma(type) { - findFatArrow(cx.stream, cx.state); - return pass(type == "{" ? statement : expressionNoComma); - } - function maybelabel(type) { - if (type == ":") return cont(poplex, statement); - return pass(maybeoperatorComma, expect(";"), poplex); - } - function property(type) { - if (type == "variable") {cx.marked = "property"; return cont();} - } - function objprop(type, value) { - if (type == "variable" || cx.style == "keyword") { - cx.marked = "property"; - if (value == "get" || value == "set") return cont(getterSetter); - return cont(afterprop); - } else if (type == "number" || type == "string") { - cx.marked = jsonldMode ? "property" : (cx.style + " property"); - return cont(afterprop); - } else if (type == "jsonld-keyword") { - return cont(afterprop); - } else if (type == "[") { - return cont(expression, expect("]"), afterprop); - } - } - function getterSetter(type) { - if (type != "variable") return pass(afterprop); - cx.marked = "property"; - return cont(functiondef); - } - function afterprop(type) { - if (type == ":") return cont(expressionNoComma); - if (type == "(") return pass(functiondef); - } - function commasep(what, end) { - function proceed(type) { - if (type == ",") { - var lex = cx.state.lexical; - if (lex.info == "call") lex.pos = (lex.pos || 0) + 1; - return cont(what, proceed); - } - if (type == end) return cont(); - return cont(expect(end)); - } - return function(type) { - if (type == end) return cont(); - return pass(what, proceed); - }; - } - function contCommasep(what, end, info) { - for (var i = 3; i < arguments.length; i++) - cx.cc.push(arguments[i]); - return cont(pushlex(end, info), commasep(what, end), poplex); - } - function block(type) { - if (type == "}") return cont(); - return pass(statement, block); - } - function maybetype(type) { - if (isTS && type == ":") return cont(typedef); - } - function typedef(type) { - if (type == "variable"){cx.marked = "variable-3"; return cont();} - } - function vardef() { - return pass(pattern, maybetype, maybeAssign, vardefCont); - } - function pattern(type, value) { - if (type == "variable") { register(value); return cont(); } - if (type == "[") return contCommasep(pattern, "]"); - if (type == "{") return contCommasep(proppattern, "}"); - } - function proppattern(type, value) { - if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { - register(value); - return cont(maybeAssign); - } - if (type == "variable") cx.marked = "property"; - return cont(expect(":"), pattern, maybeAssign); - } - function maybeAssign(_type, value) { - if (value == "=") return cont(expressionNoComma); - } - function vardefCont(type) { - if (type == ",") return cont(vardef); - } - function maybeelse(type, value) { - if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex); - } - function forspec(type) { - if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); - } - function forspec1(type) { - if (type == "var") return cont(vardef, expect(";"), forspec2); - if (type == ";") return cont(forspec2); - if (type == "variable") return cont(formaybeinof); - return pass(expression, expect(";"), forspec2); - } - function formaybeinof(_type, value) { - if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } - return cont(maybeoperatorComma, forspec2); - } - function forspec2(type, value) { - if (type == ";") return cont(forspec3); - if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } - return pass(expression, expect(";"), forspec3); - } - function forspec3(type) { - if (type != ")") cont(expression); - } - function functiondef(type, value) { - if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} - if (type == "variable") {register(value); return cont(functiondef);} - if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext); - } - function funarg(type) { - if (type == "spread") return cont(funarg); - return pass(pattern, maybetype); - } - function className(type, value) { - if (type == "variable") {register(value); return cont(classNameAfter);} - } - function classNameAfter(type, value) { - if (value == "extends") return cont(expression, classNameAfter); - if (type == "{") return cont(pushlex("}"), classBody, poplex); - } - function classBody(type, value) { - if (type == "variable" || cx.style == "keyword") { - cx.marked = "property"; - if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody); - return cont(functiondef, classBody); - } - if (value == "*") { - cx.marked = "keyword"; - return cont(classBody); - } - if (type == ";") return cont(classBody); - if (type == "}") return cont(); - } - function classGetterSetter(type) { - if (type != "variable") return pass(); - cx.marked = "property"; - return cont(); - } - function afterModule(type, value) { - if (type == "string") return cont(statement); - if (type == "variable") { register(value); return cont(maybeFrom); } - } - function afterExport(_type, value) { - if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); } - if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); } - return pass(statement); - } - function afterImport(type) { - if (type == "string") return cont(); - return pass(importSpec, maybeFrom); - } - function importSpec(type, value) { - if (type == "{") return contCommasep(importSpec, "}"); - if (type == "variable") register(value); - return cont(); - } - function maybeFrom(_type, value) { - if (value == "from") { cx.marked = "keyword"; return cont(expression); } - } - function arrayLiteral(type) { - if (type == "]") return cont(); - return pass(expressionNoComma, maybeArrayComprehension); - } - function maybeArrayComprehension(type) { - if (type == "for") return pass(comprehension, expect("]")); - if (type == ",") return cont(commasep(maybeexpressionNoComma, "]")); - return pass(commasep(expressionNoComma, "]")); - } - function comprehension(type) { - if (type == "for") return cont(forspec, comprehension); - if (type == "if") return cont(expression, comprehension); - } - - function isContinuedStatement(state, textAfter) { - return state.lastType == "operator" || state.lastType == "," || - isOperatorChar.test(textAfter.charAt(0)) || - /[,.]/.test(textAfter.charAt(0)); - } - - // Interface - - return { - startState: function(basecolumn) { - var state = { - tokenize: tokenBase, - lastType: "sof", - cc: [], - lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), - localVars: parserConfig.localVars, - context: parserConfig.localVars && {vars: parserConfig.localVars}, - indented: 0 - }; - if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") - state.globalVars = parserConfig.globalVars; - return state; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - findFatArrow(stream, state); - } - if (state.tokenize != tokenComment && stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (type == "comment") return style; - state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type; - return parseJS(state, style, type, content, stream); - }, - - indent: function(state, textAfter) { - if (state.tokenize == tokenComment) return CodeMirror.Pass; - if (state.tokenize != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; - // Kludge to prevent 'maybelse' from blocking lexical scope pops - if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { - var c = state.cc[i]; - if (c == poplex) lexical = lexical.prev; - else if (c != maybeelse) break; - } - if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; - if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") - lexical = lexical.prev; - var type = lexical.type, closing = firstChar == type; - - if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); - else if (type == "form" && firstChar == "{") return lexical.indented; - else if (type == "form") return lexical.indented + indentUnit; - else if (type == "stat") - return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0); - else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false) - return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); - else if (lexical.align) return lexical.column + (closing ? 0 : 1); - else return lexical.indented + (closing ? 0 : indentUnit); - }, - - electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, - blockCommentStart: jsonMode ? null : "/*", - blockCommentEnd: jsonMode ? null : "*/", - lineComment: jsonMode ? null : "//", - fold: "brace", - - helperType: jsonMode ? "json" : "javascript", - jsonldMode: jsonldMode, - jsonMode: jsonMode - }; -}); - -CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/); - -CodeMirror.defineMIME("text/javascript", "javascript"); -CodeMirror.defineMIME("text/ecmascript", "javascript"); -CodeMirror.defineMIME("application/javascript", "javascript"); -CodeMirror.defineMIME("application/x-javascript", "javascript"); -CodeMirror.defineMIME("application/ecmascript", "javascript"); -CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); -CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); -CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true}); -CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); -CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/javascript/json-ld.html b/shared/html/libs/codemirror/5.0.0/mode/javascript/json-ld.html deleted file mode 100644 index 3a37f0b..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/javascript/json-ld.html +++ /dev/null @@ -1,72 +0,0 @@ - - -CodeMirror: JSON-LD mode - - - - - - - - - - - - -
-

JSON-LD mode

- - -
- - - -

This is a specialization of the JavaScript mode.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/javascript/test.js b/shared/html/libs/codemirror/5.0.0/mode/javascript/test.js deleted file mode 100644 index 91b0e89..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/javascript/test.js +++ /dev/null @@ -1,200 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "javascript"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("locals", - "[keyword function] [variable foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }"); - - MT("comma-and-binop", - "[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }"); - - MT("destructuring", - "([keyword function]([def a], [[[def b], [def c] ]]) {", - " [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);", - " [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];", - "})();"); - - MT("class_body", - "[keyword class] [variable Foo] {", - " [property constructor]() {}", - " [property sayName]() {", - " [keyword return] [string-2 `foo${][variable foo][string-2 }oo`];", - " }", - "}"); - - MT("class", - "[keyword class] [variable Point] [keyword extends] [variable SuperThing] {", - " [property get] [property prop]() { [keyword return] [number 24]; }", - " [property constructor]([def x], [def y]) {", - " [keyword super]([string 'something']);", - " [keyword this].[property x] [operator =] [variable-2 x];", - " }", - "}"); - - MT("module", - "[keyword module] [string 'foo'] {", - " [keyword export] [keyword let] [def x] [operator =] [number 42];", - " [keyword export] [keyword *] [keyword from] [string 'somewhere'];", - "}"); - - MT("import", - "[keyword function] [variable foo]() {", - " [keyword import] [def $] [keyword from] [string 'jquery'];", - " [keyword module] [def crypto] [keyword from] [string 'crypto'];", - " [keyword import] { [def encrypt], [def decrypt] } [keyword from] [string 'crypto'];", - "}"); - - MT("const", - "[keyword function] [variable f]() {", - " [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];", - "}"); - - MT("for/of", - "[keyword for]([keyword let] [variable of] [keyword of] [variable something]) {}"); - - MT("generator", - "[keyword function*] [variable repeat]([def n]) {", - " [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])", - " [keyword yield] [variable-2 i];", - "}"); - - MT("quotedStringAddition", - "[keyword let] [variable f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];"); - - MT("quotedFatArrow", - "[keyword let] [variable f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c];"); - - MT("fatArrow", - "[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);", - "[variable a];", // No longer in scope - "[keyword let] [variable f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];", - "[variable c];"); - - MT("spread", - "[keyword function] [variable f]([def a], [meta ...][def b]) {", - " [variable something]([variable-2 a], [meta ...][variable-2 b]);", - "}"); - - MT("comprehension", - "[keyword function] [variable f]() {", - " [[([variable x] [operator +] [number 1]) [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];", - " ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] [operator ===] [string 'blue']));", - "}"); - - MT("quasi", - "[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]"); - - MT("quasi_no_function", - "[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]"); - - MT("indent_statement", - "[keyword var] [variable x] [operator =] [number 10]", - "[variable x] [operator +=] [variable y] [operator +]", - " [atom Infinity]", - "[keyword debugger];"); - - MT("indent_if", - "[keyword if] ([number 1])", - " [keyword break];", - "[keyword else] [keyword if] ([number 2])", - " [keyword continue];", - "[keyword else]", - " [number 10];", - "[keyword if] ([number 1]) {", - " [keyword break];", - "} [keyword else] [keyword if] ([number 2]) {", - " [keyword continue];", - "} [keyword else] {", - " [number 10];", - "}"); - - MT("indent_for", - "[keyword for] ([keyword var] [variable i] [operator =] [number 0];", - " [variable i] [operator <] [number 100];", - " [variable i][operator ++])", - " [variable doSomething]([variable i]);", - "[keyword debugger];"); - - MT("indent_c_style", - "[keyword function] [variable foo]()", - "{", - " [keyword debugger];", - "}"); - - MT("indent_else", - "[keyword for] (;;)", - " [keyword if] ([variable foo])", - " [keyword if] ([variable bar])", - " [number 1];", - " [keyword else]", - " [number 2];", - " [keyword else]", - " [number 3];"); - - MT("indent_funarg", - "[variable foo]([number 10000],", - " [keyword function]([def a]) {", - " [keyword debugger];", - "};"); - - MT("indent_below_if", - "[keyword for] (;;)", - " [keyword if] ([variable foo])", - " [number 1];", - "[number 2];"); - - MT("multilinestring", - "[keyword var] [variable x] [operator =] [string 'foo\\]", - "[string bar'];"); - - MT("scary_regexp", - "[string-2 /foo[[/]]bar/];"); - - MT("indent_strange_array", - "[keyword var] [variable x] [operator =] [[", - " [number 1],,", - " [number 2],", - "]];", - "[number 10];"); - - var jsonld_mode = CodeMirror.getMode( - {indentUnit: 2}, - {name: "javascript", jsonld: true} - ); - function LD(name) { - test.mode(name, jsonld_mode, Array.prototype.slice.call(arguments, 1)); - } - - LD("json_ld_keywords", - '{', - ' [meta "@context"]: {', - ' [meta "@base"]: [string "http://example.com"],', - ' [meta "@vocab"]: [string "http://xmlns.com/foaf/0.1/"],', - ' [property "likesFlavor"]: {', - ' [meta "@container"]: [meta "@list"]', - ' [meta "@reverse"]: [string "@beFavoriteOf"]', - ' },', - ' [property "nick"]: { [meta "@container"]: [meta "@set"] },', - ' [property "nick"]: { [meta "@container"]: [meta "@index"] }', - ' },', - ' [meta "@graph"]: [[ {', - ' [meta "@id"]: [string "http://dbpedia.org/resource/John_Lennon"],', - ' [property "name"]: [string "John Lennon"],', - ' [property "modified"]: {', - ' [meta "@value"]: [string "2010-05-29T14:17:39+02:00"],', - ' [meta "@type"]: [string "http://www.w3.org/2001/XMLSchema#dateTime"]', - ' }', - ' } ]]', - '}'); - - LD("json_ld_fake", - '{', - ' [property "@fake"]: [string "@fake"],', - ' [property "@contextual"]: [string "@identifier"],', - ' [property "user@domain.com"]: [string "@graphical"],', - ' [property "@ID"]: [string "@@ID"]', - '}'); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/javascript/typescript.html b/shared/html/libs/codemirror/5.0.0/mode/javascript/typescript.html deleted file mode 100644 index 2cfc538..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/javascript/typescript.html +++ /dev/null @@ -1,61 +0,0 @@ - - -CodeMirror: TypeScript mode - - - - - - - - - -
-

TypeScript mode

- - -
- - - -

This is a specialization of the JavaScript mode.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/jinja2/index.html b/shared/html/libs/codemirror/5.0.0/mode/jinja2/index.html deleted file mode 100644 index 5a70e91..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/jinja2/index.html +++ /dev/null @@ -1,54 +0,0 @@ - - -CodeMirror: Jinja2 mode - - - - - - - - - -
-

Jinja2 mode

-
- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/jinja2/jinja2.js b/shared/html/libs/codemirror/5.0.0/mode/jinja2/jinja2.js deleted file mode 100644 index ed19558..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/jinja2/jinja2.js +++ /dev/null @@ -1,142 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("jinja2", function() { - var keywords = ["and", "as", "block", "endblock", "by", "cycle", "debug", "else", "elif", - "extends", "filter", "endfilter", "firstof", "for", - "endfor", "if", "endif", "ifchanged", "endifchanged", - "ifequal", "endifequal", "ifnotequal", - "endifnotequal", "in", "include", "load", "not", "now", "or", - "parsed", "regroup", "reversed", "spaceless", - "endspaceless", "ssi", "templatetag", "openblock", - "closeblock", "openvariable", "closevariable", - "openbrace", "closebrace", "opencomment", - "closecomment", "widthratio", "url", "with", "endwith", - "get_current_language", "trans", "endtrans", "noop", "blocktrans", - "endblocktrans", "get_available_languages", - "get_current_language_bidi", "plural"], - operator = /^[+\-*&%=<>!?|~^]/, - sign = /^[:\[\(\{]/, - atom = ["true", "false"], - number = /^(\d[+\-\*\/])?\d+(\.\d+)?/; - - keywords = new RegExp("((" + keywords.join(")|(") + "))\\b"); - atom = new RegExp("((" + atom.join(")|(") + "))\\b"); - - function tokenBase (stream, state) { - var ch = stream.peek(); - - //Comment - if (state.incomment) { - if(!stream.skipTo("#}")) { - stream.skipToEnd(); - } else { - stream.eatWhile(/\#|}/); - state.incomment = false; - } - return "comment"; - //Tag - } else if (state.intag) { - //After operator - if(state.operator) { - state.operator = false; - if(stream.match(atom)) { - return "atom"; - } - if(stream.match(number)) { - return "number"; - } - } - //After sign - if(state.sign) { - state.sign = false; - if(stream.match(atom)) { - return "atom"; - } - if(stream.match(number)) { - return "number"; - } - } - - if(state.instring) { - if(ch == state.instring) { - state.instring = false; - } - stream.next(); - return "string"; - } else if(ch == "'" || ch == '"') { - state.instring = ch; - stream.next(); - return "string"; - } else if(stream.match(state.intag + "}") || stream.eat("-") && stream.match(state.intag + "}")) { - state.intag = false; - return "tag"; - } else if(stream.match(operator)) { - state.operator = true; - return "operator"; - } else if(stream.match(sign)) { - state.sign = true; - } else { - if(stream.eat(" ") || stream.sol()) { - if(stream.match(keywords)) { - return "keyword"; - } - if(stream.match(atom)) { - return "atom"; - } - if(stream.match(number)) { - return "number"; - } - if(stream.sol()) { - stream.next(); - } - } else { - stream.next(); - } - - } - return "variable"; - } else if (stream.eat("{")) { - if (ch = stream.eat("#")) { - state.incomment = true; - if(!stream.skipTo("#}")) { - stream.skipToEnd(); - } else { - stream.eatWhile(/\#|}/); - state.incomment = false; - } - return "comment"; - //Open tag - } else if (ch = stream.eat(/\{|%/)) { - //Cache close tag - state.intag = ch; - if(ch == "{") { - state.intag = "}"; - } - stream.eat("-"); - return "tag"; - } - } - stream.next(); - }; - - return { - startState: function () { - return {tokenize: tokenBase}; - }, - token: function (stream, state) { - return state.tokenize(stream, state); - } - }; - }); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/julia/index.html b/shared/html/libs/codemirror/5.0.0/mode/julia/index.html deleted file mode 100644 index e1492c2..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/julia/index.html +++ /dev/null @@ -1,195 +0,0 @@ - - -CodeMirror: Julia mode - - - - - - - - - -
-

Julia mode

- -
- - -

MIME types defined: text/x-julia.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/julia/julia.js b/shared/html/libs/codemirror/5.0.0/mode/julia/julia.js deleted file mode 100644 index e854988..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/julia/julia.js +++ /dev/null @@ -1,301 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("julia", function(_conf, parserConf) { - var ERRORCLASS = 'error'; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); - } - - var operators = parserConf.operators || /^\.?[|&^\\%*+\-<>!=\/]=?|\?|~|:|\$|\.[<>]|<<=?|>>>?=?|\.[<>=]=|->?|\/\/|\bin\b/; - var delimiters = parserConf.delimiters || /^[;,()[\]{}]/; - var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*!*/; - var blockOpeners = ["begin", "function", "type", "immutable", "let", "macro", "for", "while", "quote", "if", "else", "elseif", "try", "finally", "catch", "do"]; - var blockClosers = ["end", "else", "elseif", "catch", "finally"]; - var keywordList = ['if', 'else', 'elseif', 'while', 'for', 'begin', 'let', 'end', 'do', 'try', 'catch', 'finally', 'return', 'break', 'continue', 'global', 'local', 'const', 'export', 'import', 'importall', 'using', 'function', 'macro', 'module', 'baremodule', 'type', 'immutable', 'quote', 'typealias', 'abstract', 'bitstype', 'ccall']; - var builtinList = ['true', 'false', 'enumerate', 'open', 'close', 'nothing', 'NaN', 'Inf', 'print', 'println', 'Int', 'Int8', 'Uint8', 'Int16', 'Uint16', 'Int32', 'Uint32', 'Int64', 'Uint64', 'Int128', 'Uint128', 'Bool', 'Char', 'Float16', 'Float32', 'Float64', 'Array', 'Vector', 'Matrix', 'String', 'UTF8String', 'ASCIIString', 'error', 'warn', 'info', '@printf']; - - //var stringPrefixes = new RegExp("^[br]?('|\")") - var stringPrefixes = /^(`|'|"{3}|([br]?"))/; - var keywords = wordRegexp(keywordList); - var builtins = wordRegexp(builtinList); - var openers = wordRegexp(blockOpeners); - var closers = wordRegexp(blockClosers); - var macro = /^@[_A-Za-z][_A-Za-z0-9]*/; - var symbol = /^:[_A-Za-z][_A-Za-z0-9]*/; - var indentInfo = null; - - function in_array(state) { - var ch = cur_scope(state); - if(ch=="[" || ch=="{") { - return true; - } - else { - return false; - } - } - - function cur_scope(state) { - if(state.scopes.length==0) { - return null; - } - return state.scopes[state.scopes.length - 1]; - } - - // tokenizers - function tokenBase(stream, state) { - // Handle scope changes - var leaving_expr = state.leaving_expr; - if(stream.sol()) { - leaving_expr = false; - } - state.leaving_expr = false; - if(leaving_expr) { - if(stream.match(/^'+/)) { - return 'operator'; - } - - } - - if(stream.match(/^\.{2,3}/)) { - return 'operator'; - } - - if (stream.eatSpace()) { - return null; - } - - var ch = stream.peek(); - // Handle Comments - if (ch === '#') { - stream.skipToEnd(); - return 'comment'; - } - if(ch==='[') { - state.scopes.push("["); - } - - if(ch==='{') { - state.scopes.push("{"); - } - - var scope=cur_scope(state); - - if(scope==='[' && ch===']') { - state.scopes.pop(); - state.leaving_expr=true; - } - - if(scope==='{' && ch==='}') { - state.scopes.pop(); - state.leaving_expr=true; - } - - if(ch===')') { - state.leaving_expr = true; - } - - var match; - if(!in_array(state) && (match=stream.match(openers, false))) { - state.scopes.push(match); - } - - if(!in_array(state) && stream.match(closers, false)) { - state.scopes.pop(); - } - - if(in_array(state)) { - if(stream.match(/^end/)) { - return 'number'; - } - - } - - if(stream.match(/^=>/)) { - return 'operator'; - } - - - // Handle Number Literals - if (stream.match(/^[0-9\.]/, false)) { - var imMatcher = RegExp(/^im\b/); - var floatLiteral = false; - // Floats - if (stream.match(/^\d*\.(?!\.)\d+([ef][\+\-]?\d+)?/i)) { floatLiteral = true; } - if (stream.match(/^\d+\.(?!\.)\d*/)) { floatLiteral = true; } - if (stream.match(/^\.\d+/)) { floatLiteral = true; } - if (floatLiteral) { - // Float literals may be "imaginary" - stream.match(imMatcher); - state.leaving_expr = true; - return 'number'; - } - // Integers - var intLiteral = false; - // Hex - if (stream.match(/^0x[0-9a-f]+/i)) { intLiteral = true; } - // Binary - if (stream.match(/^0b[01]+/i)) { intLiteral = true; } - // Octal - if (stream.match(/^0o[0-7]+/i)) { intLiteral = true; } - // Decimal - if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) { - intLiteral = true; - } - // Zero by itself with no other piece of number. - if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; } - if (intLiteral) { - // Integer literals may be "long" - stream.match(imMatcher); - state.leaving_expr = true; - return 'number'; - } - } - - if(stream.match(/^(::)|(<:)/)) { - return 'operator'; - } - - // Handle symbols - if(!leaving_expr && stream.match(symbol)) { - return 'string'; - } - - // Handle operators and Delimiters - if (stream.match(operators)) { - return 'operator'; - } - - - // Handle Strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenStringFactory(stream.current()); - return state.tokenize(stream, state); - } - - if (stream.match(macro)) { - return 'meta'; - } - - - if (stream.match(delimiters)) { - return null; - } - - if (stream.match(keywords)) { - return 'keyword'; - } - - if (stream.match(builtins)) { - return 'builtin'; - } - - - if (stream.match(identifiers)) { - state.leaving_expr=true; - return 'variable'; - } - // Handle non-detected items - stream.next(); - return ERRORCLASS; - } - - function tokenStringFactory(delimiter) { - while ('rub'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) { - delimiter = delimiter.substr(1); - } - var singleline = delimiter.length == 1; - var OUTCLASS = 'string'; - - function tokenString(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^'"\\]/); - if (stream.eat('\\')) { - stream.next(); - if (singleline && stream.eol()) { - return OUTCLASS; - } - } else if (stream.match(delimiter)) { - state.tokenize = tokenBase; - return OUTCLASS; - } else { - stream.eat(/['"]/); - } - } - if (singleline) { - if (parserConf.singleLineStringErrors) { - return ERRORCLASS; - } else { - state.tokenize = tokenBase; - } - } - return OUTCLASS; - } - tokenString.isString = true; - return tokenString; - } - - function tokenLexer(stream, state) { - indentInfo = null; - var style = state.tokenize(stream, state); - var current = stream.current(); - - // Handle '.' connected identifiers - if (current === '.') { - style = stream.match(identifiers, false) ? null : ERRORCLASS; - if (style === null && state.lastStyle === 'meta') { - // Apply 'meta' style to '.' connected identifiers when - // appropriate. - style = 'meta'; - } - return style; - } - - return style; - } - - var external = { - startState: function() { - return { - tokenize: tokenBase, - scopes: [], - leaving_expr: false - }; - }, - - token: function(stream, state) { - var style = tokenLexer(stream, state); - state.lastStyle = style; - return style; - }, - - indent: function(state, textAfter) { - var delta = 0; - if(textAfter=="end" || textAfter=="]" || textAfter=="}" || textAfter=="else" || textAfter=="elseif" || textAfter=="catch" || textAfter=="finally") { - delta = -1; - } - return (state.scopes.length + delta) * 4; - }, - - lineComment: "#", - fold: "indent", - electricChars: "edlsifyh]}" - }; - return external; -}); - - -CodeMirror.defineMIME("text/x-julia", "julia"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/kotlin/index.html b/shared/html/libs/codemirror/5.0.0/mode/kotlin/index.html deleted file mode 100644 index 859e109..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/kotlin/index.html +++ /dev/null @@ -1,89 +0,0 @@ - - -CodeMirror: Kotlin mode - - - - - - - - - -
-

Kotlin mode

- - -
- - -

Mode for Kotlin (http://kotlin.jetbrains.org/)

-

Developed by Hadi Hariri (https://github.com/hhariri).

-

MIME type defined: text/x-kotlin.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/kotlin/kotlin.js b/shared/html/libs/codemirror/5.0.0/mode/kotlin/kotlin.js deleted file mode 100644 index 73c84f6..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/kotlin/kotlin.js +++ /dev/null @@ -1,280 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("kotlin", function (config, parserConfig) { - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var multiLineStrings = parserConfig.multiLineStrings; - - var keywords = words( - "package continue return object while break class data trait throw super" + - " when type this else This try val var fun for is in if do as true false null get set"); - var softKeywords = words("import" + - " where by get set abstract enum open annotation override private public internal" + - " protected catch out vararg inline finally final ref"); - var blockKeywords = words("catch class do else finally for if where try while enum"); - var atoms = words("null true false this"); - - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") { - return startString(ch, stream, state); - } - // Wildcard import w/o trailing semicolon (import smth.*) - if (ch == "." && stream.eat("*")) { - return "word"; - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null; - } - if (/\d/.test(ch)) { - if (stream.eat(/eE/)) { - stream.eat(/\+\-/); - stream.eatWhile(/\d/); - } - return "number"; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize.push(tokenComment); - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - if (expectExpression(state.lastToken)) { - return startString(ch, stream, state); - } - } - // Commented - if (ch == "-" && stream.eat(">")) { - curPunc = "->"; - return null; - } - if (/[\-+*&%=<>!?|\/~]/.test(ch)) { - stream.eatWhile(/[\-+*&%=<>|~]/); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - - var cur = stream.current(); - if (atoms.propertyIsEnumerable(cur)) { - return "atom"; - } - if (softKeywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "softKeyword"; - } - - if (keywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; - } - return "word"; - } - - tokenBase.isBase = true; - - function startString(quote, stream, state) { - var tripleQuoted = false; - if (quote != "/" && stream.eat(quote)) { - if (stream.eat(quote)) tripleQuoted = true; - else return "string"; - } - function t(stream, state) { - var escaped = false, next, end = !tripleQuoted; - - while ((next = stream.next()) != null) { - if (next == quote && !escaped) { - if (!tripleQuoted) { - break; - } - if (stream.match(quote + quote)) { - end = true; - break; - } - } - - if (quote == '"' && next == "$" && !escaped && stream.eat("{")) { - state.tokenize.push(tokenBaseUntilBrace()); - return "string"; - } - - if (next == "$" && !escaped && !stream.eat(" ")) { - state.tokenize.push(tokenBaseUntilSpace()); - return "string"; - } - escaped = !escaped && next == "\\"; - } - if (multiLineStrings) - state.tokenize.push(t); - if (end) state.tokenize.pop(); - return "string"; - } - - state.tokenize.push(t); - return t(stream, state); - } - - function tokenBaseUntilBrace() { - var depth = 1; - - function t(stream, state) { - if (stream.peek() == "}") { - depth--; - if (depth == 0) { - state.tokenize.pop(); - return state.tokenize[state.tokenize.length - 1](stream, state); - } - } else if (stream.peek() == "{") { - depth++; - } - return tokenBase(stream, state); - } - - t.isBase = true; - return t; - } - - function tokenBaseUntilSpace() { - function t(stream, state) { - if (stream.eat(/[\w]/)) { - var isWord = stream.eatWhile(/[\w]/); - if (isWord) { - state.tokenize.pop(); - return "word"; - } - } - state.tokenize.pop(); - return "string"; - } - - t.isBase = true; - return t; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize.pop(); - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function expectExpression(last) { - return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) || - last == "newstatement" || last == "keyword" || last == "proplabel"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function (basecolumn) { - return { - tokenize: [tokenBase], - context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false), - indented: 0, - startOfLine: true, - lastToken: null - }; - }, - - token: function (stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - // Automatic semicolon insertion - if (ctx.type == "statement" && !expectExpression(state.lastToken)) { - popContext(state); - ctx = state.context; - } - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = state.tokenize[state.tokenize.length - 1](stream, state); - if (style == "comment") return style; - if (ctx.align == null) ctx.align = true; - if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state); - // Handle indentation for {x -> \n ... } - else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") { - popContext(state); - state.context.align = false; - } - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - state.lastToken = curPunc || style; - return style; - }, - - indent: function (state, textAfter) { - if (!state.tokenize[state.tokenize.length - 1].isBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), ctx = state.context; - if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev; - var closing = firstChar == ctx.type; - if (ctx.type == "statement") { - return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit); - } - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : config.indentUnit); - }, - - electricChars: "{}" - }; -}); - -CodeMirror.defineMIME("text/x-kotlin", "kotlin"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/livescript/index.html b/shared/html/libs/codemirror/5.0.0/mode/livescript/index.html deleted file mode 100644 index f415479..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/livescript/index.html +++ /dev/null @@ -1,459 +0,0 @@ - - -CodeMirror: LiveScript mode - - - - - - - - - - -
-

LiveScript mode

-
- - -

MIME types defined: text/x-livescript.

- -

The LiveScript mode was written by Kenneth Bentley.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/livescript/livescript.js b/shared/html/libs/codemirror/5.0.0/mode/livescript/livescript.js deleted file mode 100644 index 55882ef..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/livescript/livescript.js +++ /dev/null @@ -1,280 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Link to the project's GitHub page: - * https://github.com/duralog/CodeMirror - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode('livescript', function(){ - var tokenBase = function(stream, state) { - var next_rule = state.next || "start"; - if (next_rule) { - state.next = state.next; - var nr = Rules[next_rule]; - if (nr.splice) { - for (var i$ = 0; i$ < nr.length; ++i$) { - var r = nr[i$], m; - if (r.regex && (m = stream.match(r.regex))) { - state.next = r.next || state.next; - return r.token; - } - } - stream.next(); - return 'error'; - } - if (stream.match(r = Rules[next_rule])) { - if (r.regex && stream.match(r.regex)) { - state.next = r.next; - return r.token; - } else { - stream.next(); - return 'error'; - } - } - } - stream.next(); - return 'error'; - }; - var external = { - startState: function(){ - return { - next: 'start', - lastToken: null - }; - }, - token: function(stream, state){ - while (stream.pos == stream.start) - var style = tokenBase(stream, state); - state.lastToken = { - style: style, - indent: stream.indentation(), - content: stream.current() - }; - return style.replace(/\./g, ' '); - }, - indent: function(state){ - var indentation = state.lastToken.indent; - if (state.lastToken.content.match(indenter)) { - indentation += 2; - } - return indentation; - } - }; - return external; - }); - - var identifier = '(?![\\d\\s])[$\\w\\xAA-\\uFFDC](?:(?!\\s)[$\\w\\xAA-\\uFFDC]|-[A-Za-z])*'; - var indenter = RegExp('(?:[({[=:]|[-~]>|\\b(?:e(?:lse|xport)|d(?:o|efault)|t(?:ry|hen)|finally|import(?:\\s*all)?|const|var|let|new|catch(?:\\s*' + identifier + ')?))\\s*$'); - var keywordend = '(?![$\\w]|-[A-Za-z]|\\s*:(?![:=]))'; - var stringfill = { - token: 'string', - regex: '.+' - }; - var Rules = { - start: [ - { - token: 'comment.doc', - regex: '/\\*', - next: 'comment' - }, { - token: 'comment', - regex: '#.*' - }, { - token: 'keyword', - regex: '(?:t(?:h(?:is|row|en)|ry|ypeof!?)|c(?:on(?:tinue|st)|a(?:se|tch)|lass)|i(?:n(?:stanceof)?|mp(?:ort(?:\\s+all)?|lements)|[fs])|d(?:e(?:fault|lete|bugger)|o)|f(?:or(?:\\s+own)?|inally|unction)|s(?:uper|witch)|e(?:lse|x(?:tends|port)|val)|a(?:nd|rguments)|n(?:ew|ot)|un(?:less|til)|w(?:hile|ith)|o[fr]|return|break|let|var|loop)' + keywordend - }, { - token: 'constant.language', - regex: '(?:true|false|yes|no|on|off|null|void|undefined)' + keywordend - }, { - token: 'invalid.illegal', - regex: '(?:p(?:ackage|r(?:ivate|otected)|ublic)|i(?:mplements|nterface)|enum|static|yield)' + keywordend - }, { - token: 'language.support.class', - regex: '(?:R(?:e(?:gExp|ferenceError)|angeError)|S(?:tring|yntaxError)|E(?:rror|valError)|Array|Boolean|Date|Function|Number|Object|TypeError|URIError)' + keywordend - }, { - token: 'language.support.function', - regex: '(?:is(?:NaN|Finite)|parse(?:Int|Float)|Math|JSON|(?:en|de)codeURI(?:Component)?)' + keywordend - }, { - token: 'variable.language', - regex: '(?:t(?:hat|il|o)|f(?:rom|allthrough)|it|by|e)' + keywordend - }, { - token: 'identifier', - regex: identifier + '\\s*:(?![:=])' - }, { - token: 'variable', - regex: identifier - }, { - token: 'keyword.operator', - regex: '(?:\\.{3}|\\s+\\?)' - }, { - token: 'keyword.variable', - regex: '(?:@+|::|\\.\\.)', - next: 'key' - }, { - token: 'keyword.operator', - regex: '\\.\\s*', - next: 'key' - }, { - token: 'string', - regex: '\\\\\\S[^\\s,;)}\\]]*' - }, { - token: 'string.doc', - regex: '\'\'\'', - next: 'qdoc' - }, { - token: 'string.doc', - regex: '"""', - next: 'qqdoc' - }, { - token: 'string', - regex: '\'', - next: 'qstring' - }, { - token: 'string', - regex: '"', - next: 'qqstring' - }, { - token: 'string', - regex: '`', - next: 'js' - }, { - token: 'string', - regex: '<\\[', - next: 'words' - }, { - token: 'string.regex', - regex: '//', - next: 'heregex' - }, { - token: 'string.regex', - regex: '\\/(?:[^[\\/\\n\\\\]*(?:(?:\\\\.|\\[[^\\]\\n\\\\]*(?:\\\\.[^\\]\\n\\\\]*)*\\])[^[\\/\\n\\\\]*)*)\\/[gimy$]{0,4}', - next: 'key' - }, { - token: 'constant.numeric', - regex: '(?:0x[\\da-fA-F][\\da-fA-F_]*|(?:[2-9]|[12]\\d|3[0-6])r[\\da-zA-Z][\\da-zA-Z_]*|(?:\\d[\\d_]*(?:\\.\\d[\\d_]*)?|\\.\\d[\\d_]*)(?:e[+-]?\\d[\\d_]*)?[\\w$]*)' - }, { - token: 'lparen', - regex: '[({[]' - }, { - token: 'rparen', - regex: '[)}\\]]', - next: 'key' - }, { - token: 'keyword.operator', - regex: '\\S+' - }, { - token: 'text', - regex: '\\s+' - } - ], - heregex: [ - { - token: 'string.regex', - regex: '.*?//[gimy$?]{0,4}', - next: 'start' - }, { - token: 'string.regex', - regex: '\\s*#{' - }, { - token: 'comment.regex', - regex: '\\s+(?:#.*)?' - }, { - token: 'string.regex', - regex: '\\S+' - } - ], - key: [ - { - token: 'keyword.operator', - regex: '[.?@!]+' - }, { - token: 'identifier', - regex: identifier, - next: 'start' - }, { - token: 'text', - regex: '', - next: 'start' - } - ], - comment: [ - { - token: 'comment.doc', - regex: '.*?\\*/', - next: 'start' - }, { - token: 'comment.doc', - regex: '.+' - } - ], - qdoc: [ - { - token: 'string', - regex: ".*?'''", - next: 'key' - }, stringfill - ], - qqdoc: [ - { - token: 'string', - regex: '.*?"""', - next: 'key' - }, stringfill - ], - qstring: [ - { - token: 'string', - regex: '[^\\\\\']*(?:\\\\.[^\\\\\']*)*\'', - next: 'key' - }, stringfill - ], - qqstring: [ - { - token: 'string', - regex: '[^\\\\"]*(?:\\\\.[^\\\\"]*)*"', - next: 'key' - }, stringfill - ], - js: [ - { - token: 'string', - regex: '[^\\\\`]*(?:\\\\.[^\\\\`]*)*`', - next: 'key' - }, stringfill - ], - words: [ - { - token: 'string', - regex: '.*?\\]>', - next: 'key' - }, stringfill - ] - }; - for (var idx in Rules) { - var r = Rules[idx]; - if (r.splice) { - for (var i = 0, len = r.length; i < len; ++i) { - var rr = r[i]; - if (typeof rr.regex === 'string') { - Rules[idx][i].regex = new RegExp('^' + rr.regex); - } - } - } else if (typeof rr.regex === 'string') { - Rules[idx].regex = new RegExp('^' + r.regex); - } - } - - CodeMirror.defineMIME('text/x-livescript', 'livescript'); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/lua/index.html b/shared/html/libs/codemirror/5.0.0/mode/lua/index.html deleted file mode 100644 index fc98b94..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/lua/index.html +++ /dev/null @@ -1,85 +0,0 @@ - - -CodeMirror: Lua mode - - - - - - - - - - - -
-

Lua mode

-
- - -

Loosely based on Franciszek - Wawrzak's CodeMirror - 1 mode. One configuration parameter is - supported, specials, to which you can provide an - array of strings to have those identifiers highlighted with - the lua-special style.

-

MIME types defined: text/x-lua.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/lua/lua.js b/shared/html/libs/codemirror/5.0.0/mode/lua/lua.js deleted file mode 100644 index 0b19abd..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/lua/lua.js +++ /dev/null @@ -1,159 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's -// CodeMirror 1 mode. -// highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("lua", function(config, parserConfig) { - var indentUnit = config.indentUnit; - - function prefixRE(words) { - return new RegExp("^(?:" + words.join("|") + ")", "i"); - } - function wordRE(words) { - return new RegExp("^(?:" + words.join("|") + ")$", "i"); - } - var specials = wordRE(parserConfig.specials || []); - - // long list of standard functions from lua manual - var builtins = wordRE([ - "_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load", - "loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require", - "select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall", - - "coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield", - - "debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable", - "debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable", - "debug.setupvalue","debug.traceback", - - "close","flush","lines","read","seek","setvbuf","write", - - "io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin", - "io.stdout","io.tmpfile","io.type","io.write", - - "math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg", - "math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max", - "math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh", - "math.sqrt","math.tan","math.tanh", - - "os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale", - "os.time","os.tmpname", - - "package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload", - "package.seeall", - - "string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub", - "string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper", - - "table.concat","table.insert","table.maxn","table.remove","table.sort" - ]); - var keywords = wordRE(["and","break","elseif","false","nil","not","or","return", - "true","function", "end", "if", "then", "else", "do", - "while", "repeat", "until", "for", "in", "local" ]); - - var indentTokens = wordRE(["function", "if","repeat","do", "\\(", "{"]); - var dedentTokens = wordRE(["end", "until", "\\)", "}"]); - var dedentPartial = prefixRE(["end", "until", "\\)", "}", "else", "elseif"]); - - function readBracket(stream) { - var level = 0; - while (stream.eat("=")) ++level; - stream.eat("["); - return level; - } - - function normal(stream, state) { - var ch = stream.next(); - if (ch == "-" && stream.eat("-")) { - if (stream.eat("[") && stream.eat("[")) - return (state.cur = bracketed(readBracket(stream), "comment"))(stream, state); - stream.skipToEnd(); - return "comment"; - } - if (ch == "\"" || ch == "'") - return (state.cur = string(ch))(stream, state); - if (ch == "[" && /[\[=]/.test(stream.peek())) - return (state.cur = bracketed(readBracket(stream), "string"))(stream, state); - if (/\d/.test(ch)) { - stream.eatWhile(/[\w.%]/); - return "number"; - } - if (/[\w_]/.test(ch)) { - stream.eatWhile(/[\w\\\-_.]/); - return "variable"; - } - return null; - } - - function bracketed(level, style) { - return function(stream, state) { - var curlev = null, ch; - while ((ch = stream.next()) != null) { - if (curlev == null) {if (ch == "]") curlev = 0;} - else if (ch == "=") ++curlev; - else if (ch == "]" && curlev == level) { state.cur = normal; break; } - else curlev = null; - } - return style; - }; - } - - function string(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) break; - escaped = !escaped && ch == "\\"; - } - if (!escaped) state.cur = normal; - return "string"; - }; - } - - return { - startState: function(basecol) { - return {basecol: basecol || 0, indentDepth: 0, cur: normal}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = state.cur(stream, state); - var word = stream.current(); - if (style == "variable") { - if (keywords.test(word)) style = "keyword"; - else if (builtins.test(word)) style = "builtin"; - else if (specials.test(word)) style = "variable-2"; - } - if ((style != "comment") && (style != "string")){ - if (indentTokens.test(word)) ++state.indentDepth; - else if (dedentTokens.test(word)) --state.indentDepth; - } - return style; - }, - - indent: function(state, textAfter) { - var closing = dedentPartial.test(textAfter); - return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0)); - }, - - lineComment: "--", - blockCommentStart: "--[[", - blockCommentEnd: "]]" - }; -}); - -CodeMirror.defineMIME("text/x-lua", "lua"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/markdown/index.html b/shared/html/libs/codemirror/5.0.0/mode/markdown/index.html deleted file mode 100644 index c3bb8df..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/markdown/index.html +++ /dev/null @@ -1,359 +0,0 @@ - - -CodeMirror: Markdown mode - - - - - - - - - - - -
-

Markdown mode

-
- - - -

Optionally depends on the XML mode for properly highlighted inline XML blocks.

- -

MIME types defined: text/x-markdown.

- -

Parsing/Highlighting Tests: normal, verbose.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/markdown/markdown.js b/shared/html/libs/codemirror/5.0.0/mode/markdown/markdown.js deleted file mode 100644 index 3c80311..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/markdown/markdown.js +++ /dev/null @@ -1,765 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../xml/xml", "../meta"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { - - var htmlFound = CodeMirror.modes.hasOwnProperty("xml"); - var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? {name: "xml", htmlMode: true} : "text/plain"); - - function getMode(name) { - if (CodeMirror.findModeByName) { - var found = CodeMirror.findModeByName(name); - if (found) name = found.mime || found.mimes[0]; - } - var mode = CodeMirror.getMode(cmCfg, name); - return mode.name == "null" ? null : mode; - } - - // Should characters that affect highlighting be highlighted separate? - // Does not include characters that will be output (such as `1.` and `-` for lists) - if (modeCfg.highlightFormatting === undefined) - modeCfg.highlightFormatting = false; - - // Maximum number of nested blockquotes. Set to 0 for infinite nesting. - // Excess `>` will emit `error` token. - if (modeCfg.maxBlockquoteDepth === undefined) - modeCfg.maxBlockquoteDepth = 0; - - // Should underscores in words open/close em/strong? - if (modeCfg.underscoresBreakWords === undefined) - modeCfg.underscoresBreakWords = true; - - // Turn on fenced code blocks? ("```" to start/end) - if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false; - - // Turn on task lists? ("- [ ] " and "- [x] ") - if (modeCfg.taskLists === undefined) modeCfg.taskLists = false; - - // Turn on strikethrough syntax - if (modeCfg.strikethrough === undefined) - modeCfg.strikethrough = false; - - var codeDepth = 0; - - var header = 'header' - , code = 'comment' - , quote = 'quote' - , list1 = 'variable-2' - , list2 = 'variable-3' - , list3 = 'keyword' - , hr = 'hr' - , image = 'tag' - , formatting = 'formatting' - , linkinline = 'link' - , linkemail = 'link' - , linktext = 'link' - , linkhref = 'string' - , em = 'em' - , strong = 'strong' - , strikethrough = 'strikethrough'; - - var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/ - , ulRE = /^[*\-+]\s+/ - , olRE = /^[0-9]+\.\s+/ - , taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE - , atxHeaderRE = /^#+/ - , setextHeaderRE = /^(?:\={1,}|-{1,})$/ - , textRE = /^[^#!\[\]*_\\<>` "'(~]+/; - - function switchInline(stream, state, f) { - state.f = state.inline = f; - return f(stream, state); - } - - function switchBlock(stream, state, f) { - state.f = state.block = f; - return f(stream, state); - } - - - // Blocks - - function blankLine(state) { - // Reset linkTitle state - state.linkTitle = false; - // Reset EM state - state.em = false; - // Reset STRONG state - state.strong = false; - // Reset strikethrough state - state.strikethrough = false; - // Reset state.quote - state.quote = 0; - if (!htmlFound && state.f == htmlBlock) { - state.f = inlineNormal; - state.block = blockNormal; - } - // Reset state.trailingSpace - state.trailingSpace = 0; - state.trailingSpaceNewLine = false; - // Mark this line as blank - state.thisLineHasContent = false; - return null; - } - - function blockNormal(stream, state) { - - var sol = stream.sol(); - - var prevLineIsList = (state.list !== false); - if (state.list !== false && state.indentationDiff >= 0) { // Continued list - if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block - state.indentation -= state.indentationDiff; - } - state.list = null; - } else if (state.list !== false && state.indentation > 0) { - state.list = null; - state.listDepth = Math.floor(state.indentation / 4); - } else if (state.list !== false) { // No longer a list - state.list = false; - state.listDepth = 0; - } - - var match = null; - if (state.indentationDiff >= 4) { - state.indentation -= 4; - stream.skipToEnd(); - return code; - } else if (stream.eatSpace()) { - return null; - } else if (match = stream.match(atxHeaderRE)) { - state.header = match[0].length <= 6 ? match[0].length : 6; - if (modeCfg.highlightFormatting) state.formatting = "header"; - state.f = state.inline; - return getType(state); - } else if (state.prevLineHasContent && (match = stream.match(setextHeaderRE))) { - state.header = match[0].charAt(0) == '=' ? 1 : 2; - if (modeCfg.highlightFormatting) state.formatting = "header"; - state.f = state.inline; - return getType(state); - } else if (stream.eat('>')) { - state.indentation++; - state.quote = sol ? 1 : state.quote + 1; - if (modeCfg.highlightFormatting) state.formatting = "quote"; - stream.eatSpace(); - return getType(state); - } else if (stream.peek() === '[') { - return switchInline(stream, state, footnoteLink); - } else if (stream.match(hrRE, true)) { - return hr; - } else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) { - var listType = null; - if (stream.match(ulRE, true)) { - listType = 'ul'; - } else { - stream.match(olRE, true); - listType = 'ol'; - } - state.indentation += 4; - state.list = true; - state.listDepth++; - if (modeCfg.taskLists && stream.match(taskListRE, false)) { - state.taskList = true; - } - state.f = state.inline; - if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType]; - return getType(state); - } else if (modeCfg.fencedCodeBlocks && stream.match(/^```[ \t]*([\w+#]*)/, true)) { - // try switching mode - state.localMode = getMode(RegExp.$1); - if (state.localMode) state.localState = state.localMode.startState(); - state.f = state.block = local; - if (modeCfg.highlightFormatting) state.formatting = "code-block"; - state.code = true; - return getType(state); - } - - return switchInline(stream, state, state.inline); - } - - function htmlBlock(stream, state) { - var style = htmlMode.token(stream, state.htmlState); - if ((htmlFound && state.htmlState.tagStart === null && !state.htmlState.context) || - (state.md_inside && stream.current().indexOf(">") > -1)) { - state.f = inlineNormal; - state.block = blockNormal; - state.htmlState = null; - } - return style; - } - - function local(stream, state) { - if (stream.sol() && stream.match("```", false)) { - state.localMode = state.localState = null; - state.f = state.block = leavingLocal; - return null; - } else if (state.localMode) { - return state.localMode.token(stream, state.localState); - } else { - stream.skipToEnd(); - return code; - } - } - - function leavingLocal(stream, state) { - stream.match("```"); - state.block = blockNormal; - state.f = inlineNormal; - if (modeCfg.highlightFormatting) state.formatting = "code-block"; - state.code = true; - var returnType = getType(state); - state.code = false; - return returnType; - } - - // Inline - function getType(state) { - var styles = []; - - if (state.formatting) { - styles.push(formatting); - - if (typeof state.formatting === "string") state.formatting = [state.formatting]; - - for (var i = 0; i < state.formatting.length; i++) { - styles.push(formatting + "-" + state.formatting[i]); - - if (state.formatting[i] === "header") { - styles.push(formatting + "-" + state.formatting[i] + "-" + state.header); - } - - // Add `formatting-quote` and `formatting-quote-#` for blockquotes - // Add `error` instead if the maximum blockquote nesting depth is passed - if (state.formatting[i] === "quote") { - if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) { - styles.push(formatting + "-" + state.formatting[i] + "-" + state.quote); - } else { - styles.push("error"); - } - } - } - } - - if (state.taskOpen) { - styles.push("meta"); - return styles.length ? styles.join(' ') : null; - } - if (state.taskClosed) { - styles.push("property"); - return styles.length ? styles.join(' ') : null; - } - - if (state.linkHref) { - styles.push(linkhref); - return styles.length ? styles.join(' ') : null; - } - - if (state.strong) { styles.push(strong); } - if (state.em) { styles.push(em); } - if (state.strikethrough) { styles.push(strikethrough); } - - if (state.linkText) { styles.push(linktext); } - - if (state.code) { styles.push(code); } - - if (state.header) { styles.push(header); styles.push(header + "-" + state.header); } - - if (state.quote) { - styles.push(quote); - - // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth - if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) { - styles.push(quote + "-" + state.quote); - } else { - styles.push(quote + "-" + modeCfg.maxBlockquoteDepth); - } - } - - if (state.list !== false) { - var listMod = (state.listDepth - 1) % 3; - if (!listMod) { - styles.push(list1); - } else if (listMod === 1) { - styles.push(list2); - } else { - styles.push(list3); - } - } - - if (state.trailingSpaceNewLine) { - styles.push("trailing-space-new-line"); - } else if (state.trailingSpace) { - styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b")); - } - - return styles.length ? styles.join(' ') : null; - } - - function handleText(stream, state) { - if (stream.match(textRE, true)) { - return getType(state); - } - return undefined; - } - - function inlineNormal(stream, state) { - var style = state.text(stream, state); - if (typeof style !== 'undefined') - return style; - - if (state.list) { // List marker (*, +, -, 1., etc) - state.list = null; - return getType(state); - } - - if (state.taskList) { - var taskOpen = stream.match(taskListRE, true)[1] !== "x"; - if (taskOpen) state.taskOpen = true; - else state.taskClosed = true; - if (modeCfg.highlightFormatting) state.formatting = "task"; - state.taskList = false; - return getType(state); - } - - state.taskOpen = false; - state.taskClosed = false; - - if (state.header && stream.match(/^#+$/, true)) { - if (modeCfg.highlightFormatting) state.formatting = "header"; - return getType(state); - } - - // Get sol() value now, before character is consumed - var sol = stream.sol(); - - var ch = stream.next(); - - if (ch === '\\') { - stream.next(); - if (modeCfg.highlightFormatting) { - var type = getType(state); - return type ? type + " formatting-escape" : "formatting-escape"; - } - } - - // Matches link titles present on next line - if (state.linkTitle) { - state.linkTitle = false; - var matchCh = ch; - if (ch === '(') { - matchCh = ')'; - } - matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); - var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh; - if (stream.match(new RegExp(regex), true)) { - return linkhref; - } - } - - // If this block is changed, it may need to be updated in GFM mode - if (ch === '`') { - var previousFormatting = state.formatting; - if (modeCfg.highlightFormatting) state.formatting = "code"; - var t = getType(state); - var before = stream.pos; - stream.eatWhile('`'); - var difference = 1 + stream.pos - before; - if (!state.code) { - codeDepth = difference; - state.code = true; - return getType(state); - } else { - if (difference === codeDepth) { // Must be exact - state.code = false; - return t; - } - state.formatting = previousFormatting; - return getType(state); - } - } else if (state.code) { - return getType(state); - } - - if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) { - stream.match(/\[[^\]]*\]/); - state.inline = state.f = linkHref; - return image; - } - - if (ch === '[' && stream.match(/.*\](\(.*\)| ?\[.*\])/, false)) { - state.linkText = true; - if (modeCfg.highlightFormatting) state.formatting = "link"; - return getType(state); - } - - if (ch === ']' && state.linkText && stream.match(/\(.*\)| ?\[.*\]/, false)) { - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - state.linkText = false; - state.inline = state.f = linkHref; - return type; - } - - if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) { - state.f = state.inline = linkInline; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - if (type){ - type += " "; - } else { - type = ""; - } - return type + linkinline; - } - - if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) { - state.f = state.inline = linkInline; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - if (type){ - type += " "; - } else { - type = ""; - } - return type + linkemail; - } - - if (ch === '<' && stream.match(/^\w/, false)) { - if (stream.string.indexOf(">") != -1) { - var atts = stream.string.substring(1,stream.string.indexOf(">")); - if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) { - state.md_inside = true; - } - } - stream.backUp(1); - state.htmlState = CodeMirror.startState(htmlMode); - return switchBlock(stream, state, htmlBlock); - } - - if (ch === '<' && stream.match(/^\/\w*?>/)) { - state.md_inside = false; - return "tag"; - } - - var ignoreUnderscore = false; - if (!modeCfg.underscoresBreakWords) { - if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) { - var prevPos = stream.pos - 2; - if (prevPos >= 0) { - var prevCh = stream.string.charAt(prevPos); - if (prevCh !== '_' && prevCh.match(/(\w)/, false)) { - ignoreUnderscore = true; - } - } - } - } - if (ch === '*' || (ch === '_' && !ignoreUnderscore)) { - if (sol && stream.peek() === ' ') { - // Do nothing, surrounded by newline and space - } else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG - if (modeCfg.highlightFormatting) state.formatting = "strong"; - var t = getType(state); - state.strong = false; - return t; - } else if (!state.strong && stream.eat(ch)) { // Add STRONG - state.strong = ch; - if (modeCfg.highlightFormatting) state.formatting = "strong"; - return getType(state); - } else if (state.em === ch) { // Remove EM - if (modeCfg.highlightFormatting) state.formatting = "em"; - var t = getType(state); - state.em = false; - return t; - } else if (!state.em) { // Add EM - state.em = ch; - if (modeCfg.highlightFormatting) state.formatting = "em"; - return getType(state); - } - } else if (ch === ' ') { - if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces - if (stream.peek() === ' ') { // Surrounded by spaces, ignore - return getType(state); - } else { // Not surrounded by spaces, back up pointer - stream.backUp(1); - } - } - } - - if (modeCfg.strikethrough) { - if (ch === '~' && stream.eatWhile(ch)) { - if (state.strikethrough) {// Remove strikethrough - if (modeCfg.highlightFormatting) state.formatting = "strikethrough"; - var t = getType(state); - state.strikethrough = false; - return t; - } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough - state.strikethrough = true; - if (modeCfg.highlightFormatting) state.formatting = "strikethrough"; - return getType(state); - } - } else if (ch === ' ') { - if (stream.match(/^~~/, true)) { // Probably surrounded by space - if (stream.peek() === ' ') { // Surrounded by spaces, ignore - return getType(state); - } else { // Not surrounded by spaces, back up pointer - stream.backUp(2); - } - } - } - } - - if (ch === ' ') { - if (stream.match(/ +$/, false)) { - state.trailingSpace++; - } else if (state.trailingSpace) { - state.trailingSpaceNewLine = true; - } - } - - return getType(state); - } - - function linkInline(stream, state) { - var ch = stream.next(); - - if (ch === ">") { - state.f = state.inline = inlineNormal; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - if (type){ - type += " "; - } else { - type = ""; - } - return type + linkinline; - } - - stream.match(/^[^>]+/, true); - - return linkinline; - } - - function linkHref(stream, state) { - // Check if space, and return NULL if so (to avoid marking the space) - if(stream.eatSpace()){ - return null; - } - var ch = stream.next(); - if (ch === '(' || ch === '[') { - state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]"); - if (modeCfg.highlightFormatting) state.formatting = "link-string"; - state.linkHref = true; - return getType(state); - } - return 'error'; - } - - function getLinkHrefInside(endChar) { - return function(stream, state) { - var ch = stream.next(); - - if (ch === endChar) { - state.f = state.inline = inlineNormal; - if (modeCfg.highlightFormatting) state.formatting = "link-string"; - var returnState = getType(state); - state.linkHref = false; - return returnState; - } - - if (stream.match(inlineRE(endChar), true)) { - stream.backUp(1); - } - - state.linkHref = true; - return getType(state); - }; - } - - function footnoteLink(stream, state) { - if (stream.match(/^[^\]]*\]:/, false)) { - state.f = footnoteLinkInside; - stream.next(); // Consume [ - if (modeCfg.highlightFormatting) state.formatting = "link"; - state.linkText = true; - return getType(state); - } - return switchInline(stream, state, inlineNormal); - } - - function footnoteLinkInside(stream, state) { - if (stream.match(/^\]:/, true)) { - state.f = state.inline = footnoteUrl; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var returnType = getType(state); - state.linkText = false; - return returnType; - } - - stream.match(/^[^\]]+/, true); - - return linktext; - } - - function footnoteUrl(stream, state) { - // Check if space, and return NULL if so (to avoid marking the space) - if(stream.eatSpace()){ - return null; - } - // Match URL - stream.match(/^[^\s]+/, true); - // Check for link title - if (stream.peek() === undefined) { // End of line, set flag to check next line - state.linkTitle = true; - } else { // More content on line, check if link title - stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true); - } - state.f = state.inline = inlineNormal; - return linkhref; - } - - var savedInlineRE = []; - function inlineRE(endChar) { - if (!savedInlineRE[endChar]) { - // Escape endChar for RegExp (taken from http://stackoverflow.com/a/494122/526741) - endChar = (endChar+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); - // Match any non-endChar, escaped character, as well as the closing - // endChar. - savedInlineRE[endChar] = new RegExp('^(?:[^\\\\]|\\\\.)*?(' + endChar + ')'); - } - return savedInlineRE[endChar]; - } - - var mode = { - startState: function() { - return { - f: blockNormal, - - prevLineHasContent: false, - thisLineHasContent: false, - - block: blockNormal, - htmlState: null, - indentation: 0, - - inline: inlineNormal, - text: handleText, - - formatting: false, - linkText: false, - linkHref: false, - linkTitle: false, - em: false, - strong: false, - header: 0, - taskList: false, - list: false, - listDepth: 0, - quote: 0, - trailingSpace: 0, - trailingSpaceNewLine: false, - strikethrough: false - }; - }, - - copyState: function(s) { - return { - f: s.f, - - prevLineHasContent: s.prevLineHasContent, - thisLineHasContent: s.thisLineHasContent, - - block: s.block, - htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState), - indentation: s.indentation, - - localMode: s.localMode, - localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null, - - inline: s.inline, - text: s.text, - formatting: false, - linkTitle: s.linkTitle, - em: s.em, - strong: s.strong, - strikethrough: s.strikethrough, - header: s.header, - taskList: s.taskList, - list: s.list, - listDepth: s.listDepth, - quote: s.quote, - trailingSpace: s.trailingSpace, - trailingSpaceNewLine: s.trailingSpaceNewLine, - md_inside: s.md_inside - }; - }, - - token: function(stream, state) { - - // Reset state.formatting - state.formatting = false; - - if (stream.sol()) { - var forceBlankLine = !!state.header; - - // Reset state.header - state.header = 0; - - if (stream.match(/^\s*$/, true) || forceBlankLine) { - state.prevLineHasContent = false; - blankLine(state); - return forceBlankLine ? this.token(stream, state) : null; - } else { - state.prevLineHasContent = state.thisLineHasContent; - state.thisLineHasContent = true; - } - - // Reset state.taskList - state.taskList = false; - - // Reset state.code - state.code = false; - - // Reset state.trailingSpace - state.trailingSpace = 0; - state.trailingSpaceNewLine = false; - - state.f = state.block; - var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length; - var difference = Math.floor((indentation - state.indentation) / 4) * 4; - if (difference > 4) difference = 4; - var adjustedIndentation = state.indentation + difference; - state.indentationDiff = adjustedIndentation - state.indentation; - state.indentation = adjustedIndentation; - if (indentation > 0) return null; - } - return state.f(stream, state); - }, - - innerMode: function(state) { - if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode}; - if (state.localState) return {state: state.localState, mode: state.localMode}; - return {state: state, mode: mode}; - }, - - blankLine: blankLine, - - getType: getType, - - fold: "markdown" - }; - return mode; -}, "xml"); - -CodeMirror.defineMIME("text/x-markdown", "markdown"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/markdown/test.js b/shared/html/libs/codemirror/5.0.0/mode/markdown/test.js deleted file mode 100644 index 96ca1ae..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/markdown/test.js +++ /dev/null @@ -1,754 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({tabSize: 4}, "markdown"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "markdown", highlightFormatting: true}); - function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); } - - FT("formatting_emAsterisk", - "[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]"); - - FT("formatting_emUnderscore", - "[em&formatting&formatting-em _][em foo][em&formatting&formatting-em _]"); - - FT("formatting_strongAsterisk", - "[strong&formatting&formatting-strong **][strong foo][strong&formatting&formatting-strong **]"); - - FT("formatting_strongUnderscore", - "[strong&formatting&formatting-strong __][strong foo][strong&formatting&formatting-strong __]"); - - FT("formatting_codeBackticks", - "[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]"); - - FT("formatting_doubleBackticks", - "[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]"); - - FT("formatting_atxHeader", - "[header&header-1&formatting&formatting-header&formatting-header-1 #][header&header-1 foo # bar ][header&header-1&formatting&formatting-header&formatting-header-1 #]"); - - FT("formatting_setextHeader", - "foo", - "[header&header-1&formatting&formatting-header&formatting-header-1 =]"); - - FT("formatting_blockquote", - "[quote"e-1&formatting&formatting-quote&formatting-quote-1 > ][quote"e-1 foo]"); - - FT("formatting_list", - "[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]"); - FT("formatting_list", - "[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]"); - - FT("formatting_link", - "[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string (][string http://example.com/][string&formatting&formatting-link-string )]"); - - FT("formatting_linkReference", - "[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string [][string bar][string&formatting&formatting-link-string ]]]", - "[link&formatting&formatting-link [][link bar][link&formatting&formatting-link ]]:] [string http://example.com/]"); - - FT("formatting_linkWeb", - "[link&formatting&formatting-link <][link http://example.com/][link&formatting&formatting-link >]"); - - FT("formatting_linkEmail", - "[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]"); - - FT("formatting_escape", - "[formatting-escape \\*]"); - - MT("plainText", - "foo"); - - // Don't style single trailing space - MT("trailingSpace1", - "foo "); - - // Two or more trailing spaces should be styled with line break character - MT("trailingSpace2", - "foo[trailing-space-a ][trailing-space-new-line ]"); - - MT("trailingSpace3", - "foo[trailing-space-a ][trailing-space-b ][trailing-space-new-line ]"); - - MT("trailingSpace4", - "foo[trailing-space-a ][trailing-space-b ][trailing-space-a ][trailing-space-new-line ]"); - - // Code blocks using 4 spaces (regardless of CodeMirror.tabSize value) - MT("codeBlocksUsing4Spaces", - " [comment foo]"); - - // Code blocks using 4 spaces with internal indentation - MT("codeBlocksUsing4SpacesIndentation", - " [comment bar]", - " [comment hello]", - " [comment world]", - " [comment foo]", - "bar"); - - // Code blocks using 4 spaces with internal indentation - MT("codeBlocksUsing4SpacesIndentation", - " foo", - " [comment bar]", - " [comment hello]", - " [comment world]"); - - // Code blocks should end even after extra indented lines - MT("codeBlocksWithTrailingIndentedLine", - " [comment foo]", - " [comment bar]", - " [comment baz]", - " ", - "hello"); - - // Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value) - MT("codeBlocksUsing1Tab", - "\t[comment foo]"); - - // Inline code using backticks - MT("inlineCodeUsingBackticks", - "foo [comment `bar`]"); - - // Block code using single backtick (shouldn't work) - MT("blockCodeSingleBacktick", - "[comment `]", - "foo", - "[comment `]"); - - // Unclosed backticks - // Instead of simply marking as CODE, it would be nice to have an - // incomplete flag for CODE, that is styled slightly different. - MT("unclosedBackticks", - "foo [comment `bar]"); - - // Per documentation: "To include a literal backtick character within a - // code span, you can use multiple backticks as the opening and closing - // delimiters" - MT("doubleBackticks", - "[comment ``foo ` bar``]"); - - // Tests based on Dingus - // http://daringfireball.net/projects/markdown/dingus - // - // Multiple backticks within an inline code block - MT("consecutiveBackticks", - "[comment `foo```bar`]"); - - // Multiple backticks within an inline code block with a second code block - MT("consecutiveBackticks", - "[comment `foo```bar`] hello [comment `world`]"); - - // Unclosed with several different groups of backticks - MT("unclosedBackticks", - "[comment ``foo ``` bar` hello]"); - - // Closed with several different groups of backticks - MT("closedBackticks", - "[comment ``foo ``` bar` hello``] world"); - - // atx headers - // http://daringfireball.net/projects/markdown/syntax#header - - MT("atxH1", - "[header&header-1 # foo]"); - - MT("atxH2", - "[header&header-2 ## foo]"); - - MT("atxH3", - "[header&header-3 ### foo]"); - - MT("atxH4", - "[header&header-4 #### foo]"); - - MT("atxH5", - "[header&header-5 ##### foo]"); - - MT("atxH6", - "[header&header-6 ###### foo]"); - - // H6 - 7x '#' should still be H6, per Dingus - // http://daringfireball.net/projects/markdown/dingus - MT("atxH6NotH7", - "[header&header-6 ####### foo]"); - - // Inline styles should be parsed inside headers - MT("atxH1inline", - "[header&header-1 # foo ][header&header-1&em *bar*]"); - - // Setext headers - H1, H2 - // Per documentation, "Any number of underlining =’s or -’s will work." - // http://daringfireball.net/projects/markdown/syntax#header - // Ideally, the text would be marked as `header` as well, but this is - // not really feasible at the moment. So, instead, we're testing against - // what works today, to avoid any regressions. - // - // Check if single underlining = works - MT("setextH1", - "foo", - "[header&header-1 =]"); - - // Check if 3+ ='s work - MT("setextH1", - "foo", - "[header&header-1 ===]"); - - // Check if single underlining - works - MT("setextH2", - "foo", - "[header&header-2 -]"); - - // Check if 3+ -'s work - MT("setextH2", - "foo", - "[header&header-2 ---]"); - - // Single-line blockquote with trailing space - MT("blockquoteSpace", - "[quote"e-1 > foo]"); - - // Single-line blockquote - MT("blockquoteNoSpace", - "[quote"e-1 >foo]"); - - // No blank line before blockquote - MT("blockquoteNoBlankLine", - "foo", - "[quote"e-1 > bar]"); - - // Nested blockquote - MT("blockquoteSpace", - "[quote"e-1 > foo]", - "[quote"e-1 >][quote"e-2 > foo]", - "[quote"e-1 >][quote"e-2 >][quote"e-3 > foo]"); - - // Single-line blockquote followed by normal paragraph - MT("blockquoteThenParagraph", - "[quote"e-1 >foo]", - "", - "bar"); - - // Multi-line blockquote (lazy mode) - MT("multiBlockquoteLazy", - "[quote"e-1 >foo]", - "[quote"e-1 bar]"); - - // Multi-line blockquote followed by normal paragraph (lazy mode) - MT("multiBlockquoteLazyThenParagraph", - "[quote"e-1 >foo]", - "[quote"e-1 bar]", - "", - "hello"); - - // Multi-line blockquote (non-lazy mode) - MT("multiBlockquote", - "[quote"e-1 >foo]", - "[quote"e-1 >bar]"); - - // Multi-line blockquote followed by normal paragraph (non-lazy mode) - MT("multiBlockquoteThenParagraph", - "[quote"e-1 >foo]", - "[quote"e-1 >bar]", - "", - "hello"); - - // Check list types - - MT("listAsterisk", - "foo", - "bar", - "", - "[variable-2 * foo]", - "[variable-2 * bar]"); - - MT("listPlus", - "foo", - "bar", - "", - "[variable-2 + foo]", - "[variable-2 + bar]"); - - MT("listDash", - "foo", - "bar", - "", - "[variable-2 - foo]", - "[variable-2 - bar]"); - - MT("listNumber", - "foo", - "bar", - "", - "[variable-2 1. foo]", - "[variable-2 2. bar]"); - - // Lists require a preceding blank line (per Dingus) - MT("listBogus", - "foo", - "1. bar", - "2. hello"); - - // List after header - MT("listAfterHeader", - "[header&header-1 # foo]", - "[variable-2 - bar]"); - - // Formatting in lists (*) - MT("listAsteriskFormatting", - "[variable-2 * ][variable-2&em *foo*][variable-2 bar]", - "[variable-2 * ][variable-2&strong **foo**][variable-2 bar]", - "[variable-2 * ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]", - "[variable-2 * ][variable-2&comment `foo`][variable-2 bar]"); - - // Formatting in lists (+) - MT("listPlusFormatting", - "[variable-2 + ][variable-2&em *foo*][variable-2 bar]", - "[variable-2 + ][variable-2&strong **foo**][variable-2 bar]", - "[variable-2 + ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]", - "[variable-2 + ][variable-2&comment `foo`][variable-2 bar]"); - - // Formatting in lists (-) - MT("listDashFormatting", - "[variable-2 - ][variable-2&em *foo*][variable-2 bar]", - "[variable-2 - ][variable-2&strong **foo**][variable-2 bar]", - "[variable-2 - ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]", - "[variable-2 - ][variable-2&comment `foo`][variable-2 bar]"); - - // Formatting in lists (1.) - MT("listNumberFormatting", - "[variable-2 1. ][variable-2&em *foo*][variable-2 bar]", - "[variable-2 2. ][variable-2&strong **foo**][variable-2 bar]", - "[variable-2 3. ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]", - "[variable-2 4. ][variable-2&comment `foo`][variable-2 bar]"); - - // Paragraph lists - MT("listParagraph", - "[variable-2 * foo]", - "", - "[variable-2 * bar]"); - - // Multi-paragraph lists - // - // 4 spaces - MT("listMultiParagraph", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - " [variable-2 hello]"); - - // 4 spaces, extra blank lines (should still be list, per Dingus) - MT("listMultiParagraphExtra", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - "", - " [variable-2 hello]"); - - // 4 spaces, plus 1 space (should still be list, per Dingus) - MT("listMultiParagraphExtraSpace", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - " [variable-2 hello]", - "", - " [variable-2 world]"); - - // 1 tab - MT("listTab", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - "\t[variable-2 hello]"); - - // No indent - MT("listNoIndent", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - "hello"); - - // Blockquote - MT("blockquote", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - " [variable-2"e"e-1 > hello]"); - - // Code block - MT("blockquoteCode", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - " [comment > hello]", - "", - " [variable-2 world]"); - - // Code block followed by text - MT("blockquoteCodeText", - "[variable-2 * foo]", - "", - " [variable-2 bar]", - "", - " [comment hello]", - "", - " [variable-2 world]"); - - // Nested list - - MT("listAsteriskNested", - "[variable-2 * foo]", - "", - " [variable-3 * bar]"); - - MT("listPlusNested", - "[variable-2 + foo]", - "", - " [variable-3 + bar]"); - - MT("listDashNested", - "[variable-2 - foo]", - "", - " [variable-3 - bar]"); - - MT("listNumberNested", - "[variable-2 1. foo]", - "", - " [variable-3 2. bar]"); - - MT("listMixed", - "[variable-2 * foo]", - "", - " [variable-3 + bar]", - "", - " [keyword - hello]", - "", - " [variable-2 1. world]"); - - MT("listBlockquote", - "[variable-2 * foo]", - "", - " [variable-3 + bar]", - "", - " [quote"e-1&variable-3 > hello]"); - - MT("listCode", - "[variable-2 * foo]", - "", - " [variable-3 + bar]", - "", - " [comment hello]"); - - // Code with internal indentation - MT("listCodeIndentation", - "[variable-2 * foo]", - "", - " [comment bar]", - " [comment hello]", - " [comment world]", - " [comment foo]", - " [variable-2 bar]"); - - // List nesting edge cases - MT("listNested", - "[variable-2 * foo]", - "", - " [variable-3 * bar]", - "", - " [variable-2 hello]" - ); - MT("listNested", - "[variable-2 * foo]", - "", - " [variable-3 * bar]", - "", - " [variable-3 * foo]" - ); - - // Code followed by text - MT("listCodeText", - "[variable-2 * foo]", - "", - " [comment bar]", - "", - "hello"); - - // Following tests directly from official Markdown documentation - // http://daringfireball.net/projects/markdown/syntax#hr - - MT("hrSpace", - "[hr * * *]"); - - MT("hr", - "[hr ***]"); - - MT("hrLong", - "[hr *****]"); - - MT("hrSpaceDash", - "[hr - - -]"); - - MT("hrDashLong", - "[hr ---------------------------------------]"); - - // Inline link with title - MT("linkTitle", - "[link [[foo]]][string (http://example.com/ \"bar\")] hello"); - - // Inline link without title - MT("linkNoTitle", - "[link [[foo]]][string (http://example.com/)] bar"); - - // Inline link with image - MT("linkImage", - "[link [[][tag ![[foo]]][string (http://example.com/)][link ]]][string (http://example.com/)] bar"); - - // Inline link with Em - MT("linkEm", - "[link [[][link&em *foo*][link ]]][string (http://example.com/)] bar"); - - // Inline link with Strong - MT("linkStrong", - "[link [[][link&strong **foo**][link ]]][string (http://example.com/)] bar"); - - // Inline link with EmStrong - MT("linkEmStrong", - "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string (http://example.com/)] bar"); - - // Image with title - MT("imageTitle", - "[tag ![[foo]]][string (http://example.com/ \"bar\")] hello"); - - // Image without title - MT("imageNoTitle", - "[tag ![[foo]]][string (http://example.com/)] bar"); - - // Image with asterisks - MT("imageAsterisks", - "[tag ![[*foo*]]][string (http://example.com/)] bar"); - - // Not a link. Should be normal text due to square brackets being used - // regularly in text, especially in quoted material, and no space is allowed - // between square brackets and parentheses (per Dingus). - MT("notALink", - "[[foo]] (bar)"); - - // Reference-style links - MT("linkReference", - "[link [[foo]]][string [[bar]]] hello"); - - // Reference-style links with Em - MT("linkReferenceEm", - "[link [[][link&em *foo*][link ]]][string [[bar]]] hello"); - - // Reference-style links with Strong - MT("linkReferenceStrong", - "[link [[][link&strong **foo**][link ]]][string [[bar]]] hello"); - - // Reference-style links with EmStrong - MT("linkReferenceEmStrong", - "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string [[bar]]] hello"); - - // Reference-style links with optional space separator (per docuentation) - // "You can optionally use a space to separate the sets of brackets" - MT("linkReferenceSpace", - "[link [[foo]]] [string [[bar]]] hello"); - - // Should only allow a single space ("...use *a* space...") - MT("linkReferenceDoubleSpace", - "[[foo]] [[bar]] hello"); - - // Reference-style links with implicit link name - MT("linkImplicit", - "[link [[foo]]][string [[]]] hello"); - - // @todo It would be nice if, at some point, the document was actually - // checked to see if the referenced link exists - - // Link label, for reference-style links (taken from documentation) - - MT("labelNoTitle", - "[link [[foo]]:] [string http://example.com/]"); - - MT("labelIndented", - " [link [[foo]]:] [string http://example.com/]"); - - MT("labelSpaceTitle", - "[link [[foo bar]]:] [string http://example.com/ \"hello\"]"); - - MT("labelDoubleTitle", - "[link [[foo bar]]:] [string http://example.com/ \"hello\"] \"world\""); - - MT("labelTitleDoubleQuotes", - "[link [[foo]]:] [string http://example.com/ \"bar\"]"); - - MT("labelTitleSingleQuotes", - "[link [[foo]]:] [string http://example.com/ 'bar']"); - - MT("labelTitleParenthese", - "[link [[foo]]:] [string http://example.com/ (bar)]"); - - MT("labelTitleInvalid", - "[link [[foo]]:] [string http://example.com/] bar"); - - MT("labelLinkAngleBrackets", - "[link [[foo]]:] [string \"bar\"]"); - - MT("labelTitleNextDoubleQuotes", - "[link [[foo]]:] [string http://example.com/]", - "[string \"bar\"] hello"); - - MT("labelTitleNextSingleQuotes", - "[link [[foo]]:] [string http://example.com/]", - "[string 'bar'] hello"); - - MT("labelTitleNextParenthese", - "[link [[foo]]:] [string http://example.com/]", - "[string (bar)] hello"); - - MT("labelTitleNextMixed", - "[link [[foo]]:] [string http://example.com/]", - "(bar\" hello"); - - MT("linkWeb", - "[link ] foo"); - - MT("linkWebDouble", - "[link ] foo [link ]"); - - MT("linkEmail", - "[link ] foo"); - - MT("linkEmailDouble", - "[link ] foo [link ]"); - - MT("emAsterisk", - "[em *foo*] bar"); - - MT("emUnderscore", - "[em _foo_] bar"); - - MT("emInWordAsterisk", - "foo[em *bar*]hello"); - - MT("emInWordUnderscore", - "foo[em _bar_]hello"); - - // Per documentation: "...surround an * or _ with spaces, it’ll be - // treated as a literal asterisk or underscore." - - MT("emEscapedBySpaceIn", - "foo [em _bar _ hello_] world"); - - MT("emEscapedBySpaceOut", - "foo _ bar[em _hello_]world"); - - MT("emEscapedByNewline", - "foo", - "_ bar[em _hello_]world"); - - // Unclosed emphasis characters - // Instead of simply marking as EM / STRONG, it would be nice to have an - // incomplete flag for EM and STRONG, that is styled slightly different. - MT("emIncompleteAsterisk", - "foo [em *bar]"); - - MT("emIncompleteUnderscore", - "foo [em _bar]"); - - MT("strongAsterisk", - "[strong **foo**] bar"); - - MT("strongUnderscore", - "[strong __foo__] bar"); - - MT("emStrongAsterisk", - "[em *foo][em&strong **bar*][strong hello**] world"); - - MT("emStrongUnderscore", - "[em _foo][em&strong __bar_][strong hello__] world"); - - // "...same character must be used to open and close an emphasis span."" - MT("emStrongMixed", - "[em _foo][em&strong **bar*hello__ world]"); - - MT("emStrongMixed", - "[em *foo][em&strong __bar_hello** world]"); - - // These characters should be escaped: - // \ backslash - // ` backtick - // * asterisk - // _ underscore - // {} curly braces - // [] square brackets - // () parentheses - // # hash mark - // + plus sign - // - minus sign (hyphen) - // . dot - // ! exclamation mark - - MT("escapeBacktick", - "foo \\`bar\\`"); - - MT("doubleEscapeBacktick", - "foo \\\\[comment `bar\\\\`]"); - - MT("escapeAsterisk", - "foo \\*bar\\*"); - - MT("doubleEscapeAsterisk", - "foo \\\\[em *bar\\\\*]"); - - MT("escapeUnderscore", - "foo \\_bar\\_"); - - MT("doubleEscapeUnderscore", - "foo \\\\[em _bar\\\\_]"); - - MT("escapeHash", - "\\# foo"); - - MT("doubleEscapeHash", - "\\\\# foo"); - - MT("escapeNewline", - "\\", - "[em *foo*]"); - - - // Tests to make sure GFM-specific things aren't getting through - - MT("taskList", - "[variable-2 * [ ]] bar]"); - - MT("fencedCodeBlocks", - "[comment ```]", - "foo", - "[comment ```]"); - - // Tests that require XML mode - - MT("xmlMode", - "[tag&bracket <][tag div][tag&bracket >]", - "*foo*", - "[tag&bracket <][tag http://github.com][tag&bracket />]", - "[tag&bracket ]", - "[link ]"); - - MT("xmlModeWithMarkdownInside", - "[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]", - "[em *foo*]", - "[link ]", - "[tag ]", - "[link ]", - "[tag&bracket <][tag div][tag&bracket >]", - "[tag&bracket ]"); - -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/meta.js b/shared/html/libs/codemirror/5.0.0/mode/meta.js deleted file mode 100644 index e110288..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/meta.js +++ /dev/null @@ -1,177 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.modeInfo = [ - {name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]}, - {name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk", file: /^extensions\.conf$/i}, - {name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h"]}, - {name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"], alias: ["cpp"]}, - {name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy"]}, - {name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp"]}, - {name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj"]}, - {name: "CoffeeScript", mime: "text/x-coffeescript", mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]}, - {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]}, - {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]}, - {name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]}, - {name: "CSS", mime: "text/css", mode: "css", ext: ["css"]}, - {name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]}, - {name: "D", mime: "text/x-d", mode: "d", ext: ["d"]}, - {name: "Dart", mimes: ["application/dart", "text/x-dart"], mode: "dart", ext: ["dart"]}, - {name: "diff", mime: "text/x-diff", mode: "diff", ext: ["diff", "patch"]}, - {name: "Django", mime: "text/x-django", mode: "django"}, - {name: "Dockerfile", mime: "text/x-dockerfile", mode: "dockerfile", file: /^Dockerfile$/}, - {name: "DTD", mime: "application/xml-dtd", mode: "dtd", ext: ["dtd"]}, - {name: "Dylan", mime: "text/x-dylan", mode: "dylan", ext: ["dylan", "dyl", "intr"]}, - {name: "EBNF", mime: "text/x-ebnf", mode: "ebnf"}, - {name: "ECL", mime: "text/x-ecl", mode: "ecl", ext: ["ecl"]}, - {name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel", ext: ["e"]}, - {name: "Embedded Javascript", mime: "application/x-ejs", mode: "htmlembedded", ext: ["ejs"]}, - {name: "Embedded Ruby", mime: "application/x-erb", mode: "htmlembedded", ext: ["erb"]}, - {name: "Erlang", mime: "text/x-erlang", mode: "erlang", ext: ["erl"]}, - {name: "Forth", mime: "text/x-forth", mode: "forth", ext: ["forth", "fth", "4th"]}, - {name: "Fortran", mime: "text/x-fortran", mode: "fortran", ext: ["f", "for", "f77", "f90"]}, - {name: "F#", mime: "text/x-fsharp", mode: "mllike", ext: ["fs"], alias: ["fsharp"]}, - {name: "Gas", mime: "text/x-gas", mode: "gas", ext: ["s"]}, - {name: "Gherkin", mime: "text/x-feature", mode: "gherkin", ext: ["feature"]}, - {name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm", file: /^(readme|contributing|history).md$/i}, - {name: "Go", mime: "text/x-go", mode: "go", ext: ["go"]}, - {name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy"]}, - {name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]}, - {name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]}, - {name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]}, - {name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]}, - {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]}, - {name: "HTML", mime: "text/html", mode: "htmlmixed", ext: ["html", "htm"], alias: ["xhtml"]}, - {name: "HTTP", mime: "message/http", mode: "http"}, - {name: "IDL", mime: "text/x-idl", mode: "idl", ext: ["pro"]}, - {name: "Jade", mime: "text/x-jade", mode: "jade", ext: ["jade"]}, - {name: "Java", mime: "text/x-java", mode: "clike", ext: ["java"]}, - {name: "Java Server Pages", mime: "application/x-jsp", mode: "htmlembedded", ext: ["jsp"], alias: ["jsp"]}, - {name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript"], - mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]}, - {name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]}, - {name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]}, - {name: "Jinja2", mime: "null", mode: "jinja2"}, - {name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]}, - {name: "Kotlin", mime: "text/x-kotlin", mode: "kotlin", ext: ["kt"]}, - {name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]}, - {name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]}, - {name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]}, - {name: "Markdown", mime: "text/x-markdown", mode: "markdown", ext: ["markdown", "md", "mkd"]}, - {name: "mIRC", mime: "text/mirc", mode: "mirc"}, - {name: "MariaDB SQL", mime: "text/x-mariadb", mode: "sql"}, - {name: "Modelica", mime: "text/x-modelica", mode: "modelica", ext: ["mo"]}, - {name: "MS SQL", mime: "text/x-mssql", mode: "sql"}, - {name: "MySQL", mime: "text/x-mysql", mode: "sql"}, - {name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i}, - {name: "NTriples", mime: "text/n-triples", mode: "ntriples", ext: ["nt"]}, - {name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"]}, - {name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]}, - {name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]}, - {name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]}, - {name: "PEG.js", mime: "null", mode: "pegjs", ext: ["jsonld"]}, - {name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]}, - {name: "PHP", mime: "application/x-httpd-php", mode: "php", ext: ["php", "php3", "php4", "php5", "phtml"]}, - {name: "Pig", mime: "text/x-pig", mode: "pig", ext: ["pig"]}, - {name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]}, - {name: "PLSQL", mime: "text/x-plsql", mode: "sql", ext: ["pls"]}, - {name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]}, - {name: "Python", mime: "text/x-python", mode: "python", ext: ["py", "pyw"]}, - {name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]}, - {name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]}, - {name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r"], alias: ["rscript"]}, - {name: "reStructuredText", mime: "text/x-rst", mode: "rst", ext: ["rst"], alias: ["rst"]}, - {name: "RPM Changes", mime: "text/x-rpm-changes", mode: "rpm"}, - {name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]}, - {name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]}, - {name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]}, - {name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]}, - {name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]}, - {name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]}, - {name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]}, - {name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"]}, - {name: "Sieve", mime: "application/sieve", mode: "sieve", ext: ["siv", "sieve"]}, - {name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim", ext: ["slim"]}, - {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]}, - {name: "Smarty", mime: "text/x-smarty", mode: "smarty", ext: ["tpl"]}, - {name: "SmartyMixed", mime: "text/x-smarty", mode: "smartymixed"}, - {name: "Solr", mime: "text/x-solr", mode: "solr"}, - {name: "Soy", mime: "text/x-soy", mode: "soy", ext: ["soy"], alias: ["closure template"]}, - {name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]}, - {name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]}, - {name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]}, - {name: "MariaDB", mime: "text/x-mariadb", mode: "sql"}, - {name: "sTeX", mime: "text/x-stex", mode: "stex"}, - {name: "LaTeX", mime: "text/x-latex", mode: "stex", ext: ["text", "ltx"], alias: ["tex"]}, - {name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog", ext: ["v"]}, - {name: "Tcl", mime: "text/x-tcl", mode: "tcl", ext: ["tcl"]}, - {name: "Textile", mime: "text/x-textile", mode: "textile", ext: ["textile"]}, - {name: "TiddlyWiki ", mime: "text/x-tiddlywiki", mode: "tiddlywiki"}, - {name: "Tiki wiki", mime: "text/tiki", mode: "tiki"}, - {name: "TOML", mime: "text/x-toml", mode: "toml", ext: ["toml"]}, - {name: "Tornado", mime: "text/x-tornado", mode: "tornado"}, - {name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]}, - {name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]}, - {name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]}, - {name: "VBScript", mime: "text/vbscript", mode: "vbscript", ext: ["vbs"]}, - {name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]}, - {name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]}, - {name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd"], alias: ["rss", "wsdl", "xsd"]}, - {name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]}, - {name: "YAML", mime: "text/x-yaml", mode: "yaml", ext: ["yaml"], alias: ["yml"]}, - {name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]} - ]; - // Ensure all modes have a mime property for backwards compatibility - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.mimes) info.mime = info.mimes[0]; - } - - CodeMirror.findModeByMIME = function(mime) { - mime = mime.toLowerCase(); - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.mime == mime) return info; - if (info.mimes) for (var j = 0; j < info.mimes.length; j++) - if (info.mimes[j] == mime) return info; - } - }; - - CodeMirror.findModeByExtension = function(ext) { - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.ext) for (var j = 0; j < info.ext.length; j++) - if (info.ext[j] == ext) return info; - } - }; - - CodeMirror.findModeByFileName = function(filename) { - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.file && info.file.test(filename)) return info; - } - var dot = filename.lastIndexOf("."); - var ext = dot > -1 && filename.substring(dot + 1, filename.length); - if (ext) return CodeMirror.findModeByExtension(ext); - }; - - CodeMirror.findModeByName = function(name) { - name = name.toLowerCase(); - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.name.toLowerCase() == name) return info; - if (info.alias) for (var j = 0; j < info.alias.length; j++) - if (info.alias[j].toLowerCase() == name) return info; - } - }; -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/mirc/index.html b/shared/html/libs/codemirror/5.0.0/mode/mirc/index.html deleted file mode 100644 index fd2f34e..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/mirc/index.html +++ /dev/null @@ -1,160 +0,0 @@ - - -CodeMirror: mIRC mode - - - - - - - - - - -
-

mIRC mode

-
- - -

MIME types defined: text/mirc.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/mirc/mirc.js b/shared/html/libs/codemirror/5.0.0/mode/mirc/mirc.js deleted file mode 100644 index f0d5c6a..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/mirc/mirc.js +++ /dev/null @@ -1,193 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -//mIRC mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMIME("text/mirc", "mirc"); -CodeMirror.defineMode("mirc", function() { - function parseWords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var specials = parseWords("$! $$ $& $? $+ $abook $abs $active $activecid " + - "$activewid $address $addtok $agent $agentname $agentstat $agentver " + - "$alias $and $anick $ansi2mirc $aop $appactive $appstate $asc $asctime " + - "$asin $atan $avoice $away $awaymsg $awaytime $banmask $base $bfind " + - "$binoff $biton $bnick $bvar $bytes $calc $cb $cd $ceil $chan $chanmodes " + - "$chantypes $chat $chr $cid $clevel $click $cmdbox $cmdline $cnick $color " + - "$com $comcall $comchan $comerr $compact $compress $comval $cos $count " + - "$cr $crc $creq $crlf $ctime $ctimer $ctrlenter $date $day $daylight " + - "$dbuh $dbuw $dccignore $dccport $dde $ddename $debug $decode $decompress " + - "$deltok $devent $dialog $did $didreg $didtok $didwm $disk $dlevel $dll " + - "$dllcall $dname $dns $duration $ebeeps $editbox $emailaddr $encode $error " + - "$eval $event $exist $feof $ferr $fgetc $file $filename $filtered $finddir " + - "$finddirn $findfile $findfilen $findtok $fline $floor $fopen $fread $fserve " + - "$fulladdress $fulldate $fullname $fullscreen $get $getdir $getdot $gettok $gmt " + - "$group $halted $hash $height $hfind $hget $highlight $hnick $hotline " + - "$hotlinepos $ial $ialchan $ibl $idle $iel $ifmatch $ignore $iif $iil " + - "$inelipse $ini $inmidi $inpaste $inpoly $input $inrect $inroundrect " + - "$insong $instok $int $inwave $ip $isalias $isbit $isdde $isdir $isfile " + - "$isid $islower $istok $isupper $keychar $keyrpt $keyval $knick $lactive " + - "$lactivecid $lactivewid $left $len $level $lf $line $lines $link $lock " + - "$lock $locked $log $logstamp $logstampfmt $longfn $longip $lower $ltimer " + - "$maddress $mask $matchkey $matchtok $md5 $me $menu $menubar $menucontext " + - "$menutype $mid $middir $mircdir $mircexe $mircini $mklogfn $mnick $mode " + - "$modefirst $modelast $modespl $mouse $msfile $network $newnick $nick $nofile " + - "$nopath $noqt $not $notags $notify $null $numeric $numok $oline $onpoly " + - "$opnick $or $ord $os $passivedcc $pic $play $pnick $port $portable $portfree " + - "$pos $prefix $prop $protect $puttok $qt $query $rand $r $rawmsg $read $readomo " + - "$readn $regex $regml $regsub $regsubex $remove $remtok $replace $replacex " + - "$reptok $result $rgb $right $round $scid $scon $script $scriptdir $scriptline " + - "$sdir $send $server $serverip $sfile $sha1 $shortfn $show $signal $sin " + - "$site $sline $snick $snicks $snotify $sock $sockbr $sockerr $sockname " + - "$sorttok $sound $sqrt $ssl $sreq $sslready $status $strip $str $stripped " + - "$syle $submenu $switchbar $tan $target $ticks $time $timer $timestamp " + - "$timestampfmt $timezone $tip $titlebar $toolbar $treebar $trust $ulevel " + - "$ulist $upper $uptime $url $usermode $v1 $v2 $var $vcmd $vcmdstat $vcmdver " + - "$version $vnick $vol $wid $width $wildsite $wildtok $window $wrap $xor"); - var keywords = parseWords("abook ajinvite alias aline ame amsg anick aop auser autojoin avoice " + - "away background ban bcopy beep bread break breplace bset btrunc bunset bwrite " + - "channel clear clearall cline clipboard close cnick color comclose comopen " + - "comreg continue copy creq ctcpreply ctcps dcc dccserver dde ddeserver " + - "debug dec describe dialog did didtok disable disconnect dlevel dline dll " + - "dns dqwindow drawcopy drawdot drawfill drawline drawpic drawrect drawreplace " + - "drawrot drawsave drawscroll drawtext ebeeps echo editbox emailaddr enable " + - "events exit fclose filter findtext finger firewall flash flist flood flush " + - "flushini font fopen fseek fsend fserve fullname fwrite ghide gload gmove " + - "gopts goto gplay gpoint gqreq groups gshow gsize gstop gtalk gunload hadd " + - "halt haltdef hdec hdel help hfree hinc hload hmake hop hsave ial ialclear " + - "ialmark identd if ignore iline inc invite iuser join kick linesep links list " + - "load loadbuf localinfo log mdi me menubar mkdir mnick mode msg nick noop notice " + - "notify omsg onotice part partall pdcc perform play playctrl pop protect pvoice " + - "qme qmsg query queryn quit raw reload remini remote remove rename renwin " + - "reseterror resetidle return rlevel rline rmdir run ruser save savebuf saveini " + - "say scid scon server set showmirc signam sline sockaccept sockclose socklist " + - "socklisten sockmark sockopen sockpause sockread sockrename sockudp sockwrite " + - "sound speak splay sreq strip switchbar timer timestamp titlebar tnick tokenize " + - "toolbar topic tray treebar ulist unload unset unsetall updatenl url uwho " + - "var vcadd vcmd vcrem vol while whois window winhelp write writeint if isalnum " + - "isalpha isaop isavoice isban ischan ishop isignore isin isincs isletter islower " + - "isnotify isnum ison isop isprotect isreg isupper isvoice iswm iswmcs " + - "elseif else goto menu nicklist status title icon size option text edit " + - "button check radio box scroll list combo link tab item"); - var functions = parseWords("if elseif else and not or eq ne in ni for foreach while switch"); - var isOperatorChar = /[+\-*&%=<>!?^\/\|]/; - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - function tokenBase(stream, state) { - var beforeParams = state.beforeParams; - state.beforeParams = false; - var ch = stream.next(); - if (/[\[\]{}\(\),\.]/.test(ch)) { - if (ch == "(" && beforeParams) state.inParams = true; - else if (ch == ")") state.inParams = false; - return null; - } - else if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - else if (ch == "\\") { - stream.eat("\\"); - stream.eat(/./); - return "number"; - } - else if (ch == "/" && stream.eat("*")) { - return chain(stream, state, tokenComment); - } - else if (ch == ";" && stream.match(/ *\( *\(/)) { - return chain(stream, state, tokenUnparsed); - } - else if (ch == ";" && !state.inParams) { - stream.skipToEnd(); - return "comment"; - } - else if (ch == '"') { - stream.eat(/"/); - return "keyword"; - } - else if (ch == "$") { - stream.eatWhile(/[$_a-z0-9A-Z\.:]/); - if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) { - return "keyword"; - } - else { - state.beforeParams = true; - return "builtin"; - } - } - else if (ch == "%") { - stream.eatWhile(/[^,^\s^\(^\)]/); - state.beforeParams = true; - return "string"; - } - else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - else { - stream.eatWhile(/[\w\$_{}]/); - var word = stream.current().toLowerCase(); - if (keywords && keywords.propertyIsEnumerable(word)) - return "keyword"; - if (functions && functions.propertyIsEnumerable(word)) { - state.beforeParams = true; - return "keyword"; - } - return null; - } - } - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - function tokenUnparsed(stream, state) { - var maybeEnd = 0, ch; - while (ch = stream.next()) { - if (ch == ";" && maybeEnd == 2) { - state.tokenize = tokenBase; - break; - } - if (ch == ")") - maybeEnd++; - else if (ch != " ") - maybeEnd = 0; - } - return "meta"; - } - return { - startState: function() { - return { - tokenize: tokenBase, - beforeParams: false, - inParams: false - }; - }, - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - } - }; -}); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/mllike/index.html b/shared/html/libs/codemirror/5.0.0/mode/mllike/index.html deleted file mode 100644 index 5923af8..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/mllike/index.html +++ /dev/null @@ -1,179 +0,0 @@ - - -CodeMirror: ML-like mode - - - - - - - - - - -
-

OCaml mode

- - - - -

F# mode

- - - - - -

MIME types defined: text/x-ocaml (OCaml) and text/x-fsharp (F#).

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/mllike/mllike.js b/shared/html/libs/codemirror/5.0.0/mode/mllike/mllike.js deleted file mode 100644 index 04ab1c9..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/mllike/mllike.js +++ /dev/null @@ -1,205 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('mllike', function(_config, parserConfig) { - var words = { - 'let': 'keyword', - 'rec': 'keyword', - 'in': 'keyword', - 'of': 'keyword', - 'and': 'keyword', - 'if': 'keyword', - 'then': 'keyword', - 'else': 'keyword', - 'for': 'keyword', - 'to': 'keyword', - 'while': 'keyword', - 'do': 'keyword', - 'done': 'keyword', - 'fun': 'keyword', - 'function': 'keyword', - 'val': 'keyword', - 'type': 'keyword', - 'mutable': 'keyword', - 'match': 'keyword', - 'with': 'keyword', - 'try': 'keyword', - 'open': 'builtin', - 'ignore': 'builtin', - 'begin': 'keyword', - 'end': 'keyword' - }; - - var extraWords = parserConfig.extraWords || {}; - for (var prop in extraWords) { - if (extraWords.hasOwnProperty(prop)) { - words[prop] = parserConfig.extraWords[prop]; - } - } - - function tokenBase(stream, state) { - var ch = stream.next(); - - if (ch === '"') { - state.tokenize = tokenString; - return state.tokenize(stream, state); - } - if (ch === '(') { - if (stream.eat('*')) { - state.commentLevel++; - state.tokenize = tokenComment; - return state.tokenize(stream, state); - } - } - if (ch === '~') { - stream.eatWhile(/\w/); - return 'variable-2'; - } - if (ch === '`') { - stream.eatWhile(/\w/); - return 'quote'; - } - if (ch === '/' && parserConfig.slashComments && stream.eat('/')) { - stream.skipToEnd(); - return 'comment'; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\d]/); - if (stream.eat('.')) { - stream.eatWhile(/[\d]/); - } - return 'number'; - } - if ( /[+\-*&%=<>!?|]/.test(ch)) { - return 'operator'; - } - stream.eatWhile(/\w/); - var cur = stream.current(); - return words[cur] || 'variable'; - } - - function tokenString(stream, state) { - var next, end = false, escaped = false; - while ((next = stream.next()) != null) { - if (next === '"' && !escaped) { - end = true; - break; - } - escaped = !escaped && next === '\\'; - } - if (end && !escaped) { - state.tokenize = tokenBase; - } - return 'string'; - }; - - function tokenComment(stream, state) { - var prev, next; - while(state.commentLevel > 0 && (next = stream.next()) != null) { - if (prev === '(' && next === '*') state.commentLevel++; - if (prev === '*' && next === ')') state.commentLevel--; - prev = next; - } - if (state.commentLevel <= 0) { - state.tokenize = tokenBase; - } - return 'comment'; - } - - return { - startState: function() {return {tokenize: tokenBase, commentLevel: 0};}, - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - }, - - blockCommentStart: "(*", - blockCommentEnd: "*)", - lineComment: parserConfig.slashComments ? "//" : null - }; -}); - -CodeMirror.defineMIME('text/x-ocaml', { - name: 'mllike', - extraWords: { - 'succ': 'keyword', - 'trace': 'builtin', - 'exit': 'builtin', - 'print_string': 'builtin', - 'print_endline': 'builtin', - 'true': 'atom', - 'false': 'atom', - 'raise': 'keyword' - } -}); - -CodeMirror.defineMIME('text/x-fsharp', { - name: 'mllike', - extraWords: { - 'abstract': 'keyword', - 'as': 'keyword', - 'assert': 'keyword', - 'base': 'keyword', - 'class': 'keyword', - 'default': 'keyword', - 'delegate': 'keyword', - 'downcast': 'keyword', - 'downto': 'keyword', - 'elif': 'keyword', - 'exception': 'keyword', - 'extern': 'keyword', - 'finally': 'keyword', - 'global': 'keyword', - 'inherit': 'keyword', - 'inline': 'keyword', - 'interface': 'keyword', - 'internal': 'keyword', - 'lazy': 'keyword', - 'let!': 'keyword', - 'member' : 'keyword', - 'module': 'keyword', - 'namespace': 'keyword', - 'new': 'keyword', - 'null': 'keyword', - 'override': 'keyword', - 'private': 'keyword', - 'public': 'keyword', - 'return': 'keyword', - 'return!': 'keyword', - 'select': 'keyword', - 'static': 'keyword', - 'struct': 'keyword', - 'upcast': 'keyword', - 'use': 'keyword', - 'use!': 'keyword', - 'val': 'keyword', - 'when': 'keyword', - 'yield': 'keyword', - 'yield!': 'keyword', - - 'List': 'builtin', - 'Seq': 'builtin', - 'Map': 'builtin', - 'Set': 'builtin', - 'int': 'builtin', - 'string': 'builtin', - 'raise': 'builtin', - 'failwith': 'builtin', - 'not': 'builtin', - 'true': 'builtin', - 'false': 'builtin' - }, - slashComments: true -}); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/modelica/index.html b/shared/html/libs/codemirror/5.0.0/mode/modelica/index.html deleted file mode 100644 index 408c3b1..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/modelica/index.html +++ /dev/null @@ -1,67 +0,0 @@ - - -CodeMirror: Modelica mode - - - - - - - - - - - - -
-

Modelica mode

- -
- - - -

Simple mode that tries to handle Modelica as well as it can.

- -

MIME types defined: text/x-modelica - (Modlica code).

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/modelica/modelica.js b/shared/html/libs/codemirror/5.0.0/mode/modelica/modelica.js deleted file mode 100644 index 77ec7a3..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/modelica/modelica.js +++ /dev/null @@ -1,245 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Modelica support for CodeMirror, copyright (c) by Lennart Ochel - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -}) - -(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("modelica", function(config, parserConfig) { - - var indentUnit = config.indentUnit; - var keywords = parserConfig.keywords || {}; - var builtin = parserConfig.builtin || {}; - var atoms = parserConfig.atoms || {}; - - var isSingleOperatorChar = /[;=\(:\),{}.*<>+\-\/^\[\]]/; - var isDoubleOperatorChar = /(:=|<=|>=|==|<>|\.\+|\.\-|\.\*|\.\/|\.\^)/; - var isDigit = /[0-9]/; - var isNonDigit = /[_a-zA-Z]/; - - function tokenLineComment(stream, state) { - stream.skipToEnd(); - state.tokenize = null; - return "comment"; - } - - function tokenBlockComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (maybeEnd && ch == "/") { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function tokenString(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == '"' && !escaped) { - state.tokenize = null; - state.sol = false; - break; - } - escaped = !escaped && ch == "\\"; - } - - return "string"; - } - - function tokenIdent(stream, state) { - stream.eatWhile(isDigit); - while (stream.eat(isDigit) || stream.eat(isNonDigit)) { } - - - var cur = stream.current(); - - if(state.sol && (cur == "package" || cur == "model" || cur == "when" || cur == "connector")) state.level++; - else if(state.sol && cur == "end" && state.level > 0) state.level--; - - state.tokenize = null; - state.sol = false; - - if (keywords.propertyIsEnumerable(cur)) return "keyword"; - else if (builtin.propertyIsEnumerable(cur)) return "builtin"; - else if (atoms.propertyIsEnumerable(cur)) return "atom"; - else return "variable"; - } - - function tokenQIdent(stream, state) { - while (stream.eat(/[^']/)) { } - - state.tokenize = null; - state.sol = false; - - if(stream.eat("'")) - return "variable"; - else - return "error"; - } - - function tokenUnsignedNuber(stream, state) { - stream.eatWhile(isDigit); - if (stream.eat('.')) { - stream.eatWhile(isDigit); - } - if (stream.eat('e') || stream.eat('E')) { - if (!stream.eat('-')) - stream.eat('+'); - stream.eatWhile(isDigit); - } - - state.tokenize = null; - state.sol = false; - return "number"; - } - - // Interface - return { - startState: function() { - return { - tokenize: null, - level: 0, - sol: true - }; - }, - - token: function(stream, state) { - if(state.tokenize != null) { - return state.tokenize(stream, state); - } - - if(stream.sol()) { - state.sol = true; - } - - // WHITESPACE - if(stream.eatSpace()) { - state.tokenize = null; - return null; - } - - var ch = stream.next(); - - // LINECOMMENT - if(ch == '/' && stream.eat('/')) { - state.tokenize = tokenLineComment; - } - // BLOCKCOMMENT - else if(ch == '/' && stream.eat('*')) { - state.tokenize = tokenBlockComment; - } - // TWO SYMBOL TOKENS - else if(isDoubleOperatorChar.test(ch+stream.peek())) { - stream.next(); - state.tokenize = null; - return "operator"; - } - // SINGLE SYMBOL TOKENS - else if(isSingleOperatorChar.test(ch)) { - state.tokenize = null; - return "operator"; - } - // IDENT - else if(isNonDigit.test(ch)) { - state.tokenize = tokenIdent; - } - // Q-IDENT - else if(ch == "'" && stream.peek() && stream.peek() != "'") { - state.tokenize = tokenQIdent; - } - // STRING - else if(ch == '"') { - state.tokenize = tokenString; - } - // UNSIGNED_NUBER - else if(isDigit.test(ch)) { - state.tokenize = tokenUnsignedNuber; - } - // ERROR - else { - state.tokenize = null; - return "error"; - } - - return state.tokenize(stream, state); - }, - - indent: function(state, textAfter) { - if (state.tokenize != null) return CodeMirror.Pass; - - var level = state.level; - if(/(algorithm)/.test(textAfter)) level--; - if(/(equation)/.test(textAfter)) level--; - if(/(initial algorithm)/.test(textAfter)) level--; - if(/(initial equation)/.test(textAfter)) level--; - if(/(end)/.test(textAfter)) level--; - - if(level > 0) - return indentUnit*level; - else - return 0; - }, - - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//" - }; - }); - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i=0; i - -CodeMirror: NGINX mode - - - - - - - - - - - - - -
-

NGINX mode

-
- - -

MIME types defined: text/nginx.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/nginx/nginx.js b/shared/html/libs/codemirror/5.0.0/mode/nginx/nginx.js deleted file mode 100644 index 135b9cc..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/nginx/nginx.js +++ /dev/null @@ -1,178 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("nginx", function(config) { - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var keywords = words( - /* ngxDirectiveControl */ "break return rewrite set" + - /* ngxDirective */ " accept_mutex accept_mutex_delay access_log add_after_body add_before_body add_header addition_types aio alias allow ancient_browser ancient_browser_value auth_basic auth_basic_user_file auth_http auth_http_header auth_http_timeout autoindex autoindex_exact_size autoindex_localtime charset charset_types client_body_buffer_size client_body_in_file_only client_body_in_single_buffer client_body_temp_path client_body_timeout client_header_buffer_size client_header_timeout client_max_body_size connection_pool_size create_full_put_path daemon dav_access dav_methods debug_connection debug_points default_type degradation degrade deny devpoll_changes devpoll_events directio directio_alignment empty_gif env epoll_events error_log eventport_events expires fastcgi_bind fastcgi_buffer_size fastcgi_buffers fastcgi_busy_buffers_size fastcgi_cache fastcgi_cache_key fastcgi_cache_methods fastcgi_cache_min_uses fastcgi_cache_path fastcgi_cache_use_stale fastcgi_cache_valid fastcgi_catch_stderr fastcgi_connect_timeout fastcgi_hide_header fastcgi_ignore_client_abort fastcgi_ignore_headers fastcgi_index fastcgi_intercept_errors fastcgi_max_temp_file_size fastcgi_next_upstream fastcgi_param fastcgi_pass_header fastcgi_pass_request_body fastcgi_pass_request_headers fastcgi_read_timeout fastcgi_send_lowat fastcgi_send_timeout fastcgi_split_path_info fastcgi_store fastcgi_store_access fastcgi_temp_file_write_size fastcgi_temp_path fastcgi_upstream_fail_timeout fastcgi_upstream_max_fails flv geoip_city geoip_country google_perftools_profiles gzip gzip_buffers gzip_comp_level gzip_disable gzip_hash gzip_http_version gzip_min_length gzip_no_buffer gzip_proxied gzip_static gzip_types gzip_vary gzip_window if_modified_since ignore_invalid_headers image_filter image_filter_buffer image_filter_jpeg_quality image_filter_transparency imap_auth imap_capabilities imap_client_buffer index ip_hash keepalive_requests keepalive_timeout kqueue_changes kqueue_events large_client_header_buffers limit_conn limit_conn_log_level limit_rate limit_rate_after limit_req limit_req_log_level limit_req_zone limit_zone lingering_time lingering_timeout lock_file log_format log_not_found log_subrequest map_hash_bucket_size map_hash_max_size master_process memcached_bind memcached_buffer_size memcached_connect_timeout memcached_next_upstream memcached_read_timeout memcached_send_timeout memcached_upstream_fail_timeout memcached_upstream_max_fails merge_slashes min_delete_depth modern_browser modern_browser_value msie_padding msie_refresh multi_accept open_file_cache open_file_cache_errors open_file_cache_events open_file_cache_min_uses open_file_cache_valid open_log_file_cache output_buffers override_charset perl perl_modules perl_require perl_set pid pop3_auth pop3_capabilities port_in_redirect postpone_gzipping postpone_output protocol proxy proxy_bind proxy_buffer proxy_buffer_size proxy_buffering proxy_buffers proxy_busy_buffers_size proxy_cache proxy_cache_key proxy_cache_methods proxy_cache_min_uses proxy_cache_path proxy_cache_use_stale proxy_cache_valid proxy_connect_timeout proxy_headers_hash_bucket_size proxy_headers_hash_max_size proxy_hide_header proxy_ignore_client_abort proxy_ignore_headers proxy_intercept_errors proxy_max_temp_file_size proxy_method proxy_next_upstream proxy_pass_error_message proxy_pass_header proxy_pass_request_body proxy_pass_request_headers proxy_read_timeout proxy_redirect proxy_send_lowat proxy_send_timeout proxy_set_body proxy_set_header proxy_ssl_session_reuse proxy_store proxy_store_access proxy_temp_file_write_size proxy_temp_path proxy_timeout proxy_upstream_fail_timeout proxy_upstream_max_fails random_index read_ahead real_ip_header recursive_error_pages request_pool_size reset_timedout_connection resolver resolver_timeout rewrite_log rtsig_overflow_events rtsig_overflow_test rtsig_overflow_threshold rtsig_signo satisfy secure_link_secret send_lowat send_timeout sendfile sendfile_max_chunk server_name_in_redirect server_names_hash_bucket_size server_names_hash_max_size server_tokens set_real_ip_from smtp_auth smtp_capabilities smtp_client_buffer smtp_greeting_delay so_keepalive source_charset ssi ssi_ignore_recycled_buffers ssi_min_file_chunk ssi_silent_errors ssi_types ssi_value_length ssl ssl_certificate ssl_certificate_key ssl_ciphers ssl_client_certificate ssl_crl ssl_dhparam ssl_engine ssl_prefer_server_ciphers ssl_protocols ssl_session_cache ssl_session_timeout ssl_verify_client ssl_verify_depth starttls stub_status sub_filter sub_filter_once sub_filter_types tcp_nodelay tcp_nopush thread_stack_size timeout timer_resolution types_hash_bucket_size types_hash_max_size underscores_in_headers uninitialized_variable_warn use user userid userid_domain userid_expires userid_mark userid_name userid_p3p userid_path userid_service valid_referers variables_hash_bucket_size variables_hash_max_size worker_connections worker_cpu_affinity worker_priority worker_processes worker_rlimit_core worker_rlimit_nofile worker_rlimit_sigpending worker_threads working_directory xclient xml_entities xslt_stylesheet xslt_typesdrew@li229-23" - ); - - var keywords_block = words( - /* ngxDirectiveBlock */ "http mail events server types location upstream charset_map limit_except if geo map" - ); - - var keywords_important = words( - /* ngxDirectiveImportant */ "include root server server_name listen internal proxy_pass memcached_pass fastcgi_pass try_files" - ); - - var indentUnit = config.indentUnit, type; - function ret(style, tp) {type = tp; return style;} - - function tokenBase(stream, state) { - - - stream.eatWhile(/[\w\$_]/); - - var cur = stream.current(); - - - if (keywords.propertyIsEnumerable(cur)) { - return "keyword"; - } - else if (keywords_block.propertyIsEnumerable(cur)) { - return "variable-2"; - } - else if (keywords_important.propertyIsEnumerable(cur)) { - return "string-2"; - } - /**/ - - var ch = stream.next(); - if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());} - else if (ch == "/" && stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } - else if (ch == "<" && stream.eat("!")) { - state.tokenize = tokenSGMLComment; - return tokenSGMLComment(stream, state); - } - else if (ch == "=") ret(null, "compare"); - else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare"); - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - else if (ch == "#") { - stream.skipToEnd(); - return ret("comment", "comment"); - } - else if (ch == "!") { - stream.match(/^\s*\w*/); - return ret("keyword", "important"); - } - else if (/\d/.test(ch)) { - stream.eatWhile(/[\w.%]/); - return ret("number", "unit"); - } - else if (/[,.+>*\/]/.test(ch)) { - return ret(null, "select-op"); - } - else if (/[;{}:\[\]]/.test(ch)) { - return ret(null, ch); - } - else { - stream.eatWhile(/[\w\\\-]/); - return ret("variable", "variable"); - } - } - - function tokenCComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (maybeEnd && ch == "/") { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - function tokenSGMLComment(stream, state) { - var dashes = 0, ch; - while ((ch = stream.next()) != null) { - if (dashes >= 2 && ch == ">") { - state.tokenize = tokenBase; - break; - } - dashes = (ch == "-") ? dashes + 1 : 0; - } - return ret("comment", "comment"); - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) - break; - escaped = !escaped && ch == "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return ret("string", "string"); - }; - } - - return { - startState: function(base) { - return {tokenize: tokenBase, - baseIndent: base || 0, - stack: []}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - type = null; - var style = state.tokenize(stream, state); - - var context = state.stack[state.stack.length-1]; - if (type == "hash" && context == "rule") style = "atom"; - else if (style == "variable") { - if (context == "rule") style = "number"; - else if (!context || context == "@media{") style = "tag"; - } - - if (context == "rule" && /^[\{\};]$/.test(type)) - state.stack.pop(); - if (type == "{") { - if (context == "@media") state.stack[state.stack.length-1] = "@media{"; - else state.stack.push("{"); - } - else if (type == "}") state.stack.pop(); - else if (type == "@media") state.stack.push("@media"); - else if (context == "{" && type != "comment") state.stack.push("rule"); - return style; - }, - - indent: function(state, textAfter) { - var n = state.stack.length; - if (/^\}/.test(textAfter)) - n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1; - return state.baseIndent + n * indentUnit; - }, - - electricChars: "}" - }; -}); - -CodeMirror.defineMIME("text/nginx", "text/x-nginx-conf"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/ntriples/index.html b/shared/html/libs/codemirror/5.0.0/mode/ntriples/index.html deleted file mode 100644 index 1355e71..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/ntriples/index.html +++ /dev/null @@ -1,45 +0,0 @@ - - -CodeMirror: NTriples mode - - - - - - - - - -
-

NTriples mode

-
- -
- - -

MIME types defined: text/n-triples.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/ntriples/ntriples.js b/shared/html/libs/codemirror/5.0.0/mode/ntriples/ntriples.js deleted file mode 100644 index 0524b1e..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/ntriples/ntriples.js +++ /dev/null @@ -1,186 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/********************************************************** -* This script provides syntax highlighting support for -* the Ntriples format. -* Ntriples format specification: -* http://www.w3.org/TR/rdf-testcases/#ntriples -***********************************************************/ - -/* - The following expression defines the defined ASF grammar transitions. - - pre_subject -> - { - ( writing_subject_uri | writing_bnode_uri ) - -> pre_predicate - -> writing_predicate_uri - -> pre_object - -> writing_object_uri | writing_object_bnode | - ( - writing_object_literal - -> writing_literal_lang | writing_literal_type - ) - -> post_object - -> BEGIN - } otherwise { - -> ERROR - } -*/ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("ntriples", function() { - - var Location = { - PRE_SUBJECT : 0, - WRITING_SUB_URI : 1, - WRITING_BNODE_URI : 2, - PRE_PRED : 3, - WRITING_PRED_URI : 4, - PRE_OBJ : 5, - WRITING_OBJ_URI : 6, - WRITING_OBJ_BNODE : 7, - WRITING_OBJ_LITERAL : 8, - WRITING_LIT_LANG : 9, - WRITING_LIT_TYPE : 10, - POST_OBJ : 11, - ERROR : 12 - }; - function transitState(currState, c) { - var currLocation = currState.location; - var ret; - - // Opening. - if (currLocation == Location.PRE_SUBJECT && c == '<') ret = Location.WRITING_SUB_URI; - else if(currLocation == Location.PRE_SUBJECT && c == '_') ret = Location.WRITING_BNODE_URI; - else if(currLocation == Location.PRE_PRED && c == '<') ret = Location.WRITING_PRED_URI; - else if(currLocation == Location.PRE_OBJ && c == '<') ret = Location.WRITING_OBJ_URI; - else if(currLocation == Location.PRE_OBJ && c == '_') ret = Location.WRITING_OBJ_BNODE; - else if(currLocation == Location.PRE_OBJ && c == '"') ret = Location.WRITING_OBJ_LITERAL; - - // Closing. - else if(currLocation == Location.WRITING_SUB_URI && c == '>') ret = Location.PRE_PRED; - else if(currLocation == Location.WRITING_BNODE_URI && c == ' ') ret = Location.PRE_PRED; - else if(currLocation == Location.WRITING_PRED_URI && c == '>') ret = Location.PRE_OBJ; - else if(currLocation == Location.WRITING_OBJ_URI && c == '>') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_OBJ_BNODE && c == ' ') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '"') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_LIT_LANG && c == ' ') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_LIT_TYPE && c == '>') ret = Location.POST_OBJ; - - // Closing typed and language literal. - else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '@') ret = Location.WRITING_LIT_LANG; - else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '^') ret = Location.WRITING_LIT_TYPE; - - // Spaces. - else if( c == ' ' && - ( - currLocation == Location.PRE_SUBJECT || - currLocation == Location.PRE_PRED || - currLocation == Location.PRE_OBJ || - currLocation == Location.POST_OBJ - ) - ) ret = currLocation; - - // Reset. - else if(currLocation == Location.POST_OBJ && c == '.') ret = Location.PRE_SUBJECT; - - // Error - else ret = Location.ERROR; - - currState.location=ret; - } - - return { - startState: function() { - return { - location : Location.PRE_SUBJECT, - uris : [], - anchors : [], - bnodes : [], - langs : [], - types : [] - }; - }, - token: function(stream, state) { - var ch = stream.next(); - if(ch == '<') { - transitState(state, ch); - var parsedURI = ''; - stream.eatWhile( function(c) { if( c != '#' && c != '>' ) { parsedURI += c; return true; } return false;} ); - state.uris.push(parsedURI); - if( stream.match('#', false) ) return 'variable'; - stream.next(); - transitState(state, '>'); - return 'variable'; - } - if(ch == '#') { - var parsedAnchor = ''; - stream.eatWhile(function(c) { if(c != '>' && c != ' ') { parsedAnchor+= c; return true; } return false;}); - state.anchors.push(parsedAnchor); - return 'variable-2'; - } - if(ch == '>') { - transitState(state, '>'); - return 'variable'; - } - if(ch == '_') { - transitState(state, ch); - var parsedBNode = ''; - stream.eatWhile(function(c) { if( c != ' ' ) { parsedBNode += c; return true; } return false;}); - state.bnodes.push(parsedBNode); - stream.next(); - transitState(state, ' '); - return 'builtin'; - } - if(ch == '"') { - transitState(state, ch); - stream.eatWhile( function(c) { return c != '"'; } ); - stream.next(); - if( stream.peek() != '@' && stream.peek() != '^' ) { - transitState(state, '"'); - } - return 'string'; - } - if( ch == '@' ) { - transitState(state, '@'); - var parsedLang = ''; - stream.eatWhile(function(c) { if( c != ' ' ) { parsedLang += c; return true; } return false;}); - state.langs.push(parsedLang); - stream.next(); - transitState(state, ' '); - return 'string-2'; - } - if( ch == '^' ) { - stream.next(); - transitState(state, '^'); - var parsedType = ''; - stream.eatWhile(function(c) { if( c != '>' ) { parsedType += c; return true; } return false;} ); - state.types.push(parsedType); - stream.next(); - transitState(state, '>'); - return 'variable'; - } - if( ch == ' ' ) { - transitState(state, ch); - } - if( ch == '.' ) { - transitState(state, ch); - } - } - }; -}); - -CodeMirror.defineMIME("text/n-triples", "ntriples"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/octave/index.html b/shared/html/libs/codemirror/5.0.0/mode/octave/index.html deleted file mode 100644 index 79df581..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/octave/index.html +++ /dev/null @@ -1,83 +0,0 @@ - - -CodeMirror: Octave mode - - - - - - - - - -
-

Octave mode

- -
- - -

MIME types defined: text/x-octave.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/octave/octave.js b/shared/html/libs/codemirror/5.0.0/mode/octave/octave.js deleted file mode 100644 index a7bec03..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/octave/octave.js +++ /dev/null @@ -1,135 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("octave", function() { - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); - } - - var singleOperators = new RegExp("^[\\+\\-\\*/&|\\^~<>!@'\\\\]"); - var singleDelimiters = new RegExp('^[\\(\\[\\{\\},:=;]'); - var doubleOperators = new RegExp("^((==)|(~=)|(<=)|(>=)|(<<)|(>>)|(\\.[\\+\\-\\*/\\^\\\\]))"); - var doubleDelimiters = new RegExp("^((!=)|(\\+=)|(\\-=)|(\\*=)|(/=)|(&=)|(\\|=)|(\\^=))"); - var tripleDelimiters = new RegExp("^((>>=)|(<<=))"); - var expressionEnd = new RegExp("^[\\]\\)]"); - var identifiers = new RegExp("^[_A-Za-z\xa1-\uffff][_A-Za-z0-9\xa1-\uffff]*"); - - var builtins = wordRegexp([ - 'error', 'eval', 'function', 'abs', 'acos', 'atan', 'asin', 'cos', - 'cosh', 'exp', 'log', 'prod', 'sum', 'log10', 'max', 'min', 'sign', 'sin', 'sinh', - 'sqrt', 'tan', 'reshape', 'break', 'zeros', 'default', 'margin', 'round', 'ones', - 'rand', 'syn', 'ceil', 'floor', 'size', 'clear', 'zeros', 'eye', 'mean', 'std', 'cov', - 'det', 'eig', 'inv', 'norm', 'rank', 'trace', 'expm', 'logm', 'sqrtm', 'linspace', 'plot', - 'title', 'xlabel', 'ylabel', 'legend', 'text', 'grid', 'meshgrid', 'mesh', 'num2str', - 'fft', 'ifft', 'arrayfun', 'cellfun', 'input', 'fliplr', 'flipud', 'ismember' - ]); - - var keywords = wordRegexp([ - 'return', 'case', 'switch', 'else', 'elseif', 'end', 'endif', 'endfunction', - 'if', 'otherwise', 'do', 'for', 'while', 'try', 'catch', 'classdef', 'properties', 'events', - 'methods', 'global', 'persistent', 'endfor', 'endwhile', 'printf', 'sprintf', 'disp', 'until', - 'continue', 'pkg' - ]); - - - // tokenizers - function tokenTranspose(stream, state) { - if (!stream.sol() && stream.peek() === '\'') { - stream.next(); - state.tokenize = tokenBase; - return 'operator'; - } - state.tokenize = tokenBase; - return tokenBase(stream, state); - } - - - function tokenComment(stream, state) { - if (stream.match(/^.*%}/)) { - state.tokenize = tokenBase; - return 'comment'; - }; - stream.skipToEnd(); - return 'comment'; - } - - function tokenBase(stream, state) { - // whitespaces - if (stream.eatSpace()) return null; - - // Handle one line Comments - if (stream.match('%{')){ - state.tokenize = tokenComment; - stream.skipToEnd(); - return 'comment'; - } - - if (stream.match(/^[%#]/)){ - stream.skipToEnd(); - return 'comment'; - } - - // Handle Number Literals - if (stream.match(/^[0-9\.+-]/, false)) { - if (stream.match(/^[+-]?0x[0-9a-fA-F]+[ij]?/)) { - stream.tokenize = tokenBase; - return 'number'; }; - if (stream.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?[ij]?/)) { return 'number'; }; - if (stream.match(/^[+-]?\d+([EeDd][+-]?\d+)?[ij]?/)) { return 'number'; }; - } - if (stream.match(wordRegexp(['nan','NaN','inf','Inf']))) { return 'number'; }; - - // Handle Strings - if (stream.match(/^"([^"]|(""))*"/)) { return 'string'; } ; - if (stream.match(/^'([^']|(''))*'/)) { return 'string'; } ; - - // Handle words - if (stream.match(keywords)) { return 'keyword'; } ; - if (stream.match(builtins)) { return 'builtin'; } ; - if (stream.match(identifiers)) { return 'variable'; } ; - - if (stream.match(singleOperators) || stream.match(doubleOperators)) { return 'operator'; }; - if (stream.match(singleDelimiters) || stream.match(doubleDelimiters) || stream.match(tripleDelimiters)) { return null; }; - - if (stream.match(expressionEnd)) { - state.tokenize = tokenTranspose; - return null; - }; - - - // Handle non-detected items - stream.next(); - return 'error'; - }; - - - return { - startState: function() { - return { - tokenize: tokenBase - }; - }, - - token: function(stream, state) { - var style = state.tokenize(stream, state); - if (style === 'number' || style === 'variable'){ - state.tokenize = tokenTranspose; - } - return style; - } - }; -}); - -CodeMirror.defineMIME("text/x-octave", "octave"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/pascal/index.html b/shared/html/libs/codemirror/5.0.0/mode/pascal/index.html deleted file mode 100644 index f8a99ad..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/pascal/index.html +++ /dev/null @@ -1,61 +0,0 @@ - - -CodeMirror: Pascal mode - - - - - - - - - -
-

Pascal mode

- - -
- - - -

MIME types defined: text/x-pascal.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/pascal/pascal.js b/shared/html/libs/codemirror/5.0.0/mode/pascal/pascal.js deleted file mode 100644 index 2d0c3d4..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/pascal/pascal.js +++ /dev/null @@ -1,109 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("pascal", function() { - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var keywords = words("and array begin case const div do downto else end file for forward integer " + - "boolean char function goto if in label mod nil not of or packed procedure " + - "program record repeat set string then to type until var while with"); - var atoms = {"null": true}; - - var isOperatorChar = /[+\-*&%=<>!?|\/]/; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == "#" && state.startOfLine) { - stream.skipToEnd(); - return "meta"; - } - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (ch == "(" && stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - return null; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (ch == "/") { - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) return "keyword"; - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !escaped) state.tokenize = null; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == ")" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - // Interface - - return { - startState: function() { - return {tokenize: null}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - return style; - }, - - electricChars: "{}" - }; -}); - -CodeMirror.defineMIME("text/x-pascal", "pascal"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/pegjs/index.html b/shared/html/libs/codemirror/5.0.0/mode/pegjs/index.html deleted file mode 100644 index 0c74604..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/pegjs/index.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - CodeMirror: PEG.js Mode - - - - - - - - - - - - -
-

PEG.js Mode

-
- -

The PEG.js Mode

-

Created by Forbes Lindesay.

-
- - diff --git a/shared/html/libs/codemirror/5.0.0/mode/pegjs/pegjs.js b/shared/html/libs/codemirror/5.0.0/mode/pegjs/pegjs.js deleted file mode 100644 index 306e376..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/pegjs/pegjs.js +++ /dev/null @@ -1,114 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../javascript/javascript")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../javascript/javascript"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("pegjs", function (config) { - var jsMode = CodeMirror.getMode(config, "javascript"); - - function identifier(stream) { - return stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/); - } - - return { - startState: function () { - return { - inString: false, - stringType: null, - inComment: false, - inChracterClass: false, - braced: 0, - lhs: true, - localState: null - }; - }, - token: function (stream, state) { - if (stream) - - //check for state changes - if (!state.inString && !state.inComment && ((stream.peek() == '"') || (stream.peek() == "'"))) { - state.stringType = stream.peek(); - stream.next(); // Skip quote - state.inString = true; // Update state - } - if (!state.inString && !state.inComment && stream.match(/^\/\*/)) { - state.inComment = true; - } - - //return state - if (state.inString) { - while (state.inString && !stream.eol()) { - if (stream.peek() === state.stringType) { - stream.next(); // Skip quote - state.inString = false; // Clear flag - } else if (stream.peek() === '\\') { - stream.next(); - stream.next(); - } else { - stream.match(/^.[^\\\"\']*/); - } - } - return state.lhs ? "property string" : "string"; // Token style - } else if (state.inComment) { - while (state.inComment && !stream.eol()) { - if (stream.match(/\*\//)) { - state.inComment = false; // Clear flag - } else { - stream.match(/^.[^\*]*/); - } - } - return "comment"; - } else if (state.inChracterClass) { - while (state.inChracterClass && !stream.eol()) { - if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) { - state.inChracterClass = false; - } - } - } else if (stream.peek() === '[') { - stream.next(); - state.inChracterClass = true; - return 'bracket'; - } else if (stream.match(/^\/\//)) { - stream.skipToEnd(); - return "comment"; - } else if (state.braced || stream.peek() === '{') { - if (state.localState === null) { - state.localState = jsMode.startState(); - } - var token = jsMode.token(stream, state.localState); - var text = stream.current(); - if (!token) { - for (var i = 0; i < text.length; i++) { - if (text[i] === '{') { - state.braced++; - } else if (text[i] === '}') { - state.braced--; - } - }; - } - return token; - } else if (identifier(stream)) { - if (stream.peek() === ':') { - return 'variable'; - } - return 'variable-2'; - } else if (['[', ']', '(', ')'].indexOf(stream.peek()) != -1) { - stream.next(); - return 'bracket'; - } else if (!stream.eatSpace()) { - stream.next(); - } - return null; - } - }; -}, "javascript"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/perl/index.html b/shared/html/libs/codemirror/5.0.0/mode/perl/index.html deleted file mode 100644 index 8c1021c..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/perl/index.html +++ /dev/null @@ -1,75 +0,0 @@ - - -CodeMirror: Perl mode - - - - - - - - - -
-

Perl mode

- - -
- - - -

MIME types defined: text/x-perl.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/perl/perl.js b/shared/html/libs/codemirror/5.0.0/mode/perl/perl.js deleted file mode 100644 index bef62bc..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/perl/perl.js +++ /dev/null @@ -1,837 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08) -// This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com) - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("perl",function(){ - // http://perldoc.perl.org - var PERL={ // null - magic touch - // 1 - keyword - // 2 - def - // 3 - atom - // 4 - operator - // 5 - variable-2 (predefined) - // [x,y] - x=1,2,3; y=must be defined if x{...} - // PERL operators - '->' : 4, - '++' : 4, - '--' : 4, - '**' : 4, - // ! ~ \ and unary + and - - '=~' : 4, - '!~' : 4, - '*' : 4, - '/' : 4, - '%' : 4, - 'x' : 4, - '+' : 4, - '-' : 4, - '.' : 4, - '<<' : 4, - '>>' : 4, - // named unary operators - '<' : 4, - '>' : 4, - '<=' : 4, - '>=' : 4, - 'lt' : 4, - 'gt' : 4, - 'le' : 4, - 'ge' : 4, - '==' : 4, - '!=' : 4, - '<=>' : 4, - 'eq' : 4, - 'ne' : 4, - 'cmp' : 4, - '~~' : 4, - '&' : 4, - '|' : 4, - '^' : 4, - '&&' : 4, - '||' : 4, - '//' : 4, - '..' : 4, - '...' : 4, - '?' : 4, - ':' : 4, - '=' : 4, - '+=' : 4, - '-=' : 4, - '*=' : 4, // etc. ??? - ',' : 4, - '=>' : 4, - '::' : 4, - // list operators (rightward) - 'not' : 4, - 'and' : 4, - 'or' : 4, - 'xor' : 4, - // PERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;) - 'BEGIN' : [5,1], - 'END' : [5,1], - 'PRINT' : [5,1], - 'PRINTF' : [5,1], - 'GETC' : [5,1], - 'READ' : [5,1], - 'READLINE' : [5,1], - 'DESTROY' : [5,1], - 'TIE' : [5,1], - 'TIEHANDLE' : [5,1], - 'UNTIE' : [5,1], - 'STDIN' : 5, - 'STDIN_TOP' : 5, - 'STDOUT' : 5, - 'STDOUT_TOP' : 5, - 'STDERR' : 5, - 'STDERR_TOP' : 5, - '$ARG' : 5, - '$_' : 5, - '@ARG' : 5, - '@_' : 5, - '$LIST_SEPARATOR' : 5, - '$"' : 5, - '$PROCESS_ID' : 5, - '$PID' : 5, - '$$' : 5, - '$REAL_GROUP_ID' : 5, - '$GID' : 5, - '$(' : 5, - '$EFFECTIVE_GROUP_ID' : 5, - '$EGID' : 5, - '$)' : 5, - '$PROGRAM_NAME' : 5, - '$0' : 5, - '$SUBSCRIPT_SEPARATOR' : 5, - '$SUBSEP' : 5, - '$;' : 5, - '$REAL_USER_ID' : 5, - '$UID' : 5, - '$<' : 5, - '$EFFECTIVE_USER_ID' : 5, - '$EUID' : 5, - '$>' : 5, - '$a' : 5, - '$b' : 5, - '$COMPILING' : 5, - '$^C' : 5, - '$DEBUGGING' : 5, - '$^D' : 5, - '${^ENCODING}' : 5, - '$ENV' : 5, - '%ENV' : 5, - '$SYSTEM_FD_MAX' : 5, - '$^F' : 5, - '@F' : 5, - '${^GLOBAL_PHASE}' : 5, - '$^H' : 5, - '%^H' : 5, - '@INC' : 5, - '%INC' : 5, - '$INPLACE_EDIT' : 5, - '$^I' : 5, - '$^M' : 5, - '$OSNAME' : 5, - '$^O' : 5, - '${^OPEN}' : 5, - '$PERLDB' : 5, - '$^P' : 5, - '$SIG' : 5, - '%SIG' : 5, - '$BASETIME' : 5, - '$^T' : 5, - '${^TAINT}' : 5, - '${^UNICODE}' : 5, - '${^UTF8CACHE}' : 5, - '${^UTF8LOCALE}' : 5, - '$PERL_VERSION' : 5, - '$^V' : 5, - '${^WIN32_SLOPPY_STAT}' : 5, - '$EXECUTABLE_NAME' : 5, - '$^X' : 5, - '$1' : 5, // - regexp $1, $2... - '$MATCH' : 5, - '$&' : 5, - '${^MATCH}' : 5, - '$PREMATCH' : 5, - '$`' : 5, - '${^PREMATCH}' : 5, - '$POSTMATCH' : 5, - "$'" : 5, - '${^POSTMATCH}' : 5, - '$LAST_PAREN_MATCH' : 5, - '$+' : 5, - '$LAST_SUBMATCH_RESULT' : 5, - '$^N' : 5, - '@LAST_MATCH_END' : 5, - '@+' : 5, - '%LAST_PAREN_MATCH' : 5, - '%+' : 5, - '@LAST_MATCH_START' : 5, - '@-' : 5, - '%LAST_MATCH_START' : 5, - '%-' : 5, - '$LAST_REGEXP_CODE_RESULT' : 5, - '$^R' : 5, - '${^RE_DEBUG_FLAGS}' : 5, - '${^RE_TRIE_MAXBUF}' : 5, - '$ARGV' : 5, - '@ARGV' : 5, - 'ARGV' : 5, - 'ARGVOUT' : 5, - '$OUTPUT_FIELD_SEPARATOR' : 5, - '$OFS' : 5, - '$,' : 5, - '$INPUT_LINE_NUMBER' : 5, - '$NR' : 5, - '$.' : 5, - '$INPUT_RECORD_SEPARATOR' : 5, - '$RS' : 5, - '$/' : 5, - '$OUTPUT_RECORD_SEPARATOR' : 5, - '$ORS' : 5, - '$\\' : 5, - '$OUTPUT_AUTOFLUSH' : 5, - '$|' : 5, - '$ACCUMULATOR' : 5, - '$^A' : 5, - '$FORMAT_FORMFEED' : 5, - '$^L' : 5, - '$FORMAT_PAGE_NUMBER' : 5, - '$%' : 5, - '$FORMAT_LINES_LEFT' : 5, - '$-' : 5, - '$FORMAT_LINE_BREAK_CHARACTERS' : 5, - '$:' : 5, - '$FORMAT_LINES_PER_PAGE' : 5, - '$=' : 5, - '$FORMAT_TOP_NAME' : 5, - '$^' : 5, - '$FORMAT_NAME' : 5, - '$~' : 5, - '${^CHILD_ERROR_NATIVE}' : 5, - '$EXTENDED_OS_ERROR' : 5, - '$^E' : 5, - '$EXCEPTIONS_BEING_CAUGHT' : 5, - '$^S' : 5, - '$WARNING' : 5, - '$^W' : 5, - '${^WARNING_BITS}' : 5, - '$OS_ERROR' : 5, - '$ERRNO' : 5, - '$!' : 5, - '%OS_ERROR' : 5, - '%ERRNO' : 5, - '%!' : 5, - '$CHILD_ERROR' : 5, - '$?' : 5, - '$EVAL_ERROR' : 5, - '$@' : 5, - '$OFMT' : 5, - '$#' : 5, - '$*' : 5, - '$ARRAY_BASE' : 5, - '$[' : 5, - '$OLD_PERL_VERSION' : 5, - '$]' : 5, - // PERL blocks - 'if' :[1,1], - elsif :[1,1], - 'else' :[1,1], - 'while' :[1,1], - unless :[1,1], - 'for' :[1,1], - foreach :[1,1], - // PERL functions - 'abs' :1, // - absolute value function - accept :1, // - accept an incoming socket connect - alarm :1, // - schedule a SIGALRM - 'atan2' :1, // - arctangent of Y/X in the range -PI to PI - bind :1, // - binds an address to a socket - binmode :1, // - prepare binary files for I/O - bless :1, // - create an object - bootstrap :1, // - 'break' :1, // - break out of a "given" block - caller :1, // - get context of the current subroutine call - chdir :1, // - change your current working directory - chmod :1, // - changes the permissions on a list of files - chomp :1, // - remove a trailing record separator from a string - chop :1, // - remove the last character from a string - chown :1, // - change the owership on a list of files - chr :1, // - get character this number represents - chroot :1, // - make directory new root for path lookups - close :1, // - close file (or pipe or socket) handle - closedir :1, // - close directory handle - connect :1, // - connect to a remote socket - 'continue' :[1,1], // - optional trailing block in a while or foreach - 'cos' :1, // - cosine function - crypt :1, // - one-way passwd-style encryption - dbmclose :1, // - breaks binding on a tied dbm file - dbmopen :1, // - create binding on a tied dbm file - 'default' :1, // - defined :1, // - test whether a value, variable, or function is defined - 'delete' :1, // - deletes a value from a hash - die :1, // - raise an exception or bail out - 'do' :1, // - turn a BLOCK into a TERM - dump :1, // - create an immediate core dump - each :1, // - retrieve the next key/value pair from a hash - endgrent :1, // - be done using group file - endhostent :1, // - be done using hosts file - endnetent :1, // - be done using networks file - endprotoent :1, // - be done using protocols file - endpwent :1, // - be done using passwd file - endservent :1, // - be done using services file - eof :1, // - test a filehandle for its end - 'eval' :1, // - catch exceptions or compile and run code - 'exec' :1, // - abandon this program to run another - exists :1, // - test whether a hash key is present - exit :1, // - terminate this program - 'exp' :1, // - raise I to a power - fcntl :1, // - file control system call - fileno :1, // - return file descriptor from filehandle - flock :1, // - lock an entire file with an advisory lock - fork :1, // - create a new process just like this one - format :1, // - declare a picture format with use by the write() function - formline :1, // - internal function used for formats - getc :1, // - get the next character from the filehandle - getgrent :1, // - get next group record - getgrgid :1, // - get group record given group user ID - getgrnam :1, // - get group record given group name - gethostbyaddr :1, // - get host record given its address - gethostbyname :1, // - get host record given name - gethostent :1, // - get next hosts record - getlogin :1, // - return who logged in at this tty - getnetbyaddr :1, // - get network record given its address - getnetbyname :1, // - get networks record given name - getnetent :1, // - get next networks record - getpeername :1, // - find the other end of a socket connection - getpgrp :1, // - get process group - getppid :1, // - get parent process ID - getpriority :1, // - get current nice value - getprotobyname :1, // - get protocol record given name - getprotobynumber :1, // - get protocol record numeric protocol - getprotoent :1, // - get next protocols record - getpwent :1, // - get next passwd record - getpwnam :1, // - get passwd record given user login name - getpwuid :1, // - get passwd record given user ID - getservbyname :1, // - get services record given its name - getservbyport :1, // - get services record given numeric port - getservent :1, // - get next services record - getsockname :1, // - retrieve the sockaddr for a given socket - getsockopt :1, // - get socket options on a given socket - given :1, // - glob :1, // - expand filenames using wildcards - gmtime :1, // - convert UNIX time into record or string using Greenwich time - 'goto' :1, // - create spaghetti code - grep :1, // - locate elements in a list test true against a given criterion - hex :1, // - convert a string to a hexadecimal number - 'import' :1, // - patch a module's namespace into your own - index :1, // - find a substring within a string - 'int' :1, // - get the integer portion of a number - ioctl :1, // - system-dependent device control system call - 'join' :1, // - join a list into a string using a separator - keys :1, // - retrieve list of indices from a hash - kill :1, // - send a signal to a process or process group - last :1, // - exit a block prematurely - lc :1, // - return lower-case version of a string - lcfirst :1, // - return a string with just the next letter in lower case - length :1, // - return the number of bytes in a string - 'link' :1, // - create a hard link in the filesytem - listen :1, // - register your socket as a server - local : 2, // - create a temporary value for a global variable (dynamic scoping) - localtime :1, // - convert UNIX time into record or string using local time - lock :1, // - get a thread lock on a variable, subroutine, or method - 'log' :1, // - retrieve the natural logarithm for a number - lstat :1, // - stat a symbolic link - m :null, // - match a string with a regular expression pattern - map :1, // - apply a change to a list to get back a new list with the changes - mkdir :1, // - create a directory - msgctl :1, // - SysV IPC message control operations - msgget :1, // - get SysV IPC message queue - msgrcv :1, // - receive a SysV IPC message from a message queue - msgsnd :1, // - send a SysV IPC message to a message queue - my : 2, // - declare and assign a local variable (lexical scoping) - 'new' :1, // - next :1, // - iterate a block prematurely - no :1, // - unimport some module symbols or semantics at compile time - oct :1, // - convert a string to an octal number - open :1, // - open a file, pipe, or descriptor - opendir :1, // - open a directory - ord :1, // - find a character's numeric representation - our : 2, // - declare and assign a package variable (lexical scoping) - pack :1, // - convert a list into a binary representation - 'package' :1, // - declare a separate global namespace - pipe :1, // - open a pair of connected filehandles - pop :1, // - remove the last element from an array and return it - pos :1, // - find or set the offset for the last/next m//g search - print :1, // - output a list to a filehandle - printf :1, // - output a formatted list to a filehandle - prototype :1, // - get the prototype (if any) of a subroutine - push :1, // - append one or more elements to an array - q :null, // - singly quote a string - qq :null, // - doubly quote a string - qr :null, // - Compile pattern - quotemeta :null, // - quote regular expression magic characters - qw :null, // - quote a list of words - qx :null, // - backquote quote a string - rand :1, // - retrieve the next pseudorandom number - read :1, // - fixed-length buffered input from a filehandle - readdir :1, // - get a directory from a directory handle - readline :1, // - fetch a record from a file - readlink :1, // - determine where a symbolic link is pointing - readpipe :1, // - execute a system command and collect standard output - recv :1, // - receive a message over a Socket - redo :1, // - start this loop iteration over again - ref :1, // - find out the type of thing being referenced - rename :1, // - change a filename - require :1, // - load in external functions from a library at runtime - reset :1, // - clear all variables of a given name - 'return' :1, // - get out of a function early - reverse :1, // - flip a string or a list - rewinddir :1, // - reset directory handle - rindex :1, // - right-to-left substring search - rmdir :1, // - remove a directory - s :null, // - replace a pattern with a string - say :1, // - print with newline - scalar :1, // - force a scalar context - seek :1, // - reposition file pointer for random-access I/O - seekdir :1, // - reposition directory pointer - select :1, // - reset default output or do I/O multiplexing - semctl :1, // - SysV semaphore control operations - semget :1, // - get set of SysV semaphores - semop :1, // - SysV semaphore operations - send :1, // - send a message over a socket - setgrent :1, // - prepare group file for use - sethostent :1, // - prepare hosts file for use - setnetent :1, // - prepare networks file for use - setpgrp :1, // - set the process group of a process - setpriority :1, // - set a process's nice value - setprotoent :1, // - prepare protocols file for use - setpwent :1, // - prepare passwd file for use - setservent :1, // - prepare services file for use - setsockopt :1, // - set some socket options - shift :1, // - remove the first element of an array, and return it - shmctl :1, // - SysV shared memory operations - shmget :1, // - get SysV shared memory segment identifier - shmread :1, // - read SysV shared memory - shmwrite :1, // - write SysV shared memory - shutdown :1, // - close down just half of a socket connection - 'sin' :1, // - return the sine of a number - sleep :1, // - block for some number of seconds - socket :1, // - create a socket - socketpair :1, // - create a pair of sockets - 'sort' :1, // - sort a list of values - splice :1, // - add or remove elements anywhere in an array - 'split' :1, // - split up a string using a regexp delimiter - sprintf :1, // - formatted print into a string - 'sqrt' :1, // - square root function - srand :1, // - seed the random number generator - stat :1, // - get a file's status information - state :1, // - declare and assign a state variable (persistent lexical scoping) - study :1, // - optimize input data for repeated searches - 'sub' :1, // - declare a subroutine, possibly anonymously - 'substr' :1, // - get or alter a portion of a stirng - symlink :1, // - create a symbolic link to a file - syscall :1, // - execute an arbitrary system call - sysopen :1, // - open a file, pipe, or descriptor - sysread :1, // - fixed-length unbuffered input from a filehandle - sysseek :1, // - position I/O pointer on handle used with sysread and syswrite - system :1, // - run a separate program - syswrite :1, // - fixed-length unbuffered output to a filehandle - tell :1, // - get current seekpointer on a filehandle - telldir :1, // - get current seekpointer on a directory handle - tie :1, // - bind a variable to an object class - tied :1, // - get a reference to the object underlying a tied variable - time :1, // - return number of seconds since 1970 - times :1, // - return elapsed time for self and child processes - tr :null, // - transliterate a string - truncate :1, // - shorten a file - uc :1, // - return upper-case version of a string - ucfirst :1, // - return a string with just the next letter in upper case - umask :1, // - set file creation mode mask - undef :1, // - remove a variable or function definition - unlink :1, // - remove one link to a file - unpack :1, // - convert binary structure into normal perl variables - unshift :1, // - prepend more elements to the beginning of a list - untie :1, // - break a tie binding to a variable - use :1, // - load in a module at compile time - utime :1, // - set a file's last access and modify times - values :1, // - return a list of the values in a hash - vec :1, // - test or set particular bits in a string - wait :1, // - wait for any child process to die - waitpid :1, // - wait for a particular child process to die - wantarray :1, // - get void vs scalar vs list context of current subroutine call - warn :1, // - print debugging info - when :1, // - write :1, // - print a picture record - y :null}; // - transliterate a string - - var RXstyle="string-2"; - var RXmodifiers=/[goseximacplud]/; // NOTE: "m", "s", "y" and "tr" need to correct real modifiers for each regexp type - - function tokenChain(stream,state,chain,style,tail){ // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;) - state.chain=null; // 12 3tail - state.style=null; - state.tail=null; - state.tokenize=function(stream,state){ - var e=false,c,i=0; - while(c=stream.next()){ - if(c===chain[i]&&!e){ - if(chain[++i]!==undefined){ - state.chain=chain[i]; - state.style=style; - state.tail=tail;} - else if(tail) - stream.eatWhile(tail); - state.tokenize=tokenPerl; - return style;} - e=!e&&c=="\\";} - return style;}; - return state.tokenize(stream,state);} - - function tokenSOMETHING(stream,state,string){ - state.tokenize=function(stream,state){ - if(stream.string==string) - state.tokenize=tokenPerl; - stream.skipToEnd(); - return "string";}; - return state.tokenize(stream,state);} - - function tokenPerl(stream,state){ - if(stream.eatSpace()) - return null; - if(state.chain) - return tokenChain(stream,state,state.chain,state.style,state.tail); - if(stream.match(/^\-?[\d\.]/,false)) - if(stream.match(/^(\-?(\d*\.\d+(e[+-]?\d+)?|\d+\.\d*)|0x[\da-fA-F]+|0b[01]+|\d+(e[+-]?\d+)?)/)) - return 'number'; - if(stream.match(/^<<(?=\w)/)){ // NOTE: <"],RXstyle,RXmodifiers);} - if(/[\^'"!~\/]/.test(c)){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}} - else if(c=="q"){ - c=look(stream, 1); - if(c=="("){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[")"],"string");} - if(c=="["){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["]"],"string");} - if(c=="{"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["}"],"string");} - if(c=="<"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[">"],"string");} - if(/[\^'"!~\/]/.test(c)){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[stream.eat(c)],"string");}} - else if(c=="w"){ - c=look(stream, 1); - if(c=="("){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[")"],"bracket");} - if(c=="["){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["]"],"bracket");} - if(c=="{"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["}"],"bracket");} - if(c=="<"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[">"],"bracket");} - if(/[\^'"!~\/]/.test(c)){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[stream.eat(c)],"bracket");}} - else if(c=="r"){ - c=look(stream, 1); - if(c=="("){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);} - if(c=="["){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);} - if(c=="{"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);} - if(c=="<"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);} - if(/[\^'"!~\/]/.test(c)){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}} - else if(/[\^'"!~\/(\[{<]/.test(c)){ - if(c=="("){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[")"],"string");} - if(c=="["){ - eatSuffix(stream, 1); - return tokenChain(stream,state,["]"],"string");} - if(c=="{"){ - eatSuffix(stream, 1); - return tokenChain(stream,state,["}"],"string");} - if(c=="<"){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[">"],"string");} - if(/[\^'"!~\/]/.test(c)){ - return tokenChain(stream,state,[stream.eat(c)],"string");}}}} - if(ch=="m"){ - var c=look(stream, -2); - if(!(c&&/\w/.test(c))){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(/[\^'"!~\/]/.test(c)){ - return tokenChain(stream,state,[c],RXstyle,RXmodifiers);} - if(c=="("){ - return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);} - if(c=="["){ - return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);} - if(c=="{"){ - return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);} - if(c=="<"){ - return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}}}} - if(ch=="s"){ - var c=/[\/>\]})\w]/.test(look(stream, -2)); - if(!c){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(c=="[") - return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers); - if(c=="{") - return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers); - if(c=="<") - return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers); - if(c=="(") - return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers); - return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}} - if(ch=="y"){ - var c=/[\/>\]})\w]/.test(look(stream, -2)); - if(!c){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(c=="[") - return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers); - if(c=="{") - return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers); - if(c=="<") - return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers); - if(c=="(") - return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers); - return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}} - if(ch=="t"){ - var c=/[\/>\]})\w]/.test(look(stream, -2)); - if(!c){ - c=stream.eat("r");if(c){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(c=="[") - return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers); - if(c=="{") - return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers); - if(c=="<") - return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers); - if(c=="(") - return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers); - return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}} - if(ch=="`"){ - return tokenChain(stream,state,[ch],"variable-2");} - if(ch=="/"){ - if(!/~\s*$/.test(prefix(stream))) - return "operator"; - else - return tokenChain(stream,state,[ch],RXstyle,RXmodifiers);} - if(ch=="$"){ - var p=stream.pos; - if(stream.eatWhile(/\d/)||stream.eat("{")&&stream.eatWhile(/\d/)&&stream.eat("}")) - return "variable-2"; - else - stream.pos=p;} - if(/[$@%]/.test(ch)){ - var p=stream.pos; - if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(look(stream, -2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){ - var c=stream.current(); - if(PERL[c]) - return "variable-2";} - stream.pos=p;} - if(/[$@%&]/.test(ch)){ - if(stream.eatWhile(/[\w$\[\]]/)||stream.eat("{")&&stream.eatWhile(/[\w$\[\]]/)&&stream.eat("}")){ - var c=stream.current(); - if(PERL[c]) - return "variable-2"; - else - return "variable";}} - if(ch=="#"){ - if(look(stream, -2)!="$"){ - stream.skipToEnd(); - return "comment";}} - if(/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)){ - var p=stream.pos; - stream.eatWhile(/[:+\-\^*$&%@=<>!?|\/~\.]/); - if(PERL[stream.current()]) - return "operator"; - else - stream.pos=p;} - if(ch=="_"){ - if(stream.pos==1){ - if(suffix(stream, 6)=="_END__"){ - return tokenChain(stream,state,['\0'],"comment");} - else if(suffix(stream, 7)=="_DATA__"){ - return tokenChain(stream,state,['\0'],"variable-2");} - else if(suffix(stream, 7)=="_C__"){ - return tokenChain(stream,state,['\0'],"string");}}} - if(/\w/.test(ch)){ - var p=stream.pos; - if(look(stream, -2)=="{"&&(look(stream, 0)=="}"||stream.eatWhile(/\w/)&&look(stream, 0)=="}")) - return "string"; - else - stream.pos=p;} - if(/[A-Z]/.test(ch)){ - var l=look(stream, -2); - var p=stream.pos; - stream.eatWhile(/[A-Z_]/); - if(/[\da-z]/.test(look(stream, 0))){ - stream.pos=p;} - else{ - var c=PERL[stream.current()]; - if(!c) - return "meta"; - if(c[1]) - c=c[0]; - if(l!=":"){ - if(c==1) - return "keyword"; - else if(c==2) - return "def"; - else if(c==3) - return "atom"; - else if(c==4) - return "operator"; - else if(c==5) - return "variable-2"; - else - return "meta";} - else - return "meta";}} - if(/[a-zA-Z_]/.test(ch)){ - var l=look(stream, -2); - stream.eatWhile(/\w/); - var c=PERL[stream.current()]; - if(!c) - return "meta"; - if(c[1]) - c=c[0]; - if(l!=":"){ - if(c==1) - return "keyword"; - else if(c==2) - return "def"; - else if(c==3) - return "atom"; - else if(c==4) - return "operator"; - else if(c==5) - return "variable-2"; - else - return "meta";} - else - return "meta";} - return null;} - - return { - startState: function() { - return { - tokenize: tokenPerl, - chain: null, - style: null, - tail: null - }; - }, - token: function(stream, state) { - return (state.tokenize || tokenPerl)(stream, state); - }, - lineComment: '#' - }; -}); - -CodeMirror.registerHelper("wordChars", "perl", /[\w$]/); - -CodeMirror.defineMIME("text/x-perl", "perl"); - -// it's like "peek", but need for look-ahead or look-behind if index < 0 -function look(stream, c){ - return stream.string.charAt(stream.pos+(c||0)); -} - -// return a part of prefix of current stream from current position -function prefix(stream, c){ - if(c){ - var x=stream.pos-c; - return stream.string.substr((x>=0?x:0),c);} - else{ - return stream.string.substr(0,stream.pos-1); - } -} - -// return a part of suffix of current stream from current position -function suffix(stream, c){ - var y=stream.string.length; - var x=y-stream.pos+1; - return stream.string.substr(stream.pos,(c&&c=(y=stream.string.length-1)) - stream.pos=y; - else - stream.pos=x; -} - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/php/index.html b/shared/html/libs/codemirror/5.0.0/mode/php/index.html deleted file mode 100644 index adf6b1b..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/php/index.html +++ /dev/null @@ -1,64 +0,0 @@ - - -CodeMirror: PHP mode - - - - - - - - - - - - - - - -
-

PHP mode

-
- - - -

Simple HTML/PHP mode based on - the C-like mode. Depends on XML, - JavaScript, CSS, HTMLMixed, and C-like modes.

- -

MIME types defined: application/x-httpd-php (HTML with PHP code), text/x-php (plain, non-wrapped PHP code).

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/php/php.js b/shared/html/libs/codemirror/5.0.0/mode/php/php.js deleted file mode 100644 index e112d91..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/php/php.js +++ /dev/null @@ -1,226 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../clike/clike")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../clike/clike"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function keywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - // Helper for stringWithEscapes - function matchSequence(list, end) { - if (list.length == 0) return stringWithEscapes(end); - return function (stream, state) { - var patterns = list[0]; - for (var i = 0; i < patterns.length; i++) if (stream.match(patterns[i][0])) { - state.tokenize = matchSequence(list.slice(1), end); - return patterns[i][1]; - } - state.tokenize = stringWithEscapes(end); - return "string"; - }; - } - function stringWithEscapes(closing) { - return function(stream, state) { return stringWithEscapes_(stream, state, closing); }; - } - function stringWithEscapes_(stream, state, closing) { - // "Complex" syntax - if (stream.match("${", false) || stream.match("{$", false)) { - state.tokenize = null; - return "string"; - } - - // Simple syntax - if (stream.match(/^\$[a-zA-Z_][a-zA-Z0-9_]*/)) { - // After the variable name there may appear array or object operator. - if (stream.match("[", false)) { - // Match array operator - state.tokenize = matchSequence([ - [["[", null]], - [[/\d[\w\.]*/, "number"], - [/\$[a-zA-Z_][a-zA-Z0-9_]*/, "variable-2"], - [/[\w\$]+/, "variable"]], - [["]", null]] - ], closing); - } - if (stream.match(/\-\>\w/, false)) { - // Match object operator - state.tokenize = matchSequence([ - [["->", null]], - [[/[\w]+/, "variable"]] - ], closing); - } - return "variable-2"; - } - - var escaped = false; - // Normal string - while (!stream.eol() && - (escaped || (!stream.match("{$", false) && - !stream.match(/^(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/, false)))) { - if (!escaped && stream.match(closing)) { - state.tokenize = null; - state.tokStack.pop(); state.tokStack.pop(); - break; - } - escaped = stream.next() == "\\" && !escaped; - } - return "string"; - } - - var phpKeywords = "abstract and array as break case catch class clone const continue declare default " + - "do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final " + - "for foreach function global goto if implements interface instanceof namespace " + - "new or private protected public static switch throw trait try use var while xor " + - "die echo empty exit eval include include_once isset list require require_once return " + - "print unset __halt_compiler self static parent yield insteadof finally"; - var phpAtoms = "true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__"; - var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count"; - CodeMirror.registerHelper("hintWords", "php", [phpKeywords, phpAtoms, phpBuiltin].join(" ").split(" ")); - CodeMirror.registerHelper("wordChars", "php", /[\w$]/); - - var phpConfig = { - name: "clike", - helperType: "php", - keywords: keywords(phpKeywords), - blockKeywords: keywords("catch do else elseif for foreach if switch try while finally"), - atoms: keywords(phpAtoms), - builtin: keywords(phpBuiltin), - multiLineStrings: true, - hooks: { - "$": function(stream) { - stream.eatWhile(/[\w\$_]/); - return "variable-2"; - }, - "<": function(stream, state) { - if (stream.match(/<", false)) stream.next(); - return "comment"; - }, - "/": function(stream) { - if (stream.eat("/")) { - while (!stream.eol() && !stream.match("?>", false)) stream.next(); - return "comment"; - } - return false; - }, - '"': function(_stream, state) { - (state.tokStack || (state.tokStack = [])).push('"', 0); - state.tokenize = stringWithEscapes('"'); - return "string"; - }, - "{": function(_stream, state) { - if (state.tokStack && state.tokStack.length) - state.tokStack[state.tokStack.length - 1]++; - return false; - }, - "}": function(_stream, state) { - if (state.tokStack && state.tokStack.length > 0 && - !--state.tokStack[state.tokStack.length - 1]) { - state.tokenize = stringWithEscapes(state.tokStack[state.tokStack.length - 2]); - } - return false; - } - } - }; - - CodeMirror.defineMode("php", function(config, parserConfig) { - var htmlMode = CodeMirror.getMode(config, "text/html"); - var phpMode = CodeMirror.getMode(config, phpConfig); - - function dispatch(stream, state) { - var isPHP = state.curMode == phpMode; - if (stream.sol() && state.pending && state.pending != '"' && state.pending != "'") state.pending = null; - if (!isPHP) { - if (stream.match(/^<\?\w*/)) { - state.curMode = phpMode; - state.curState = state.php; - return "meta"; - } - if (state.pending == '"' || state.pending == "'") { - while (!stream.eol() && stream.next() != state.pending) {} - var style = "string"; - } else if (state.pending && stream.pos < state.pending.end) { - stream.pos = state.pending.end; - var style = state.pending.style; - } else { - var style = htmlMode.token(stream, state.curState); - } - if (state.pending) state.pending = null; - var cur = stream.current(), openPHP = cur.search(/<\?/), m; - if (openPHP != -1) { - if (style == "string" && (m = cur.match(/[\'\"]$/)) && !/\?>/.test(cur)) state.pending = m[0]; - else state.pending = {end: stream.pos, style: style}; - stream.backUp(cur.length - openPHP); - } - return style; - } else if (isPHP && state.php.tokenize == null && stream.match("?>")) { - state.curMode = htmlMode; - state.curState = state.html; - return "meta"; - } else { - return phpMode.token(stream, state.curState); - } - } - - return { - startState: function() { - var html = CodeMirror.startState(htmlMode), php = CodeMirror.startState(phpMode); - return {html: html, - php: php, - curMode: parserConfig.startOpen ? phpMode : htmlMode, - curState: parserConfig.startOpen ? php : html, - pending: null}; - }, - - copyState: function(state) { - var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html), - php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur; - if (state.curMode == htmlMode) cur = htmlNew; - else cur = phpNew; - return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur, - pending: state.pending}; - }, - - token: dispatch, - - indent: function(state, textAfter) { - if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) || - (state.curMode == phpMode && /^\?>/.test(textAfter))) - return htmlMode.indent(state.html, textAfter); - return state.curMode.indent(state.curState, textAfter); - }, - - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//", - - innerMode: function(state) { return {state: state.curState, mode: state.curMode}; } - }; - }, "htmlmixed", "clike"); - - CodeMirror.defineMIME("application/x-httpd-php", "php"); - CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true}); - CodeMirror.defineMIME("text/x-php", phpConfig); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/php/test.js b/shared/html/libs/codemirror/5.0.0/mode/php/test.js deleted file mode 100644 index e2ecefc..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/php/test.js +++ /dev/null @@ -1,154 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "php"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT('simple_test', - '[meta ]'); - - MT('variable_interpolation_non_alphanumeric', - '[meta $/$\\$}$\\\"$:$;$?$|$[[$]]$+$=aaa"]', - '[meta ?>]'); - - MT('variable_interpolation_digits', - '[meta ]'); - - MT('variable_interpolation_simple_syntax_1', - '[meta ]'); - - MT('variable_interpolation_simple_syntax_2', - '[meta ]'); - - MT('variable_interpolation_simple_syntax_3', - '[meta [variable aaaaa][string .aaaaaa"];', - '[keyword echo] [string "aaa][variable-2 $aaaa][string ->][variable-2 $aaaaa][string .aaaaaa"];', - '[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string [[2]].aaaaaa"];', - '[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string ->aaaa2.aaaaaa"];', - '[meta ?>]'); - - MT('variable_interpolation_escaping', - '[meta aaa.aaa"];', - '[keyword echo] [string "aaa\\$aaaa[[2]]aaa.aaa"];', - '[keyword echo] [string "aaa\\$aaaa[[asd]]aaa.aaa"];', - '[keyword echo] [string "aaa{\\$aaaa->aaa.aaa"];', - '[keyword echo] [string "aaa{\\$aaaa[[2]]aaa.aaa"];', - '[keyword echo] [string "aaa{\\aaaaa[[asd]]aaa.aaa"];', - '[keyword echo] [string "aaa\\${aaaa->aaa.aaa"];', - '[keyword echo] [string "aaa\\${aaaa[[2]]aaa.aaa"];', - '[keyword echo] [string "aaa\\${aaaa[[asd]]aaa.aaa"];', - '[meta ?>]'); - - MT('variable_interpolation_complex_syntax_1', - '[meta aaa.aaa"];', - '[keyword echo] [string "aaa][variable-2 $]{[variable-2 $aaaa]}[string ->aaa.aaa"];', - '[keyword echo] [string "aaa][variable-2 $]{[variable-2 $aaaa][[',' [number 42]',']]}[string ->aaa.aaa"];', - '[keyword echo] [string "aaa][variable-2 $]{[variable aaaa][meta ?>]aaaaaa'); - - MT('variable_interpolation_complex_syntax_2', - '[meta } $aaaaaa.aaa"];', - '[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*}?>*/][[',' [string "aaa][variable-2 $aaa][string {}][variable-2 $]{[variable aaa]}[string "]',']]}[string ->aaa.aaa"];', - '[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*} } $aaa } */]}[string ->aaa.aaa"];'); - - - function build_recursive_monsters(nt, t, n){ - var monsters = [t]; - for (var i = 1; i <= n; ++i) - monsters[i] = nt.join(monsters[i - 1]); - return monsters; - } - - var m1 = build_recursive_monsters( - ['[string "][variable-2 $]{[variable aaa] [operator +] ', '}[string "]'], - '[comment /* }?>} */] [string "aaa][variable-2 $aaa][string .aaa"]', - 10 - ); - - MT('variable_interpolation_complex_syntax_3_1', - '[meta ]'); - - var m2 = build_recursive_monsters( - ['[string "a][variable-2 $]{[variable aaa] [operator +] ', ' [operator +] ', '}[string .a"]'], - '[comment /* }?>{{ */] [string "a?>}{{aa][variable-2 $aaa][string .a}a?>a"]', - 5 - ); - - MT('variable_interpolation_complex_syntax_3_2', - '[meta ]'); - - function build_recursive_monsters_2(mf1, mf2, nt, t, n){ - var monsters = [t]; - for (var i = 1; i <= n; ++i) - monsters[i] = nt[0] + mf1[i - 1] + nt[1] + mf2[i - 1] + nt[2] + monsters[i - 1] + nt[3]; - return monsters; - } - - var m3 = build_recursive_monsters_2( - m1, - m2, - ['[string "a][variable-2 $]{[variable aaa] [operator +] ', ' [operator +] ', ' [operator +] ', '}[string .a"]'], - '[comment /* }?>{{ */] [string "a?>}{{aa][variable-2 $aaa][string .a}a?>a"]', - 4 - ); - - MT('variable_interpolation_complex_syntax_3_3', - '[meta ]'); - - MT("variable_interpolation_heredoc", - "[meta - -CodeMirror: Pig Latin mode - - - - - - - - - -
-

Pig Latin mode

-
- - - -

- Simple mode that handles Pig Latin language. -

- -

MIME type defined: text/x-pig - (PIG code) - -

diff --git a/shared/html/libs/codemirror/5.0.0/mode/pig/pig.js b/shared/html/libs/codemirror/5.0.0/mode/pig/pig.js deleted file mode 100644 index c74b2cc..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/pig/pig.js +++ /dev/null @@ -1,188 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* - * Pig Latin Mode for CodeMirror 2 - * @author Prasanth Jayachandran - * @link https://github.com/prasanthj/pig-codemirror-2 - * This implementation is adapted from PL/SQL mode in CodeMirror 2. - */ -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("pig", function(_config, parserConfig) { - var keywords = parserConfig.keywords, - builtins = parserConfig.builtins, - types = parserConfig.types, - multiLineStrings = parserConfig.multiLineStrings; - - var isOperatorChar = /[*+\-%<>=&?:\/!|]/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - var type; - function ret(tp, style) { - type = tp; - return style; - } - - function tokenComment(stream, state) { - var isEnd = false; - var ch; - while(ch = stream.next()) { - if(ch == "/" && isEnd) { - state.tokenize = tokenBase; - break; - } - isEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while((next = stream.next()) != null) { - if (next == quote && !escaped) { - end = true; break; - } - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = tokenBase; - return ret("string", "error"); - }; - } - - function tokenBase(stream, state) { - var ch = stream.next(); - - // is a start of string? - if (ch == '"' || ch == "'") - return chain(stream, state, tokenString(ch)); - // is it one of the special chars - else if(/[\[\]{}\(\),;\.]/.test(ch)) - return ret(ch); - // is it a number? - else if(/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return ret("number", "number"); - } - // multi line comment or operator - else if (ch == "/") { - if (stream.eat("*")) { - return chain(stream, state, tokenComment); - } - else { - stream.eatWhile(isOperatorChar); - return ret("operator", "operator"); - } - } - // single line comment or operator - else if (ch=="-") { - if(stream.eat("-")){ - stream.skipToEnd(); - return ret("comment", "comment"); - } - else { - stream.eatWhile(isOperatorChar); - return ret("operator", "operator"); - } - } - // is it an operator - else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return ret("operator", "operator"); - } - else { - // get the while word - stream.eatWhile(/[\w\$_]/); - // is it one of the listed keywords? - if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) { - if (stream.eat(")") || stream.eat(".")) { - //keywords can be used as variables like flatten(group), group.$0 etc.. - } - else { - return ("keyword", "keyword"); - } - } - // is it one of the builtin functions? - if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) - { - return ("keyword", "variable-2"); - } - // is it one of the listed types? - if (types && types.propertyIsEnumerable(stream.current().toUpperCase())) - return ("keyword", "variable-3"); - // default is a 'variable' - return ret("variable", "pig-word"); - } - } - - // Interface - return { - startState: function() { - return { - tokenize: tokenBase, - startOfLine: true - }; - }, - - token: function(stream, state) { - if(stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - return style; - } - }; -}); - -(function() { - function keywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - // builtin funcs taken from trunk revision 1303237 - var pBuiltins = "ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL " - + "CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS " - + "DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG " - + "FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN " - + "INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER " - + "ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS " - + "LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA " - + "PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE " - + "SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG " - + "TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER "; - - // taken from QueryLexer.g - var pKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP " - + "JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL " - + "PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE " - + "SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE " - + "NEQ MATCHES TRUE FALSE DUMP"; - - // data types - var pTypes = "BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP "; - - CodeMirror.defineMIME("text/x-pig", { - name: "pig", - builtins: keywords(pBuiltins), - keywords: keywords(pKeywords), - types: keywords(pTypes) - }); - - CodeMirror.registerHelper("hintWords", "pig", (pBuiltins + pTypes + pKeywords).split(" ")); -}()); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/properties/index.html b/shared/html/libs/codemirror/5.0.0/mode/properties/index.html deleted file mode 100644 index f885302..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/properties/index.html +++ /dev/null @@ -1,53 +0,0 @@ - - -CodeMirror: Properties files mode - - - - - - - - - -
-

Properties files mode

-
- - -

MIME types defined: text/x-properties, - text/x-ini.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/properties/properties.js b/shared/html/libs/codemirror/5.0.0/mode/properties/properties.js deleted file mode 100644 index 0740084..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/properties/properties.js +++ /dev/null @@ -1,78 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("properties", function() { - return { - token: function(stream, state) { - var sol = stream.sol() || state.afterSection; - var eol = stream.eol(); - - state.afterSection = false; - - if (sol) { - if (state.nextMultiline) { - state.inMultiline = true; - state.nextMultiline = false; - } else { - state.position = "def"; - } - } - - if (eol && ! state.nextMultiline) { - state.inMultiline = false; - state.position = "def"; - } - - if (sol) { - while(stream.eatSpace()); - } - - var ch = stream.next(); - - if (sol && (ch === "#" || ch === "!" || ch === ";")) { - state.position = "comment"; - stream.skipToEnd(); - return "comment"; - } else if (sol && ch === "[") { - state.afterSection = true; - stream.skipTo("]"); stream.eat("]"); - return "header"; - } else if (ch === "=" || ch === ":") { - state.position = "quote"; - return null; - } else if (ch === "\\" && state.position === "quote") { - if (stream.next() !== "u") { // u = Unicode sequence \u1234 - // Multiline value - state.nextMultiline = true; - } - } - - return state.position; - }, - - startState: function() { - return { - position : "def", // Current position, "def", "quote" or "comment" - nextMultiline : false, // Is the next line multiline value - inMultiline : false, // Is the current line a multiline value - afterSection : false // Did we just open a section - }; - } - - }; -}); - -CodeMirror.defineMIME("text/x-properties", "properties"); -CodeMirror.defineMIME("text/x-ini", "properties"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/puppet/index.html b/shared/html/libs/codemirror/5.0.0/mode/puppet/index.html deleted file mode 100644 index 5614c36..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/puppet/index.html +++ /dev/null @@ -1,121 +0,0 @@ - - -CodeMirror: Puppet mode - - - - - - - - - - -
-

Puppet mode

-
- - -

MIME types defined: text/x-puppet.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/puppet/puppet.js b/shared/html/libs/codemirror/5.0.0/mode/puppet/puppet.js deleted file mode 100644 index e7f799f..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/puppet/puppet.js +++ /dev/null @@ -1,220 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("puppet", function () { - // Stores the words from the define method - var words = {}; - // Taken, mostly, from the Puppet official variable standards regex - var variable_regex = /({)?([a-z][a-z0-9_]*)?((::[a-z][a-z0-9_]*)*::)?[a-zA-Z0-9_]+(})?/; - - // Takes a string of words separated by spaces and adds them as - // keys with the value of the first argument 'style' - function define(style, string) { - var split = string.split(' '); - for (var i = 0; i < split.length; i++) { - words[split[i]] = style; - } - } - - // Takes commonly known puppet types/words and classifies them to a style - define('keyword', 'class define site node include import inherits'); - define('keyword', 'case if else in and elsif default or'); - define('atom', 'false true running present absent file directory undef'); - define('builtin', 'action augeas burst chain computer cron destination dport exec ' + - 'file filebucket group host icmp iniface interface jump k5login limit log_level ' + - 'log_prefix macauthorization mailalias maillist mcx mount nagios_command ' + - 'nagios_contact nagios_contactgroup nagios_host nagios_hostdependency ' + - 'nagios_hostescalation nagios_hostextinfo nagios_hostgroup nagios_service ' + - 'nagios_servicedependency nagios_serviceescalation nagios_serviceextinfo ' + - 'nagios_servicegroup nagios_timeperiod name notify outiface package proto reject ' + - 'resources router schedule scheduled_task selboolean selmodule service source ' + - 'sport ssh_authorized_key sshkey stage state table tidy todest toports tosource ' + - 'user vlan yumrepo zfs zone zpool'); - - // After finding a start of a string ('|") this function attempts to find the end; - // If a variable is encountered along the way, we display it differently when it - // is encapsulated in a double-quoted string. - function tokenString(stream, state) { - var current, prev, found_var = false; - while (!stream.eol() && (current = stream.next()) != state.pending) { - if (current === '$' && prev != '\\' && state.pending == '"') { - found_var = true; - break; - } - prev = current; - } - if (found_var) { - stream.backUp(1); - } - if (current == state.pending) { - state.continueString = false; - } else { - state.continueString = true; - } - return "string"; - } - - // Main function - function tokenize(stream, state) { - // Matches one whole word - var word = stream.match(/[\w]+/, false); - // Matches attributes (i.e. ensure => present ; 'ensure' would be matched) - var attribute = stream.match(/(\s+)?\w+\s+=>.*/, false); - // Matches non-builtin resource declarations - // (i.e. "apache::vhost {" or "mycustomclasss {" would be matched) - var resource = stream.match(/(\s+)?[\w:_]+(\s+)?{/, false); - // Matches virtual and exported resources (i.e. @@user { ; and the like) - var special_resource = stream.match(/(\s+)?[@]{1,2}[\w:_]+(\s+)?{/, false); - - // Finally advance the stream - var ch = stream.next(); - - // Have we found a variable? - if (ch === '$') { - if (stream.match(variable_regex)) { - // If so, and its in a string, assign it a different color - return state.continueString ? 'variable-2' : 'variable'; - } - // Otherwise return an invalid variable - return "error"; - } - // Should we still be looking for the end of a string? - if (state.continueString) { - // If so, go through the loop again - stream.backUp(1); - return tokenString(stream, state); - } - // Are we in a definition (class, node, define)? - if (state.inDefinition) { - // If so, return def (i.e. for 'class myclass {' ; 'myclass' would be matched) - if (stream.match(/(\s+)?[\w:_]+(\s+)?/)) { - return 'def'; - } - // Match the rest it the next time around - stream.match(/\s+{/); - state.inDefinition = false; - } - // Are we in an 'include' statement? - if (state.inInclude) { - // Match and return the included class - stream.match(/(\s+)?\S+(\s+)?/); - state.inInclude = false; - return 'def'; - } - // Do we just have a function on our hands? - // In 'ensure_resource("myclass")', 'ensure_resource' is matched - if (stream.match(/(\s+)?\w+\(/)) { - stream.backUp(1); - return 'def'; - } - // Have we matched the prior attribute regex? - if (attribute) { - stream.match(/(\s+)?\w+/); - return 'tag'; - } - // Do we have Puppet specific words? - if (word && words.hasOwnProperty(word)) { - // Negates the initial next() - stream.backUp(1); - // Acutally move the stream - stream.match(/[\w]+/); - // We want to process these words differently - // do to the importance they have in Puppet - if (stream.match(/\s+\S+\s+{/, false)) { - state.inDefinition = true; - } - if (word == 'include') { - state.inInclude = true; - } - // Returns their value as state in the prior define methods - return words[word]; - } - // Is there a match on a reference? - if (/(^|\s+)[A-Z][\w:_]+/.test(word)) { - // Negate the next() - stream.backUp(1); - // Match the full reference - stream.match(/(^|\s+)[A-Z][\w:_]+/); - return 'def'; - } - // Have we matched the prior resource regex? - if (resource) { - stream.match(/(\s+)?[\w:_]+/); - return 'def'; - } - // Have we matched the prior special_resource regex? - if (special_resource) { - stream.match(/(\s+)?[@]{1,2}/); - return 'special'; - } - // Match all the comments. All of them. - if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - // Have we found a string? - if (ch == "'" || ch == '"') { - // Store the type (single or double) - state.pending = ch; - // Perform the looping function to find the end - return tokenString(stream, state); - } - // Match all the brackets - if (ch == '{' || ch == '}') { - return 'bracket'; - } - // Match characters that we are going to assume - // are trying to be regex - if (ch == '/') { - stream.match(/.*?\//); - return 'variable-3'; - } - // Match all the numbers - if (ch.match(/[0-9]/)) { - stream.eatWhile(/[0-9]+/); - return 'number'; - } - // Match the '=' and '=>' operators - if (ch == '=') { - if (stream.peek() == '>') { - stream.next(); - } - return "operator"; - } - // Keep advancing through all the rest - stream.eatWhile(/[\w-]/); - // Return a blank line for everything else - return null; - } - // Start it all - return { - startState: function () { - var state = {}; - state.inDefinition = false; - state.inInclude = false; - state.continueString = false; - state.pending = false; - return state; - }, - token: function (stream, state) { - // Strip the spaces, but regex will account for them eitherway - if (stream.eatSpace()) return null; - // Go through the main process - return tokenize(stream, state); - } - }; -}); - -CodeMirror.defineMIME("text/x-puppet", "puppet"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/python/index.html b/shared/html/libs/codemirror/5.0.0/mode/python/index.html deleted file mode 100644 index 86eb3d5..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/python/index.html +++ /dev/null @@ -1,198 +0,0 @@ - - -CodeMirror: Python mode - - - - - - - - - - -
-

Python mode

- -
- - -

Cython mode

- -
- - -

Configuration Options for Python mode:

-
    -
  • version - 2/3 - The version of Python to recognize. Default is 2.
  • -
  • singleLineStringErrors - true/false - If you have a single-line string that is not terminated at the end of the line, this will show subsequent lines as errors if true, otherwise it will consider the newline as the end of the string. Default is false.
  • -
  • hangingIndent - int - If you want to write long arguments to a function starting on a new line, how much that line should be indented. Defaults to one normal indentation unit.
  • -
-

Advanced Configuration Options:

-

Usefull for superset of python syntax like Enthought enaml, IPython magics and questionmark help

-
    -
  • singleOperators - RegEx - Regular Expression for single operator matching, default :
    ^[\\+\\-\\*/%&|\\^~<>!]
    including
    @
    on Python 3
  • -
  • singleDelimiters - RegEx - Regular Expression for single delimiter matching, default :
    ^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]
  • -
  • doubleOperators - RegEx - Regular Expression for double operators matching, default :
    ^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))
  • -
  • doubleDelimiters - RegEx - Regular Expressoin for double delimiters matching, default :
    ^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))
  • -
  • tripleDelimiters - RegEx - Regular Expression for triple delimiters matching, default :
    ^((//=)|(>>=)|(<<=)|(\\*\\*=))
  • -
  • identifiers - RegEx - Regular Expression for identifier, default :
    ^[_A-Za-z][_A-Za-z0-9]*
    on Python 2 and
    ^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*
    on Python 3.
  • -
  • extra_keywords - list of string - List of extra words ton consider as keywords
  • -
  • extra_builtins - list of string - List of extra words ton consider as builtins
  • -
- - -

MIME types defined: text/x-python and text/x-cython.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/python/python.js b/shared/html/libs/codemirror/5.0.0/mode/python/python.js deleted file mode 100644 index 98c0409..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/python/python.js +++ /dev/null @@ -1,359 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); - } - - var wordOperators = wordRegexp(["and", "or", "not", "is"]); - var commonKeywords = ["as", "assert", "break", "class", "continue", - "def", "del", "elif", "else", "except", "finally", - "for", "from", "global", "if", "import", - "lambda", "pass", "raise", "return", - "try", "while", "with", "yield", "in"]; - var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr", - "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod", - "enumerate", "eval", "filter", "float", "format", "frozenset", - "getattr", "globals", "hasattr", "hash", "help", "hex", "id", - "input", "int", "isinstance", "issubclass", "iter", "len", - "list", "locals", "map", "max", "memoryview", "min", "next", - "object", "oct", "open", "ord", "pow", "property", "range", - "repr", "reversed", "round", "set", "setattr", "slice", - "sorted", "staticmethod", "str", "sum", "super", "tuple", - "type", "vars", "zip", "__import__", "NotImplemented", - "Ellipsis", "__debug__"]; - var py2 = {builtins: ["apply", "basestring", "buffer", "cmp", "coerce", "execfile", - "file", "intern", "long", "raw_input", "reduce", "reload", - "unichr", "unicode", "xrange", "False", "True", "None"], - keywords: ["exec", "print"]}; - var py3 = {builtins: ["ascii", "bytes", "exec", "print"], - keywords: ["nonlocal", "False", "True", "None"]}; - - CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins)); - - function top(state) { - return state.scopes[state.scopes.length - 1]; - } - - CodeMirror.defineMode("python", function(conf, parserConf) { - var ERRORCLASS = "error"; - - var singleDelimiters = parserConf.singleDelimiters || new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]"); - var doubleOperators = parserConf.doubleOperators || new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))"); - var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))"); - var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))"); - - if (parserConf.version && parseInt(parserConf.version, 10) == 3){ - // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator - var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!@]"); - var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*"); - } else { - var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!]"); - var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*"); - } - - var hangingIndent = parserConf.hangingIndent || conf.indentUnit; - - var myKeywords = commonKeywords, myBuiltins = commonBuiltins; - if(parserConf.extra_keywords != undefined){ - myKeywords = myKeywords.concat(parserConf.extra_keywords); - } - if(parserConf.extra_builtins != undefined){ - myBuiltins = myBuiltins.concat(parserConf.extra_builtins); - } - if (parserConf.version && parseInt(parserConf.version, 10) == 3) { - myKeywords = myKeywords.concat(py3.keywords); - myBuiltins = myBuiltins.concat(py3.builtins); - var stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i"); - } else { - myKeywords = myKeywords.concat(py2.keywords); - myBuiltins = myBuiltins.concat(py2.builtins); - var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i"); - } - var keywords = wordRegexp(myKeywords); - var builtins = wordRegexp(myBuiltins); - - // tokenizers - function tokenBase(stream, state) { - // Handle scope changes - if (stream.sol() && top(state).type == "py") { - var scopeOffset = top(state).offset; - if (stream.eatSpace()) { - var lineOffset = stream.indentation(); - if (lineOffset > scopeOffset) - pushScope(stream, state, "py"); - else if (lineOffset < scopeOffset && dedent(stream, state)) - state.errorToken = true; - return null; - } else { - var style = tokenBaseInner(stream, state); - if (scopeOffset > 0 && dedent(stream, state)) - style += " " + ERRORCLASS; - return style; - } - } - return tokenBaseInner(stream, state); - } - - function tokenBaseInner(stream, state) { - if (stream.eatSpace()) return null; - - var ch = stream.peek(); - - // Handle Comments - if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - - // Handle Number Literals - if (stream.match(/^[0-9\.]/, false)) { - var floatLiteral = false; - // Floats - if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) { floatLiteral = true; } - if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; } - if (stream.match(/^\.\d+/)) { floatLiteral = true; } - if (floatLiteral) { - // Float literals may be "imaginary" - stream.eat(/J/i); - return "number"; - } - // Integers - var intLiteral = false; - // Hex - if (stream.match(/^0x[0-9a-f]+/i)) intLiteral = true; - // Binary - if (stream.match(/^0b[01]+/i)) intLiteral = true; - // Octal - if (stream.match(/^0o[0-7]+/i)) intLiteral = true; - // Decimal - if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) { - // Decimal literals may be "imaginary" - stream.eat(/J/i); - // TODO - Can you have imaginary longs? - intLiteral = true; - } - // Zero by itself with no other piece of number. - if (stream.match(/^0(?![\dx])/i)) intLiteral = true; - if (intLiteral) { - // Integer literals may be "long" - stream.eat(/L/i); - return "number"; - } - } - - // Handle Strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenStringFactory(stream.current()); - return state.tokenize(stream, state); - } - - // Handle operators and Delimiters - if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) - return null; - - if (stream.match(doubleOperators) - || stream.match(singleOperators) - || stream.match(wordOperators)) - return "operator"; - - if (stream.match(singleDelimiters)) - return null; - - if (stream.match(keywords)) - return "keyword"; - - if (stream.match(builtins)) - return "builtin"; - - if (stream.match(/^(self|cls)\b/)) - return "variable-2"; - - if (stream.match(identifiers)) { - if (state.lastToken == "def" || state.lastToken == "class") - return "def"; - return "variable"; - } - - // Handle non-detected items - stream.next(); - return ERRORCLASS; - } - - function tokenStringFactory(delimiter) { - while ("rub".indexOf(delimiter.charAt(0).toLowerCase()) >= 0) - delimiter = delimiter.substr(1); - - var singleline = delimiter.length == 1; - var OUTCLASS = "string"; - - function tokenString(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^'"\\]/); - if (stream.eat("\\")) { - stream.next(); - if (singleline && stream.eol()) - return OUTCLASS; - } else if (stream.match(delimiter)) { - state.tokenize = tokenBase; - return OUTCLASS; - } else { - stream.eat(/['"]/); - } - } - if (singleline) { - if (parserConf.singleLineStringErrors) - return ERRORCLASS; - else - state.tokenize = tokenBase; - } - return OUTCLASS; - } - tokenString.isString = true; - return tokenString; - } - - function pushScope(stream, state, type) { - var offset = 0, align = null; - if (type == "py") { - while (top(state).type != "py") - state.scopes.pop(); - } - offset = top(state).offset + (type == "py" ? conf.indentUnit : hangingIndent); - if (type != "py" && !stream.match(/^(\s|#.*)*$/, false)) - align = stream.column() + 1; - state.scopes.push({offset: offset, type: type, align: align}); - } - - function dedent(stream, state) { - var indented = stream.indentation(); - while (top(state).offset > indented) { - if (top(state).type != "py") return true; - state.scopes.pop(); - } - return top(state).offset != indented; - } - - function tokenLexer(stream, state) { - var style = state.tokenize(stream, state); - var current = stream.current(); - - // Handle '.' connected identifiers - if (current == ".") { - style = stream.match(identifiers, false) ? null : ERRORCLASS; - if (style == null && state.lastStyle == "meta") { - // Apply 'meta' style to '.' connected identifiers when - // appropriate. - style = "meta"; - } - return style; - } - - // Handle decorators - if (current == "@"){ - if(parserConf.version && parseInt(parserConf.version, 10) == 3){ - return stream.match(identifiers, false) ? "meta" : "operator"; - } else { - return stream.match(identifiers, false) ? "meta" : ERRORCLASS; - } - } - - if ((style == "variable" || style == "builtin") - && state.lastStyle == "meta") - style = "meta"; - - // Handle scope changes. - if (current == "pass" || current == "return") - state.dedent += 1; - - if (current == "lambda") state.lambda = true; - if (current == ":" && !state.lambda && top(state).type == "py") - pushScope(stream, state, "py"); - - var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1; - if (delimiter_index != -1) - pushScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1)); - - delimiter_index = "])}".indexOf(current); - if (delimiter_index != -1) { - if (top(state).type == current) state.scopes.pop(); - else return ERRORCLASS; - } - if (state.dedent > 0 && stream.eol() && top(state).type == "py") { - if (state.scopes.length > 1) state.scopes.pop(); - state.dedent -= 1; - } - - return style; - } - - var external = { - startState: function(basecolumn) { - return { - tokenize: tokenBase, - scopes: [{offset: basecolumn || 0, type: "py", align: null}], - lastStyle: null, - lastToken: null, - lambda: false, - dedent: 0 - }; - }, - - token: function(stream, state) { - var addErr = state.errorToken; - if (addErr) state.errorToken = false; - var style = tokenLexer(stream, state); - - state.lastStyle = style; - - var current = stream.current(); - if (current && style) - state.lastToken = current; - - if (stream.eol() && state.lambda) - state.lambda = false; - return addErr ? style + " " + ERRORCLASS : style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase) - return state.tokenize.isString ? CodeMirror.Pass : 0; - - var scope = top(state); - var closing = textAfter && textAfter.charAt(0) == scope.type; - if (scope.align != null) - return scope.align - (closing ? 1 : 0); - else if (closing && state.scopes.length > 1) - return state.scopes[state.scopes.length - 2].offset; - else - return scope.offset; - }, - - lineComment: "#", - fold: "indent" - }; - return external; - }); - - CodeMirror.defineMIME("text/x-python", "python"); - - var words = function(str) { return str.split(" "); }; - - CodeMirror.defineMIME("text/x-cython", { - name: "python", - extra_keywords: words("by cdef cimport cpdef ctypedef enum except"+ - "extern gil include nogil property public"+ - "readonly struct union DEF IF ELIF ELSE") - }); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/q/index.html b/shared/html/libs/codemirror/5.0.0/mode/q/index.html deleted file mode 100644 index 72785ba..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/q/index.html +++ /dev/null @@ -1,144 +0,0 @@ - - -CodeMirror: Q mode - - - - - - - - - - -
-

Q mode

- - -
- - - -

MIME type defined: text/x-q.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/q/q.js b/shared/html/libs/codemirror/5.0.0/mode/q/q.js deleted file mode 100644 index a4af938..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/q/q.js +++ /dev/null @@ -1,139 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("q",function(config){ - var indentUnit=config.indentUnit, - curPunc, - keywords=buildRE(["abs","acos","aj","aj0","all","and","any","asc","asin","asof","atan","attr","avg","avgs","bin","by","ceiling","cols","cor","cos","count","cov","cross","csv","cut","delete","deltas","desc","dev","differ","distinct","div","do","each","ej","enlist","eval","except","exec","exit","exp","fby","fills","first","fkeys","flip","floor","from","get","getenv","group","gtime","hclose","hcount","hdel","hopen","hsym","iasc","idesc","if","ij","in","insert","inter","inv","key","keys","last","like","list","lj","load","log","lower","lsq","ltime","ltrim","mavg","max","maxs","mcount","md5","mdev","med","meta","min","mins","mmax","mmin","mmu","mod","msum","neg","next","not","null","or","over","parse","peach","pj","plist","prd","prds","prev","prior","rand","rank","ratios","raze","read0","read1","reciprocal","reverse","rload","rotate","rsave","rtrim","save","scan","select","set","setenv","show","signum","sin","sqrt","ss","ssr","string","sublist","sum","sums","sv","system","tables","tan","til","trim","txf","type","uj","ungroup","union","update","upper","upsert","value","var","view","views","vs","wavg","where","where","while","within","wj","wj1","wsum","xasc","xbar","xcol","xcols","xdesc","xexp","xgroup","xkey","xlog","xprev","xrank"]), - E=/[|/&^!+:\\\-*%$=~#;@><,?_\'\"\[\(\]\)\s{}]/; - function buildRE(w){return new RegExp("^("+w.join("|")+")$");} - function tokenBase(stream,state){ - var sol=stream.sol(),c=stream.next(); - curPunc=null; - if(sol) - if(c=="/") - return(state.tokenize=tokenLineComment)(stream,state); - else if(c=="\\"){ - if(stream.eol()||/\s/.test(stream.peek())) - return stream.skipToEnd(),/^\\\s*$/.test(stream.current())?(state.tokenize=tokenCommentToEOF)(stream, state):state.tokenize=tokenBase,"comment"; - else - return state.tokenize=tokenBase,"builtin"; - } - if(/\s/.test(c)) - return stream.peek()=="/"?(stream.skipToEnd(),"comment"):"whitespace"; - if(c=='"') - return(state.tokenize=tokenString)(stream,state); - if(c=='`') - return stream.eatWhile(/[A-Z|a-z|\d|_|:|\/|\.]/),"symbol"; - if(("."==c&&/\d/.test(stream.peek()))||/\d/.test(c)){ - var t=null; - stream.backUp(1); - if(stream.match(/^\d{4}\.\d{2}(m|\.\d{2}([D|T](\d{2}(:\d{2}(:\d{2}(\.\d{1,9})?)?)?)?)?)/) - || stream.match(/^\d+D(\d{2}(:\d{2}(:\d{2}(\.\d{1,9})?)?)?)/) - || stream.match(/^\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?/) - || stream.match(/^\d+[ptuv]{1}/)) - t="temporal"; - else if(stream.match(/^0[NwW]{1}/) - || stream.match(/^0x[\d|a-f|A-F]*/) - || stream.match(/^[0|1]+[b]{1}/) - || stream.match(/^\d+[chijn]{1}/) - || stream.match(/-?\d*(\.\d*)?(e[+\-]?\d+)?(e|f)?/)) - t="number"; - return(t&&(!(c=stream.peek())||E.test(c)))?t:(stream.next(),"error"); - } - if(/[A-Z|a-z]|\./.test(c)) - return stream.eatWhile(/[A-Z|a-z|\.|_|\d]/),keywords.test(stream.current())?"keyword":"variable"; - if(/[|/&^!+:\\\-*%$=~#;@><\.,?_\']/.test(c)) - return null; - if(/[{}\(\[\]\)]/.test(c)) - return null; - return"error"; - } - function tokenLineComment(stream,state){ - return stream.skipToEnd(),/\/\s*$/.test(stream.current())?(state.tokenize=tokenBlockComment)(stream,state):(state.tokenize=tokenBase),"comment"; - } - function tokenBlockComment(stream,state){ - var f=stream.sol()&&stream.peek()=="\\"; - stream.skipToEnd(); - if(f&&/^\\\s*$/.test(stream.current())) - state.tokenize=tokenBase; - return"comment"; - } - function tokenCommentToEOF(stream){return stream.skipToEnd(),"comment";} - function tokenString(stream,state){ - var escaped=false,next,end=false; - while((next=stream.next())){ - if(next=="\""&&!escaped){end=true;break;} - escaped=!escaped&&next=="\\"; - } - if(end)state.tokenize=tokenBase; - return"string"; - } - function pushContext(state,type,col){state.context={prev:state.context,indent:state.indent,col:col,type:type};} - function popContext(state){state.indent=state.context.indent;state.context=state.context.prev;} - return{ - startState:function(){ - return{tokenize:tokenBase, - context:null, - indent:0, - col:0}; - }, - token:function(stream,state){ - if(stream.sol()){ - if(state.context&&state.context.align==null) - state.context.align=false; - state.indent=stream.indentation(); - } - //if (stream.eatSpace()) return null; - var style=state.tokenize(stream,state); - if(style!="comment"&&state.context&&state.context.align==null&&state.context.type!="pattern"){ - state.context.align=true; - } - if(curPunc=="(")pushContext(state,")",stream.column()); - else if(curPunc=="[")pushContext(state,"]",stream.column()); - else if(curPunc=="{")pushContext(state,"}",stream.column()); - else if(/[\]\}\)]/.test(curPunc)){ - while(state.context&&state.context.type=="pattern")popContext(state); - if(state.context&&curPunc==state.context.type)popContext(state); - } - else if(curPunc=="."&&state.context&&state.context.type=="pattern")popContext(state); - else if(/atom|string|variable/.test(style)&&state.context){ - if(/[\}\]]/.test(state.context.type)) - pushContext(state,"pattern",stream.column()); - else if(state.context.type=="pattern"&&!state.context.align){ - state.context.align=true; - state.context.col=stream.column(); - } - } - return style; - }, - indent:function(state,textAfter){ - var firstChar=textAfter&&textAfter.charAt(0); - var context=state.context; - if(/[\]\}]/.test(firstChar)) - while (context&&context.type=="pattern")context=context.prev; - var closing=context&&firstChar==context.type; - if(!context) - return 0; - else if(context.type=="pattern") - return context.col; - else if(context.align) - return context.col+(closing?0:1); - else - return context.indent+(closing?0:indentUnit); - } - }; -}); -CodeMirror.defineMIME("text/x-q","q"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/r/index.html b/shared/html/libs/codemirror/5.0.0/mode/r/index.html deleted file mode 100644 index 6dd9634..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/r/index.html +++ /dev/null @@ -1,85 +0,0 @@ - - -CodeMirror: R mode - - - - - - - - - -
-

R mode

-
- - -

MIME types defined: text/x-rsrc.

- -

Development of the CodeMirror R mode was kindly sponsored - by Ubalo.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/r/r.js b/shared/html/libs/codemirror/5.0.0/mode/r/r.js deleted file mode 100644 index 1ab4a95..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/r/r.js +++ /dev/null @@ -1,162 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("r", function(config) { - function wordObj(str) { - var words = str.split(" "), res = {}; - for (var i = 0; i < words.length; ++i) res[words[i]] = true; - return res; - } - var atoms = wordObj("NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_"); - var builtins = wordObj("list quote bquote eval return call parse deparse"); - var keywords = wordObj("if else repeat while function for in next break"); - var blockkeywords = wordObj("if else repeat while function for"); - var opChars = /[+\-*\/^<>=!&|~$:]/; - var curPunc; - - function tokenBase(stream, state) { - curPunc = null; - var ch = stream.next(); - if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } else if (ch == "0" && stream.eat("x")) { - stream.eatWhile(/[\da-f]/i); - return "number"; - } else if (ch == "." && stream.eat(/\d/)) { - stream.match(/\d*(?:e[+\-]?\d+)?/); - return "number"; - } else if (/\d/.test(ch)) { - stream.match(/\d*(?:\.\d+)?(?:e[+\-]\d+)?L?/); - return "number"; - } else if (ch == "'" || ch == '"') { - state.tokenize = tokenString(ch); - return "string"; - } else if (ch == "." && stream.match(/.[.\d]+/)) { - return "keyword"; - } else if (/[\w\.]/.test(ch) && ch != "_") { - stream.eatWhile(/[\w\.]/); - var word = stream.current(); - if (atoms.propertyIsEnumerable(word)) return "atom"; - if (keywords.propertyIsEnumerable(word)) { - // Block keywords start new blocks, except 'else if', which only starts - // one new block for the 'if', no block for the 'else'. - if (blockkeywords.propertyIsEnumerable(word) && - !stream.match(/\s*if(\s+|$)/, false)) - curPunc = "block"; - return "keyword"; - } - if (builtins.propertyIsEnumerable(word)) return "builtin"; - return "variable"; - } else if (ch == "%") { - if (stream.skipTo("%")) stream.next(); - return "variable-2"; - } else if (ch == "<" && stream.eat("-")) { - return "arrow"; - } else if (ch == "=" && state.ctx.argList) { - return "arg-is"; - } else if (opChars.test(ch)) { - if (ch == "$") return "dollar"; - stream.eatWhile(opChars); - return "operator"; - } else if (/[\(\){}\[\];]/.test(ch)) { - curPunc = ch; - if (ch == ";") return "semi"; - return null; - } else { - return null; - } - } - - function tokenString(quote) { - return function(stream, state) { - if (stream.eat("\\")) { - var ch = stream.next(); - if (ch == "x") stream.match(/^[a-f0-9]{2}/i); - else if ((ch == "u" || ch == "U") && stream.eat("{") && stream.skipTo("}")) stream.next(); - else if (ch == "u") stream.match(/^[a-f0-9]{4}/i); - else if (ch == "U") stream.match(/^[a-f0-9]{8}/i); - else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/); - return "string-2"; - } else { - var next; - while ((next = stream.next()) != null) { - if (next == quote) { state.tokenize = tokenBase; break; } - if (next == "\\") { stream.backUp(1); break; } - } - return "string"; - } - }; - } - - function push(state, type, stream) { - state.ctx = {type: type, - indent: state.indent, - align: null, - column: stream.column(), - prev: state.ctx}; - } - function pop(state) { - state.indent = state.ctx.indent; - state.ctx = state.ctx.prev; - } - - return { - startState: function() { - return {tokenize: tokenBase, - ctx: {type: "top", - indent: -config.indentUnit, - align: false}, - indent: 0, - afterIdent: false}; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (state.ctx.align == null) state.ctx.align = false; - state.indent = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (style != "comment" && state.ctx.align == null) state.ctx.align = true; - - var ctype = state.ctx.type; - if ((curPunc == ";" || curPunc == "{" || curPunc == "}") && ctype == "block") pop(state); - if (curPunc == "{") push(state, "}", stream); - else if (curPunc == "(") { - push(state, ")", stream); - if (state.afterIdent) state.ctx.argList = true; - } - else if (curPunc == "[") push(state, "]", stream); - else if (curPunc == "block") push(state, "block", stream); - else if (curPunc == ctype) pop(state); - state.afterIdent = style == "variable" || style == "keyword"; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx, - closing = firstChar == ctx.type; - if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indent + (closing ? 0 : config.indentUnit); - }, - - lineComment: "#" - }; -}); - -CodeMirror.defineMIME("text/x-rsrc", "r"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/rpm/changes/index.html b/shared/html/libs/codemirror/5.0.0/mode/rpm/changes/index.html deleted file mode 100644 index 6e5031b..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/rpm/changes/index.html +++ /dev/null @@ -1,66 +0,0 @@ - - -CodeMirror: RPM changes mode - - - - - - - - - - - -
-

RPM changes mode

- -
- - -

MIME types defined: text/x-rpm-changes.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/rpm/index.html b/shared/html/libs/codemirror/5.0.0/mode/rpm/index.html deleted file mode 100644 index 9a34e6d..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/rpm/index.html +++ /dev/null @@ -1,149 +0,0 @@ - - -CodeMirror: RPM changes mode - - - - - - - - - - - -
-

RPM changes mode

- -
- - -

RPM spec mode

- -
- - -

MIME types defined: text/x-rpm-spec, text/x-rpm-changes.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/rpm/rpm.js b/shared/html/libs/codemirror/5.0.0/mode/rpm/rpm.js deleted file mode 100644 index 3bb7cd2..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/rpm/rpm.js +++ /dev/null @@ -1,101 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("rpm-changes", function() { - var headerSeperator = /^-+$/; - var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ?\d{1,2} \d{2}:\d{2}(:\d{2})? [A-Z]{3,4} \d{4} - /; - var simpleEmail = /^[\w+.-]+@[\w.-]+/; - - return { - token: function(stream) { - if (stream.sol()) { - if (stream.match(headerSeperator)) { return 'tag'; } - if (stream.match(headerLine)) { return 'tag'; } - } - if (stream.match(simpleEmail)) { return 'string'; } - stream.next(); - return null; - } - }; -}); - -CodeMirror.defineMIME("text/x-rpm-changes", "rpm-changes"); - -// Quick and dirty spec file highlighting - -CodeMirror.defineMode("rpm-spec", function() { - var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/; - - var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/; - var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/; - var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros - var control_flow_simple = /^%(else|endif)/; // rpm control flow macros - var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros - - return { - startState: function () { - return { - controlFlow: false, - macroParameters: false, - section: false - }; - }, - token: function (stream, state) { - var ch = stream.peek(); - if (ch == "#") { stream.skipToEnd(); return "comment"; } - - if (stream.sol()) { - if (stream.match(preamble)) { return "preamble"; } - if (stream.match(section)) { return "section"; } - } - - if (stream.match(/^\$\w+/)) { return "def"; } // Variables like '$RPM_BUILD_ROOT' - if (stream.match(/^\$\{\w+\}/)) { return "def"; } // Variables like '${RPM_BUILD_ROOT}' - - if (stream.match(control_flow_simple)) { return "keyword"; } - if (stream.match(control_flow_complex)) { - state.controlFlow = true; - return "keyword"; - } - if (state.controlFlow) { - if (stream.match(operators)) { return "operator"; } - if (stream.match(/^(\d+)/)) { return "number"; } - if (stream.eol()) { state.controlFlow = false; } - } - - if (stream.match(arch)) { return "number"; } - - // Macros like '%make_install' or '%attr(0775,root,root)' - if (stream.match(/^%[\w]+/)) { - if (stream.match(/^\(/)) { state.macroParameters = true; } - return "macro"; - } - if (state.macroParameters) { - if (stream.match(/^\d+/)) { return "number";} - if (stream.match(/^\)/)) { - state.macroParameters = false; - return "macro"; - } - } - if (stream.match(/^%\{\??[\w \-]+\}/)) { return "macro"; } // Macros like '%{defined fedora}' - - //TODO: Include bash script sub-parser (CodeMirror supports that) - stream.next(); - return null; - } - }; -}); - -CodeMirror.defineMIME("text/x-rpm-spec", "rpm-spec"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/rst/index.html b/shared/html/libs/codemirror/5.0.0/mode/rst/index.html deleted file mode 100644 index 2902dea..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/rst/index.html +++ /dev/null @@ -1,535 +0,0 @@ - - -CodeMirror: reStructuredText mode - - - - - - - - - - -
-

reStructuredText mode

-
- - -

- The python mode will be used for highlighting blocks - containing Python/IPython terminal sessions: blocks starting with - >>> (for Python) or In [num]: (for - IPython). - - Further, the stex mode will be used for highlighting - blocks containing LaTex code. -

- -

MIME types defined: text/x-rst.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/rst/rst.js b/shared/html/libs/codemirror/5.0.0/mode/rst/rst.js deleted file mode 100644 index bcf110c..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/rst/rst.js +++ /dev/null @@ -1,557 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../python/python"), require("../stex/stex"), require("../../addon/mode/overlay")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../python/python", "../stex/stex", "../../addon/mode/overlay"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('rst', function (config, options) { - - var rx_strong = /^\*\*[^\*\s](?:[^\*]*[^\*\s])?\*\*/; - var rx_emphasis = /^\*[^\*\s](?:[^\*]*[^\*\s])?\*/; - var rx_literal = /^``[^`\s](?:[^`]*[^`\s])``/; - - var rx_number = /^(?:[\d]+(?:[\.,]\d+)*)/; - var rx_positive = /^(?:\s\+[\d]+(?:[\.,]\d+)*)/; - var rx_negative = /^(?:\s\-[\d]+(?:[\.,]\d+)*)/; - - var rx_uri_protocol = "[Hh][Tt][Tt][Pp][Ss]?://"; - var rx_uri_domain = "(?:[\\d\\w.-]+)\\.(?:\\w{2,6})"; - var rx_uri_path = "(?:/[\\d\\w\\#\\%\\&\\-\\.\\,\\/\\:\\=\\?\\~]+)*"; - var rx_uri = new RegExp("^" + rx_uri_protocol + rx_uri_domain + rx_uri_path); - - var overlay = { - token: function (stream) { - - if (stream.match(rx_strong) && stream.match (/\W+|$/, false)) - return 'strong'; - if (stream.match(rx_emphasis) && stream.match (/\W+|$/, false)) - return 'em'; - if (stream.match(rx_literal) && stream.match (/\W+|$/, false)) - return 'string-2'; - if (stream.match(rx_number)) - return 'number'; - if (stream.match(rx_positive)) - return 'positive'; - if (stream.match(rx_negative)) - return 'negative'; - if (stream.match(rx_uri)) - return 'link'; - - while (stream.next() != null) { - if (stream.match(rx_strong, false)) break; - if (stream.match(rx_emphasis, false)) break; - if (stream.match(rx_literal, false)) break; - if (stream.match(rx_number, false)) break; - if (stream.match(rx_positive, false)) break; - if (stream.match(rx_negative, false)) break; - if (stream.match(rx_uri, false)) break; - } - - return null; - } - }; - - var mode = CodeMirror.getMode( - config, options.backdrop || 'rst-base' - ); - - return CodeMirror.overlayMode(mode, overlay, true); // combine -}, 'python', 'stex'); - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -CodeMirror.defineMode('rst-base', function (config) { - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function format(string) { - var args = Array.prototype.slice.call(arguments, 1); - return string.replace(/{(\d+)}/g, function (match, n) { - return typeof args[n] != 'undefined' ? args[n] : match; - }); - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - var mode_python = CodeMirror.getMode(config, 'python'); - var mode_stex = CodeMirror.getMode(config, 'stex'); - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - var SEPA = "\\s+"; - var TAIL = "(?:\\s*|\\W|$)", - rx_TAIL = new RegExp(format('^{0}', TAIL)); - - var NAME = - "(?:[^\\W\\d_](?:[\\w!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)", - rx_NAME = new RegExp(format('^{0}', NAME)); - var NAME_WWS = - "(?:[^\\W\\d_](?:[\\w\\s!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)"; - var REF_NAME = format('(?:{0}|`{1}`)', NAME, NAME_WWS); - - var TEXT1 = "(?:[^\\s\\|](?:[^\\|]*[^\\s\\|])?)"; - var TEXT2 = "(?:[^\\`]+)", - rx_TEXT2 = new RegExp(format('^{0}', TEXT2)); - - var rx_section = new RegExp( - "^([!'#$%&\"()*+,-./:;<=>?@\\[\\\\\\]^_`{|}~])\\1{3,}\\s*$"); - var rx_explicit = new RegExp( - format('^\\.\\.{0}', SEPA)); - var rx_link = new RegExp( - format('^_{0}:{1}|^__:{1}', REF_NAME, TAIL)); - var rx_directive = new RegExp( - format('^{0}::{1}', REF_NAME, TAIL)); - var rx_substitution = new RegExp( - format('^\\|{0}\\|{1}{2}::{3}', TEXT1, SEPA, REF_NAME, TAIL)); - var rx_footnote = new RegExp( - format('^\\[(?:\\d+|#{0}?|\\*)]{1}', REF_NAME, TAIL)); - var rx_citation = new RegExp( - format('^\\[{0}\\]{1}', REF_NAME, TAIL)); - - var rx_substitution_ref = new RegExp( - format('^\\|{0}\\|', TEXT1)); - var rx_footnote_ref = new RegExp( - format('^\\[(?:\\d+|#{0}?|\\*)]_', REF_NAME)); - var rx_citation_ref = new RegExp( - format('^\\[{0}\\]_', REF_NAME)); - var rx_link_ref1 = new RegExp( - format('^{0}__?', REF_NAME)); - var rx_link_ref2 = new RegExp( - format('^`{0}`_', TEXT2)); - - var rx_role_pre = new RegExp( - format('^:{0}:`{1}`{2}', NAME, TEXT2, TAIL)); - var rx_role_suf = new RegExp( - format('^`{1}`:{0}:{2}', NAME, TEXT2, TAIL)); - var rx_role = new RegExp( - format('^:{0}:{1}', NAME, TAIL)); - - var rx_directive_name = new RegExp(format('^{0}', REF_NAME)); - var rx_directive_tail = new RegExp(format('^::{0}', TAIL)); - var rx_substitution_text = new RegExp(format('^\\|{0}\\|', TEXT1)); - var rx_substitution_sepa = new RegExp(format('^{0}', SEPA)); - var rx_substitution_name = new RegExp(format('^{0}', REF_NAME)); - var rx_substitution_tail = new RegExp(format('^::{0}', TAIL)); - var rx_link_head = new RegExp("^_"); - var rx_link_name = new RegExp(format('^{0}|_', REF_NAME)); - var rx_link_tail = new RegExp(format('^:{0}', TAIL)); - - var rx_verbatim = new RegExp('^::\\s*$'); - var rx_examples = new RegExp('^\\s+(?:>>>|In \\[\\d+\\]:)\\s'); - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function to_normal(stream, state) { - var token = null; - - if (stream.sol() && stream.match(rx_examples, false)) { - change(state, to_mode, { - mode: mode_python, local: CodeMirror.startState(mode_python) - }); - } else if (stream.sol() && stream.match(rx_explicit)) { - change(state, to_explicit); - token = 'meta'; - } else if (stream.sol() && stream.match(rx_section)) { - change(state, to_normal); - token = 'header'; - } else if (phase(state) == rx_role_pre || - stream.match(rx_role_pre, false)) { - - switch (stage(state)) { - case 0: - change(state, to_normal, context(rx_role_pre, 1)); - stream.match(/^:/); - token = 'meta'; - break; - case 1: - change(state, to_normal, context(rx_role_pre, 2)); - stream.match(rx_NAME); - token = 'keyword'; - - if (stream.current().match(/^(?:math|latex)/)) { - state.tmp_stex = true; - } - break; - case 2: - change(state, to_normal, context(rx_role_pre, 3)); - stream.match(/^:`/); - token = 'meta'; - break; - case 3: - if (state.tmp_stex) { - state.tmp_stex = undefined; state.tmp = { - mode: mode_stex, local: CodeMirror.startState(mode_stex) - }; - } - - if (state.tmp) { - if (stream.peek() == '`') { - change(state, to_normal, context(rx_role_pre, 4)); - state.tmp = undefined; - break; - } - - token = state.tmp.mode.token(stream, state.tmp.local); - break; - } - - change(state, to_normal, context(rx_role_pre, 4)); - stream.match(rx_TEXT2); - token = 'string'; - break; - case 4: - change(state, to_normal, context(rx_role_pre, 5)); - stream.match(/^`/); - token = 'meta'; - break; - case 5: - change(state, to_normal, context(rx_role_pre, 6)); - stream.match(rx_TAIL); - break; - default: - change(state, to_normal); - } - } else if (phase(state) == rx_role_suf || - stream.match(rx_role_suf, false)) { - - switch (stage(state)) { - case 0: - change(state, to_normal, context(rx_role_suf, 1)); - stream.match(/^`/); - token = 'meta'; - break; - case 1: - change(state, to_normal, context(rx_role_suf, 2)); - stream.match(rx_TEXT2); - token = 'string'; - break; - case 2: - change(state, to_normal, context(rx_role_suf, 3)); - stream.match(/^`:/); - token = 'meta'; - break; - case 3: - change(state, to_normal, context(rx_role_suf, 4)); - stream.match(rx_NAME); - token = 'keyword'; - break; - case 4: - change(state, to_normal, context(rx_role_suf, 5)); - stream.match(/^:/); - token = 'meta'; - break; - case 5: - change(state, to_normal, context(rx_role_suf, 6)); - stream.match(rx_TAIL); - break; - default: - change(state, to_normal); - } - } else if (phase(state) == rx_role || stream.match(rx_role, false)) { - - switch (stage(state)) { - case 0: - change(state, to_normal, context(rx_role, 1)); - stream.match(/^:/); - token = 'meta'; - break; - case 1: - change(state, to_normal, context(rx_role, 2)); - stream.match(rx_NAME); - token = 'keyword'; - break; - case 2: - change(state, to_normal, context(rx_role, 3)); - stream.match(/^:/); - token = 'meta'; - break; - case 3: - change(state, to_normal, context(rx_role, 4)); - stream.match(rx_TAIL); - break; - default: - change(state, to_normal); - } - } else if (phase(state) == rx_substitution_ref || - stream.match(rx_substitution_ref, false)) { - - switch (stage(state)) { - case 0: - change(state, to_normal, context(rx_substitution_ref, 1)); - stream.match(rx_substitution_text); - token = 'variable-2'; - break; - case 1: - change(state, to_normal, context(rx_substitution_ref, 2)); - if (stream.match(/^_?_?/)) token = 'link'; - break; - default: - change(state, to_normal); - } - } else if (stream.match(rx_footnote_ref)) { - change(state, to_normal); - token = 'quote'; - } else if (stream.match(rx_citation_ref)) { - change(state, to_normal); - token = 'quote'; - } else if (stream.match(rx_link_ref1)) { - change(state, to_normal); - if (!stream.peek() || stream.peek().match(/^\W$/)) { - token = 'link'; - } - } else if (phase(state) == rx_link_ref2 || - stream.match(rx_link_ref2, false)) { - - switch (stage(state)) { - case 0: - if (!stream.peek() || stream.peek().match(/^\W$/)) { - change(state, to_normal, context(rx_link_ref2, 1)); - } else { - stream.match(rx_link_ref2); - } - break; - case 1: - change(state, to_normal, context(rx_link_ref2, 2)); - stream.match(/^`/); - token = 'link'; - break; - case 2: - change(state, to_normal, context(rx_link_ref2, 3)); - stream.match(rx_TEXT2); - break; - case 3: - change(state, to_normal, context(rx_link_ref2, 4)); - stream.match(/^`_/); - token = 'link'; - break; - default: - change(state, to_normal); - } - } else if (stream.match(rx_verbatim)) { - change(state, to_verbatim); - } - - else { - if (stream.next()) change(state, to_normal); - } - - return token; - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function to_explicit(stream, state) { - var token = null; - - if (phase(state) == rx_substitution || - stream.match(rx_substitution, false)) { - - switch (stage(state)) { - case 0: - change(state, to_explicit, context(rx_substitution, 1)); - stream.match(rx_substitution_text); - token = 'variable-2'; - break; - case 1: - change(state, to_explicit, context(rx_substitution, 2)); - stream.match(rx_substitution_sepa); - break; - case 2: - change(state, to_explicit, context(rx_substitution, 3)); - stream.match(rx_substitution_name); - token = 'keyword'; - break; - case 3: - change(state, to_explicit, context(rx_substitution, 4)); - stream.match(rx_substitution_tail); - token = 'meta'; - break; - default: - change(state, to_normal); - } - } else if (phase(state) == rx_directive || - stream.match(rx_directive, false)) { - - switch (stage(state)) { - case 0: - change(state, to_explicit, context(rx_directive, 1)); - stream.match(rx_directive_name); - token = 'keyword'; - - if (stream.current().match(/^(?:math|latex)/)) - state.tmp_stex = true; - else if (stream.current().match(/^python/)) - state.tmp_py = true; - break; - case 1: - change(state, to_explicit, context(rx_directive, 2)); - stream.match(rx_directive_tail); - token = 'meta'; - - if (stream.match(/^latex\s*$/) || state.tmp_stex) { - state.tmp_stex = undefined; change(state, to_mode, { - mode: mode_stex, local: CodeMirror.startState(mode_stex) - }); - } - break; - case 2: - change(state, to_explicit, context(rx_directive, 3)); - if (stream.match(/^python\s*$/) || state.tmp_py) { - state.tmp_py = undefined; change(state, to_mode, { - mode: mode_python, local: CodeMirror.startState(mode_python) - }); - } - break; - default: - change(state, to_normal); - } - } else if (phase(state) == rx_link || stream.match(rx_link, false)) { - - switch (stage(state)) { - case 0: - change(state, to_explicit, context(rx_link, 1)); - stream.match(rx_link_head); - stream.match(rx_link_name); - token = 'link'; - break; - case 1: - change(state, to_explicit, context(rx_link, 2)); - stream.match(rx_link_tail); - token = 'meta'; - break; - default: - change(state, to_normal); - } - } else if (stream.match(rx_footnote)) { - change(state, to_normal); - token = 'quote'; - } else if (stream.match(rx_citation)) { - change(state, to_normal); - token = 'quote'; - } - - else { - stream.eatSpace(); - if (stream.eol()) { - change(state, to_normal); - } else { - stream.skipToEnd(); - change(state, to_comment); - token = 'comment'; - } - } - - return token; - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function to_comment(stream, state) { - return as_block(stream, state, 'comment'); - } - - function to_verbatim(stream, state) { - return as_block(stream, state, 'meta'); - } - - function as_block(stream, state, token) { - if (stream.eol() || stream.eatSpace()) { - stream.skipToEnd(); - return token; - } else { - change(state, to_normal); - return null; - } - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function to_mode(stream, state) { - - if (state.ctx.mode && state.ctx.local) { - - if (stream.sol()) { - if (!stream.eatSpace()) change(state, to_normal); - return null; - } - - return state.ctx.mode.token(stream, state.ctx.local); - } - - change(state, to_normal); - return null; - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function context(phase, stage, mode, local) { - return {phase: phase, stage: stage, mode: mode, local: local}; - } - - function change(state, tok, ctx) { - state.tok = tok; - state.ctx = ctx || {}; - } - - function stage(state) { - return state.ctx.stage || 0; - } - - function phase(state) { - return state.ctx.phase; - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - return { - startState: function () { - return {tok: to_normal, ctx: context(undefined, 0)}; - }, - - copyState: function (state) { - var ctx = state.ctx, tmp = state.tmp; - if (ctx.local) - ctx = {mode: ctx.mode, local: CodeMirror.copyState(ctx.mode, ctx.local)}; - if (tmp) - tmp = {mode: tmp.mode, local: CodeMirror.copyState(tmp.mode, tmp.local)}; - return {tok: state.tok, ctx: ctx, tmp: tmp}; - }, - - innerMode: function (state) { - return state.tmp ? {state: state.tmp.local, mode: state.tmp.mode} - : state.ctx.mode ? {state: state.ctx.local, mode: state.ctx.mode} - : null; - }, - - token: function (stream, state) { - return state.tok(stream, state); - } - }; -}, 'python', 'stex'); - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -CodeMirror.defineMIME('text/x-rst', 'rst'); - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/ruby/index.html b/shared/html/libs/codemirror/5.0.0/mode/ruby/index.html deleted file mode 100644 index 97544ba..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/ruby/index.html +++ /dev/null @@ -1,183 +0,0 @@ - - -CodeMirror: Ruby mode - - - - - - - - - - -
-

Ruby mode

-
- - -

MIME types defined: text/x-ruby.

- -

Development of the CodeMirror Ruby mode was kindly sponsored - by Ubalo.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/ruby/ruby.js b/shared/html/libs/codemirror/5.0.0/mode/ruby/ruby.js deleted file mode 100644 index eab9d9d..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/ruby/ruby.js +++ /dev/null @@ -1,285 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("ruby", function(config) { - function wordObj(words) { - var o = {}; - for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true; - return o; - } - var keywords = wordObj([ - "alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else", - "elsif", "END", "end", "ensure", "false", "for", "if", "in", "module", "next", "not", "or", - "redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless", - "until", "when", "while", "yield", "nil", "raise", "throw", "catch", "fail", "loop", "callcc", - "caller", "lambda", "proc", "public", "protected", "private", "require", "load", - "require_relative", "extend", "autoload", "__END__", "__FILE__", "__LINE__", "__dir__" - ]); - var indentWords = wordObj(["def", "class", "case", "for", "while", "module", "then", - "catch", "loop", "proc", "begin"]); - var dedentWords = wordObj(["end", "until"]); - var matching = {"[": "]", "{": "}", "(": ")"}; - var curPunc; - - function chain(newtok, stream, state) { - state.tokenize.push(newtok); - return newtok(stream, state); - } - - function tokenBase(stream, state) { - curPunc = null; - if (stream.sol() && stream.match("=begin") && stream.eol()) { - state.tokenize.push(readBlockComment); - return "comment"; - } - if (stream.eatSpace()) return null; - var ch = stream.next(), m; - if (ch == "`" || ch == "'" || ch == '"') { - return chain(readQuoted(ch, "string", ch == '"' || ch == "`"), stream, state); - } else if (ch == "/") { - var currentIndex = stream.current().length; - if (stream.skipTo("/")) { - var search_till = stream.current().length; - stream.backUp(stream.current().length - currentIndex); - var balance = 0; // balance brackets - while (stream.current().length < search_till) { - var chchr = stream.next(); - if (chchr == "(") balance += 1; - else if (chchr == ")") balance -= 1; - if (balance < 0) break; - } - stream.backUp(stream.current().length - currentIndex); - if (balance == 0) - return chain(readQuoted(ch, "string-2", true), stream, state); - } - return "operator"; - } else if (ch == "%") { - var style = "string", embed = true; - if (stream.eat("s")) style = "atom"; - else if (stream.eat(/[WQ]/)) style = "string"; - else if (stream.eat(/[r]/)) style = "string-2"; - else if (stream.eat(/[wxq]/)) { style = "string"; embed = false; } - var delim = stream.eat(/[^\w\s=]/); - if (!delim) return "operator"; - if (matching.propertyIsEnumerable(delim)) delim = matching[delim]; - return chain(readQuoted(delim, style, embed, true), stream, state); - } else if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } else if (ch == "<" && (m = stream.match(/^<-?[\`\"\']?([a-zA-Z_?]\w*)[\`\"\']?(?:;|$)/))) { - return chain(readHereDoc(m[1]), stream, state); - } else if (ch == "0") { - if (stream.eat("x")) stream.eatWhile(/[\da-fA-F]/); - else if (stream.eat("b")) stream.eatWhile(/[01]/); - else stream.eatWhile(/[0-7]/); - return "number"; - } else if (/\d/.test(ch)) { - stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+\-]?[\d_]+)?/); - return "number"; - } else if (ch == "?") { - while (stream.match(/^\\[CM]-/)) {} - if (stream.eat("\\")) stream.eatWhile(/\w/); - else stream.next(); - return "string"; - } else if (ch == ":") { - if (stream.eat("'")) return chain(readQuoted("'", "atom", false), stream, state); - if (stream.eat('"')) return chain(readQuoted('"', "atom", true), stream, state); - - // :> :>> :< :<< are valid symbols - if (stream.eat(/[\<\>]/)) { - stream.eat(/[\<\>]/); - return "atom"; - } - - // :+ :- :/ :* :| :& :! are valid symbols - if (stream.eat(/[\+\-\*\/\&\|\:\!]/)) { - return "atom"; - } - - // Symbols can't start by a digit - if (stream.eat(/[a-zA-Z$@_\xa1-\uffff]/)) { - stream.eatWhile(/[\w$\xa1-\uffff]/); - // Only one ? ! = is allowed and only as the last character - stream.eat(/[\?\!\=]/); - return "atom"; - } - return "operator"; - } else if (ch == "@" && stream.match(/^@?[a-zA-Z_\xa1-\uffff]/)) { - stream.eat("@"); - stream.eatWhile(/[\w\xa1-\uffff]/); - return "variable-2"; - } else if (ch == "$") { - if (stream.eat(/[a-zA-Z_]/)) { - stream.eatWhile(/[\w]/); - } else if (stream.eat(/\d/)) { - stream.eat(/\d/); - } else { - stream.next(); // Must be a special global like $: or $! - } - return "variable-3"; - } else if (/[a-zA-Z_\xa1-\uffff]/.test(ch)) { - stream.eatWhile(/[\w\xa1-\uffff]/); - stream.eat(/[\?\!]/); - if (stream.eat(":")) return "atom"; - return "ident"; - } else if (ch == "|" && (state.varList || state.lastTok == "{" || state.lastTok == "do")) { - curPunc = "|"; - return null; - } else if (/[\(\)\[\]{}\\;]/.test(ch)) { - curPunc = ch; - return null; - } else if (ch == "-" && stream.eat(">")) { - return "arrow"; - } else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) { - var more = stream.eatWhile(/[=+\-\/*:\.^%<>~|]/); - if (ch == "." && !more) curPunc = "."; - return "operator"; - } else { - return null; - } - } - - function tokenBaseUntilBrace(depth) { - if (!depth) depth = 1; - return function(stream, state) { - if (stream.peek() == "}") { - if (depth == 1) { - state.tokenize.pop(); - return state.tokenize[state.tokenize.length-1](stream, state); - } else { - state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth - 1); - } - } else if (stream.peek() == "{") { - state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth + 1); - } - return tokenBase(stream, state); - }; - } - function tokenBaseOnce() { - var alreadyCalled = false; - return function(stream, state) { - if (alreadyCalled) { - state.tokenize.pop(); - return state.tokenize[state.tokenize.length-1](stream, state); - } - alreadyCalled = true; - return tokenBase(stream, state); - }; - } - function readQuoted(quote, style, embed, unescaped) { - return function(stream, state) { - var escaped = false, ch; - - if (state.context.type === 'read-quoted-paused') { - state.context = state.context.prev; - stream.eat("}"); - } - - while ((ch = stream.next()) != null) { - if (ch == quote && (unescaped || !escaped)) { - state.tokenize.pop(); - break; - } - if (embed && ch == "#" && !escaped) { - if (stream.eat("{")) { - if (quote == "}") { - state.context = {prev: state.context, type: 'read-quoted-paused'}; - } - state.tokenize.push(tokenBaseUntilBrace()); - break; - } else if (/[@\$]/.test(stream.peek())) { - state.tokenize.push(tokenBaseOnce()); - break; - } - } - escaped = !escaped && ch == "\\"; - } - return style; - }; - } - function readHereDoc(phrase) { - return function(stream, state) { - if (stream.match(phrase)) state.tokenize.pop(); - else stream.skipToEnd(); - return "string"; - }; - } - function readBlockComment(stream, state) { - if (stream.sol() && stream.match("=end") && stream.eol()) - state.tokenize.pop(); - stream.skipToEnd(); - return "comment"; - } - - return { - startState: function() { - return {tokenize: [tokenBase], - indented: 0, - context: {type: "top", indented: -config.indentUnit}, - continuedLine: false, - lastTok: null, - varList: false}; - }, - - token: function(stream, state) { - if (stream.sol()) state.indented = stream.indentation(); - var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype; - var thisTok = curPunc; - if (style == "ident") { - var word = stream.current(); - style = state.lastTok == "." ? "property" - : keywords.propertyIsEnumerable(stream.current()) ? "keyword" - : /^[A-Z]/.test(word) ? "tag" - : (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def" - : "variable"; - if (style == "keyword") { - thisTok = word; - if (indentWords.propertyIsEnumerable(word)) kwtype = "indent"; - else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent"; - else if ((word == "if" || word == "unless") && stream.column() == stream.indentation()) - kwtype = "indent"; - else if (word == "do" && state.context.indented < state.indented) - kwtype = "indent"; - } - } - if (curPunc || (style && style != "comment")) state.lastTok = thisTok; - if (curPunc == "|") state.varList = !state.varList; - - if (kwtype == "indent" || /[\(\[\{]/.test(curPunc)) - state.context = {prev: state.context, type: curPunc || style, indented: state.indented}; - else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev) - state.context = state.context.prev; - - if (stream.eol()) - state.continuedLine = (curPunc == "\\" || style == "operator"); - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0); - var ct = state.context; - var closing = ct.type == matching[firstChar] || - ct.type == "keyword" && /^(?:end|until|else|elsif|when|rescue)\b/.test(textAfter); - return ct.indented + (closing ? 0 : config.indentUnit) + - (state.continuedLine ? config.indentUnit : 0); - }, - - electricChars: "}de", // enD and rescuE - lineComment: "#" - }; -}); - -CodeMirror.defineMIME("text/x-ruby", "ruby"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/ruby/test.js b/shared/html/libs/codemirror/5.0.0/mode/ruby/test.js deleted file mode 100644 index cade864..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/ruby/test.js +++ /dev/null @@ -1,14 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "ruby"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("divide_equal_operator", - "[variable bar] [operator /=] [variable foo]"); - - MT("divide_equal_operator_no_spacing", - "[variable foo][operator /=][number 42]"); - -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/rust/index.html b/shared/html/libs/codemirror/5.0.0/mode/rust/index.html deleted file mode 100644 index 407e84f..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/rust/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - -CodeMirror: Rust mode - - - - - - - - - -
-

Rust mode

- - -
- - - -

MIME types defined: text/x-rustsrc.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/rust/rust.js b/shared/html/libs/codemirror/5.0.0/mode/rust/rust.js deleted file mode 100644 index 2bffa9a..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/rust/rust.js +++ /dev/null @@ -1,451 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("rust", function() { - var indentUnit = 4, altIndentUnit = 2; - var valKeywords = { - "if": "if-style", "while": "if-style", "loop": "else-style", "else": "else-style", - "do": "else-style", "ret": "else-style", "fail": "else-style", - "break": "atom", "cont": "atom", "const": "let", "resource": "fn", - "let": "let", "fn": "fn", "for": "for", "alt": "alt", "iface": "iface", - "impl": "impl", "type": "type", "enum": "enum", "mod": "mod", - "as": "op", "true": "atom", "false": "atom", "assert": "op", "check": "op", - "claim": "op", "native": "ignore", "unsafe": "ignore", "import": "else-style", - "export": "else-style", "copy": "op", "log": "op", "log_err": "op", - "use": "op", "bind": "op", "self": "atom", "struct": "enum" - }; - var typeKeywords = function() { - var keywords = {"fn": "fn", "block": "fn", "obj": "obj"}; - var atoms = "bool uint int i8 i16 i32 i64 u8 u16 u32 u64 float f32 f64 str char".split(" "); - for (var i = 0, e = atoms.length; i < e; ++i) keywords[atoms[i]] = "atom"; - return keywords; - }(); - var operatorChar = /[+\-*&%=<>!?|\.@]/; - - // Tokenizer - - // Used as scratch variable to communicate multiple values without - // consing up tons of objects. - var tcat, content; - function r(tc, style) { - tcat = tc; - return style; - } - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"') { - state.tokenize = tokenString; - return state.tokenize(stream, state); - } - if (ch == "'") { - tcat = "atom"; - if (stream.eat("\\")) { - if (stream.skipTo("'")) { stream.next(); return "string"; } - else { return "error"; } - } else { - stream.next(); - return stream.eat("'") ? "string" : "error"; - } - } - if (ch == "/") { - if (stream.eat("/")) { stream.skipToEnd(); return "comment"; } - if (stream.eat("*")) { - state.tokenize = tokenComment(1); - return state.tokenize(stream, state); - } - } - if (ch == "#") { - if (stream.eat("[")) { tcat = "open-attr"; return null; } - stream.eatWhile(/\w/); - return r("macro", "meta"); - } - if (ch == ":" && stream.match(":<")) { - return r("op", null); - } - if (ch.match(/\d/) || (ch == "." && stream.eat(/\d/))) { - var flp = false; - if (!stream.match(/^x[\da-f]+/i) && !stream.match(/^b[01]+/)) { - stream.eatWhile(/\d/); - if (stream.eat(".")) { flp = true; stream.eatWhile(/\d/); } - if (stream.match(/^e[+\-]?\d+/i)) { flp = true; } - } - if (flp) stream.match(/^f(?:32|64)/); - else stream.match(/^[ui](?:8|16|32|64)/); - return r("atom", "number"); - } - if (ch.match(/[()\[\]{}:;,]/)) return r(ch, null); - if (ch == "-" && stream.eat(">")) return r("->", null); - if (ch.match(operatorChar)) { - stream.eatWhile(operatorChar); - return r("op", null); - } - stream.eatWhile(/\w/); - content = stream.current(); - if (stream.match(/^::\w/)) { - stream.backUp(1); - return r("prefix", "variable-2"); - } - if (state.keywords.propertyIsEnumerable(content)) - return r(state.keywords[content], content.match(/true|false/) ? "atom" : "keyword"); - return r("name", "variable"); - } - - function tokenString(stream, state) { - var ch, escaped = false; - while (ch = stream.next()) { - if (ch == '"' && !escaped) { - state.tokenize = tokenBase; - return r("atom", "string"); - } - escaped = !escaped && ch == "\\"; - } - // Hack to not confuse the parser when a string is split in - // pieces. - return r("op", "string"); - } - - function tokenComment(depth) { - return function(stream, state) { - var lastCh = null, ch; - while (ch = stream.next()) { - if (ch == "/" && lastCh == "*") { - if (depth == 1) { - state.tokenize = tokenBase; - break; - } else { - state.tokenize = tokenComment(depth - 1); - return state.tokenize(stream, state); - } - } - if (ch == "*" && lastCh == "/") { - state.tokenize = tokenComment(depth + 1); - return state.tokenize(stream, state); - } - lastCh = ch; - } - return "comment"; - }; - } - - // Parser - - var cx = {state: null, stream: null, marked: null, cc: null}; - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); - } - function cont() { - pass.apply(null, arguments); - return true; - } - - function pushlex(type, info) { - var result = function() { - var state = cx.state; - state.lexical = {indented: state.indented, column: cx.stream.column(), - type: type, prev: state.lexical, info: info}; - }; - result.lex = true; - return result; - } - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type == ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - function typecx() { cx.state.keywords = typeKeywords; } - function valcx() { cx.state.keywords = valKeywords; } - poplex.lex = typecx.lex = valcx.lex = true; - - function commasep(comb, end) { - function more(type) { - if (type == ",") return cont(comb, more); - if (type == end) return cont(); - return cont(more); - } - return function(type) { - if (type == end) return cont(); - return pass(comb, more); - }; - } - - function stat_of(comb, tag) { - return cont(pushlex("stat", tag), comb, poplex, block); - } - function block(type) { - if (type == "}") return cont(); - if (type == "let") return stat_of(letdef1, "let"); - if (type == "fn") return stat_of(fndef); - if (type == "type") return cont(pushlex("stat"), tydef, endstatement, poplex, block); - if (type == "enum") return stat_of(enumdef); - if (type == "mod") return stat_of(mod); - if (type == "iface") return stat_of(iface); - if (type == "impl") return stat_of(impl); - if (type == "open-attr") return cont(pushlex("]"), commasep(expression, "]"), poplex); - if (type == "ignore" || type.match(/[\]\);,]/)) return cont(block); - return pass(pushlex("stat"), expression, poplex, endstatement, block); - } - function endstatement(type) { - if (type == ";") return cont(); - return pass(); - } - function expression(type) { - if (type == "atom" || type == "name") return cont(maybeop); - if (type == "{") return cont(pushlex("}"), exprbrace, poplex); - if (type.match(/[\[\(]/)) return matchBrackets(type, expression); - if (type.match(/[\]\)\};,]/)) return pass(); - if (type == "if-style") return cont(expression, expression); - if (type == "else-style" || type == "op") return cont(expression); - if (type == "for") return cont(pattern, maybetype, inop, expression, expression); - if (type == "alt") return cont(expression, altbody); - if (type == "fn") return cont(fndef); - if (type == "macro") return cont(macro); - return cont(); - } - function maybeop(type) { - if (content == ".") return cont(maybeprop); - if (content == "::<"){return cont(typarams, maybeop);} - if (type == "op" || content == ":") return cont(expression); - if (type == "(" || type == "[") return matchBrackets(type, expression); - return pass(); - } - function maybeprop() { - if (content.match(/^\w+$/)) {cx.marked = "variable"; return cont(maybeop);} - return pass(expression); - } - function exprbrace(type) { - if (type == "op") { - if (content == "|") return cont(blockvars, poplex, pushlex("}", "block"), block); - if (content == "||") return cont(poplex, pushlex("}", "block"), block); - } - if (content == "mutable" || (content.match(/^\w+$/) && cx.stream.peek() == ":" - && !cx.stream.match("::", false))) - return pass(record_of(expression)); - return pass(block); - } - function record_of(comb) { - function ro(type) { - if (content == "mutable" || content == "with") {cx.marked = "keyword"; return cont(ro);} - if (content.match(/^\w*$/)) {cx.marked = "variable"; return cont(ro);} - if (type == ":") return cont(comb, ro); - if (type == "}") return cont(); - return cont(ro); - } - return ro; - } - function blockvars(type) { - if (type == "name") {cx.marked = "def"; return cont(blockvars);} - if (type == "op" && content == "|") return cont(); - return cont(blockvars); - } - - function letdef1(type) { - if (type.match(/[\]\)\};]/)) return cont(); - if (content == "=") return cont(expression, letdef2); - if (type == ",") return cont(letdef1); - return pass(pattern, maybetype, letdef1); - } - function letdef2(type) { - if (type.match(/[\]\)\};,]/)) return pass(letdef1); - else return pass(expression, letdef2); - } - function maybetype(type) { - if (type == ":") return cont(typecx, rtype, valcx); - return pass(); - } - function inop(type) { - if (type == "name" && content == "in") {cx.marked = "keyword"; return cont();} - return pass(); - } - function fndef(type) { - if (content == "@" || content == "~") {cx.marked = "keyword"; return cont(fndef);} - if (type == "name") {cx.marked = "def"; return cont(fndef);} - if (content == "<") return cont(typarams, fndef); - if (type == "{") return pass(expression); - if (type == "(") return cont(pushlex(")"), commasep(argdef, ")"), poplex, fndef); - if (type == "->") return cont(typecx, rtype, valcx, fndef); - if (type == ";") return cont(); - return cont(fndef); - } - function tydef(type) { - if (type == "name") {cx.marked = "def"; return cont(tydef);} - if (content == "<") return cont(typarams, tydef); - if (content == "=") return cont(typecx, rtype, valcx); - return cont(tydef); - } - function enumdef(type) { - if (type == "name") {cx.marked = "def"; return cont(enumdef);} - if (content == "<") return cont(typarams, enumdef); - if (content == "=") return cont(typecx, rtype, valcx, endstatement); - if (type == "{") return cont(pushlex("}"), typecx, enumblock, valcx, poplex); - return cont(enumdef); - } - function enumblock(type) { - if (type == "}") return cont(); - if (type == "(") return cont(pushlex(")"), commasep(rtype, ")"), poplex, enumblock); - if (content.match(/^\w+$/)) cx.marked = "def"; - return cont(enumblock); - } - function mod(type) { - if (type == "name") {cx.marked = "def"; return cont(mod);} - if (type == "{") return cont(pushlex("}"), block, poplex); - return pass(); - } - function iface(type) { - if (type == "name") {cx.marked = "def"; return cont(iface);} - if (content == "<") return cont(typarams, iface); - if (type == "{") return cont(pushlex("}"), block, poplex); - return pass(); - } - function impl(type) { - if (content == "<") return cont(typarams, impl); - if (content == "of" || content == "for") {cx.marked = "keyword"; return cont(rtype, impl);} - if (type == "name") {cx.marked = "def"; return cont(impl);} - if (type == "{") return cont(pushlex("}"), block, poplex); - return pass(); - } - function typarams() { - if (content == ">") return cont(); - if (content == ",") return cont(typarams); - if (content == ":") return cont(rtype, typarams); - return pass(rtype, typarams); - } - function argdef(type) { - if (type == "name") {cx.marked = "def"; return cont(argdef);} - if (type == ":") return cont(typecx, rtype, valcx); - return pass(); - } - function rtype(type) { - if (type == "name") {cx.marked = "variable-3"; return cont(rtypemaybeparam); } - if (content == "mutable") {cx.marked = "keyword"; return cont(rtype);} - if (type == "atom") return cont(rtypemaybeparam); - if (type == "op" || type == "obj") return cont(rtype); - if (type == "fn") return cont(fntype); - if (type == "{") return cont(pushlex("{"), record_of(rtype), poplex); - return matchBrackets(type, rtype); - } - function rtypemaybeparam() { - if (content == "<") return cont(typarams); - return pass(); - } - function fntype(type) { - if (type == "(") return cont(pushlex("("), commasep(rtype, ")"), poplex, fntype); - if (type == "->") return cont(rtype); - return pass(); - } - function pattern(type) { - if (type == "name") {cx.marked = "def"; return cont(patternmaybeop);} - if (type == "atom") return cont(patternmaybeop); - if (type == "op") return cont(pattern); - if (type.match(/[\]\)\};,]/)) return pass(); - return matchBrackets(type, pattern); - } - function patternmaybeop(type) { - if (type == "op" && content == ".") return cont(); - if (content == "to") {cx.marked = "keyword"; return cont(pattern);} - else return pass(); - } - function altbody(type) { - if (type == "{") return cont(pushlex("}", "alt"), altblock1, poplex); - return pass(); - } - function altblock1(type) { - if (type == "}") return cont(); - if (type == "|") return cont(altblock1); - if (content == "when") {cx.marked = "keyword"; return cont(expression, altblock2);} - if (type.match(/[\]\);,]/)) return cont(altblock1); - return pass(pattern, altblock2); - } - function altblock2(type) { - if (type == "{") return cont(pushlex("}", "alt"), block, poplex, altblock1); - else return pass(altblock1); - } - - function macro(type) { - if (type.match(/[\[\(\{]/)) return matchBrackets(type, expression); - return pass(); - } - function matchBrackets(type, comb) { - if (type == "[") return cont(pushlex("]"), commasep(comb, "]"), poplex); - if (type == "(") return cont(pushlex(")"), commasep(comb, ")"), poplex); - if (type == "{") return cont(pushlex("}"), commasep(comb, "}"), poplex); - return cont(); - } - - function parse(state, stream, style) { - var cc = state.cc; - // Communicate our context to the combinators. - // (Less wasteful than consing up a hundred closures on every call.) - cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; - - while (true) { - var combinator = cc.length ? cc.pop() : block; - if (combinator(tcat)) { - while(cc.length && cc[cc.length - 1].lex) - cc.pop()(); - return cx.marked || style; - } - } - } - - return { - startState: function() { - return { - tokenize: tokenBase, - cc: [], - lexical: {indented: -indentUnit, column: 0, type: "top", align: false}, - keywords: valKeywords, - indented: 0 - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - } - if (stream.eatSpace()) return null; - tcat = content = null; - var style = state.tokenize(stream, state); - if (style == "comment") return style; - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - if (tcat == "prefix") return style; - if (!content) content = stream.current(); - return parse(state, stream, style); - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, - type = lexical.type, closing = firstChar == type; - if (type == "stat") return lexical.indented + indentUnit; - if (lexical.align) return lexical.column + (closing ? 0 : 1); - return lexical.indented + (closing ? 0 : (lexical.info == "alt" ? altIndentUnit : indentUnit)); - }, - - electricChars: "{}", - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//", - fold: "brace" - }; -}); - -CodeMirror.defineMIME("text/x-rustsrc", "rust"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/sass/index.html b/shared/html/libs/codemirror/5.0.0/mode/sass/index.html deleted file mode 100644 index 9f4a790..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/sass/index.html +++ /dev/null @@ -1,66 +0,0 @@ - - -CodeMirror: Sass mode - - - - - - - - - - -
-

Sass mode

-
- - -

MIME types defined: text/x-sass.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/sass/sass.js b/shared/html/libs/codemirror/5.0.0/mode/sass/sass.js deleted file mode 100644 index 52a6682..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/sass/sass.js +++ /dev/null @@ -1,414 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("sass", function(config) { - function tokenRegexp(words) { - return new RegExp("^" + words.join("|")); - } - - var keywords = ["true", "false", "null", "auto"]; - var keywordsRegexp = new RegExp("^" + keywords.join("|")); - - var operators = ["\\(", "\\)", "=", ">", "<", "==", ">=", "<=", "\\+", "-", - "\\!=", "/", "\\*", "%", "and", "or", "not", ";","\\{","\\}",":"]; - var opRegexp = tokenRegexp(operators); - - var pseudoElementsRegexp = /^::?[a-zA-Z_][\w\-]*/; - - function urlTokens(stream, state) { - var ch = stream.peek(); - - if (ch === ")") { - stream.next(); - state.tokenizer = tokenBase; - return "operator"; - } else if (ch === "(") { - stream.next(); - stream.eatSpace(); - - return "operator"; - } else if (ch === "'" || ch === '"') { - state.tokenizer = buildStringTokenizer(stream.next()); - return "string"; - } else { - state.tokenizer = buildStringTokenizer(")", false); - return "string"; - } - } - function comment(indentation, multiLine) { - return function(stream, state) { - if (stream.sol() && stream.indentation() <= indentation) { - state.tokenizer = tokenBase; - return tokenBase(stream, state); - } - - if (multiLine && stream.skipTo("*/")) { - stream.next(); - stream.next(); - state.tokenizer = tokenBase; - } else { - stream.skipToEnd(); - } - - return "comment"; - }; - } - - function buildStringTokenizer(quote, greedy) { - if (greedy == null) { greedy = true; } - - function stringTokenizer(stream, state) { - var nextChar = stream.next(); - var peekChar = stream.peek(); - var previousChar = stream.string.charAt(stream.pos-2); - - var endingString = ((nextChar !== "\\" && peekChar === quote) || (nextChar === quote && previousChar !== "\\")); - - if (endingString) { - if (nextChar !== quote && greedy) { stream.next(); } - state.tokenizer = tokenBase; - return "string"; - } else if (nextChar === "#" && peekChar === "{") { - state.tokenizer = buildInterpolationTokenizer(stringTokenizer); - stream.next(); - return "operator"; - } else { - return "string"; - } - } - - return stringTokenizer; - } - - function buildInterpolationTokenizer(currentTokenizer) { - return function(stream, state) { - if (stream.peek() === "}") { - stream.next(); - state.tokenizer = currentTokenizer; - return "operator"; - } else { - return tokenBase(stream, state); - } - }; - } - - function indent(state) { - if (state.indentCount == 0) { - state.indentCount++; - var lastScopeOffset = state.scopes[0].offset; - var currentOffset = lastScopeOffset + config.indentUnit; - state.scopes.unshift({ offset:currentOffset }); - } - } - - function dedent(state) { - if (state.scopes.length == 1) return; - - state.scopes.shift(); - } - - function tokenBase(stream, state) { - var ch = stream.peek(); - - // Comment - if (stream.match("/*")) { - state.tokenizer = comment(stream.indentation(), true); - return state.tokenizer(stream, state); - } - if (stream.match("//")) { - state.tokenizer = comment(stream.indentation(), false); - return state.tokenizer(stream, state); - } - - // Interpolation - if (stream.match("#{")) { - state.tokenizer = buildInterpolationTokenizer(tokenBase); - return "operator"; - } - - // Strings - if (ch === '"' || ch === "'") { - stream.next(); - state.tokenizer = buildStringTokenizer(ch); - return "string"; - } - - if(!state.cursorHalf){// state.cursorHalf === 0 - // first half i.e. before : for key-value pairs - // including selectors - - if (ch === ".") { - stream.next(); - if (stream.match(/^[\w-]+/)) { - indent(state); - return "atom"; - } else if (stream.peek() === "#") { - indent(state); - return "atom"; - } - } - - if (ch === "#") { - stream.next(); - // ID selectors - if (stream.match(/^[\w-]+/)) { - indent(state); - return "atom"; - } - if (stream.peek() === "#") { - indent(state); - return "atom"; - } - } - - // Variables - if (ch === "$") { - stream.next(); - stream.eatWhile(/[\w-]/); - return "variable-2"; - } - - // Numbers - if (stream.match(/^-?[0-9\.]+/)) - return "number"; - - // Units - if (stream.match(/^(px|em|in)\b/)) - return "unit"; - - if (stream.match(keywordsRegexp)) - return "keyword"; - - if (stream.match(/^url/) && stream.peek() === "(") { - state.tokenizer = urlTokens; - return "atom"; - } - - if (ch === "=") { - // Match shortcut mixin definition - if (stream.match(/^=[\w-]+/)) { - indent(state); - return "meta"; - } - } - - if (ch === "+") { - // Match shortcut mixin definition - if (stream.match(/^\+[\w-]+/)){ - return "variable-3"; - } - } - - if(ch === "@"){ - if(stream.match(/@extend/)){ - if(!stream.match(/\s*[\w]/)) - dedent(state); - } - } - - - // Indent Directives - if (stream.match(/^@(else if|if|media|else|for|each|while|mixin|function)/)) { - indent(state); - return "meta"; - } - - // Other Directives - if (ch === "@") { - stream.next(); - stream.eatWhile(/[\w-]/); - return "meta"; - } - - if (stream.eatWhile(/[\w-]/)){ - if(stream.match(/ *: *[\w-\+\$#!\("']/,false)){ - return "propery"; - } - else if(stream.match(/ *:/,false)){ - indent(state); - state.cursorHalf = 1; - return "atom"; - } - else if(stream.match(/ *,/,false)){ - return "atom"; - } - else{ - indent(state); - return "atom"; - } - } - - if(ch === ":"){ - if (stream.match(pseudoElementsRegexp)){ // could be a pseudo-element - return "keyword"; - } - stream.next(); - state.cursorHalf=1; - return "operator"; - } - - } // cursorHalf===0 ends here - else{ - - if (ch === "#") { - stream.next(); - // Hex numbers - if (stream.match(/[0-9a-fA-F]{6}|[0-9a-fA-F]{3}/)){ - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "number"; - } - } - - // Numbers - if (stream.match(/^-?[0-9\.]+/)){ - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "number"; - } - - // Units - if (stream.match(/^(px|em|in)\b/)){ - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "unit"; - } - - if (stream.match(keywordsRegexp)){ - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "keyword"; - } - - if (stream.match(/^url/) && stream.peek() === "(") { - state.tokenizer = urlTokens; - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "atom"; - } - - // Variables - if (ch === "$") { - stream.next(); - stream.eatWhile(/[\w-]/); - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "variable-3"; - } - - // bang character for !important, !default, etc. - if (ch === "!") { - stream.next(); - if(!stream.peek()){ - state.cursorHalf = 0; - } - return stream.match(/^[\w]+/) ? "keyword": "operator"; - } - - if (stream.match(opRegexp)){ - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "operator"; - } - - // attributes - if (stream.eatWhile(/[\w-]/)) { - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "attribute"; - } - - //stream.eatSpace(); - if(!stream.peek()){ - state.cursorHalf = 0; - return null; - } - - } // else ends here - - if (stream.match(opRegexp)) - return "operator"; - - // If we haven't returned by now, we move 1 character - // and return an error - stream.next(); - return null; - } - - function tokenLexer(stream, state) { - if (stream.sol()) state.indentCount = 0; - var style = state.tokenizer(stream, state); - var current = stream.current(); - - if (current === "@return" || current === "}"){ - dedent(state); - } - - if (style !== null) { - var startOfToken = stream.pos - current.length; - - var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount); - - var newScopes = []; - - for (var i = 0; i < state.scopes.length; i++) { - var scope = state.scopes[i]; - - if (scope.offset <= withCurrentIndent) - newScopes.push(scope); - } - - state.scopes = newScopes; - } - - - return style; - } - - return { - startState: function() { - return { - tokenizer: tokenBase, - scopes: [{offset: 0, type: "sass"}], - indentCount: 0, - cursorHalf: 0, // cursor half tells us if cursor lies after (1) - // or before (0) colon (well... more or less) - definedVars: [], - definedMixins: [] - }; - }, - token: function(stream, state) { - var style = tokenLexer(stream, state); - - state.lastToken = { style: style, content: stream.current() }; - - return style; - }, - - indent: function(state) { - return state.scopes[0].offset; - } - }; -}); - -CodeMirror.defineMIME("text/x-sass", "sass"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/scheme/index.html b/shared/html/libs/codemirror/5.0.0/mode/scheme/index.html deleted file mode 100644 index 04d5c6a..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/scheme/index.html +++ /dev/null @@ -1,77 +0,0 @@ - - -CodeMirror: Scheme mode - - - - - - - - - -
-

Scheme mode

-
- - -

MIME types defined: text/x-scheme.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/scheme/scheme.js b/shared/html/libs/codemirror/5.0.0/mode/scheme/scheme.js deleted file mode 100644 index 979edc0..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/scheme/scheme.js +++ /dev/null @@ -1,248 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Author: Koh Zi Han, based on implementation by Koh Zi Chun - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("scheme", function () { - var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", - ATOM = "atom", NUMBER = "number", BRACKET = "bracket"; - var INDENT_WORD_SKIP = 2; - - function makeKeywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var keywords = makeKeywords("λ case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt #f floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string=? string>? string? substring symbol->string symbol? #t tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?"); - var indentKeys = makeKeywords("define let letrec let* lambda"); - - function stateStack(indent, type, prev) { // represents a state stack object - this.indent = indent; - this.type = type; - this.prev = prev; - } - - function pushStack(state, indent, type) { - state.indentStack = new stateStack(indent, type, state.indentStack); - } - - function popStack(state) { - state.indentStack = state.indentStack.prev; - } - - var binaryMatcher = new RegExp(/^(?:[-+]i|[-+][01]+#*(?:\/[01]+#*)?i|[-+]?[01]+#*(?:\/[01]+#*)?@[-+]?[01]+#*(?:\/[01]+#*)?|[-+]?[01]+#*(?:\/[01]+#*)?[-+](?:[01]+#*(?:\/[01]+#*)?)?i|[-+]?[01]+#*(?:\/[01]+#*)?)(?=[()\s;"]|$)/i); - var octalMatcher = new RegExp(/^(?:[-+]i|[-+][0-7]+#*(?:\/[0-7]+#*)?i|[-+]?[0-7]+#*(?:\/[0-7]+#*)?@[-+]?[0-7]+#*(?:\/[0-7]+#*)?|[-+]?[0-7]+#*(?:\/[0-7]+#*)?[-+](?:[0-7]+#*(?:\/[0-7]+#*)?)?i|[-+]?[0-7]+#*(?:\/[0-7]+#*)?)(?=[()\s;"]|$)/i); - var hexMatcher = new RegExp(/^(?:[-+]i|[-+][\da-f]+#*(?:\/[\da-f]+#*)?i|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?@[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?[-+](?:[\da-f]+#*(?:\/[\da-f]+#*)?)?i|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?)(?=[()\s;"]|$)/i); - var decimalMatcher = new RegExp(/^(?:[-+]i|[-+](?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)i|[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)@[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)|[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)[-+](?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)?i|(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*))(?=[()\s;"]|$)/i); - - function isBinaryNumber (stream) { - return stream.match(binaryMatcher); - } - - function isOctalNumber (stream) { - return stream.match(octalMatcher); - } - - function isDecimalNumber (stream, backup) { - if (backup === true) { - stream.backUp(1); - } - return stream.match(decimalMatcher); - } - - function isHexNumber (stream) { - return stream.match(hexMatcher); - } - - return { - startState: function () { - return { - indentStack: null, - indentation: 0, - mode: false, - sExprComment: false - }; - }, - - token: function (stream, state) { - if (state.indentStack == null && stream.sol()) { - // update indentation, but only if indentStack is empty - state.indentation = stream.indentation(); - } - - // skip spaces - if (stream.eatSpace()) { - return null; - } - var returnType = null; - - switch(state.mode){ - case "string": // multi-line string parsing mode - var next, escaped = false; - while ((next = stream.next()) != null) { - if (next == "\"" && !escaped) { - - state.mode = false; - break; - } - escaped = !escaped && next == "\\"; - } - returnType = STRING; // continue on in scheme-string mode - break; - case "comment": // comment parsing mode - var next, maybeEnd = false; - while ((next = stream.next()) != null) { - if (next == "#" && maybeEnd) { - - state.mode = false; - break; - } - maybeEnd = (next == "|"); - } - returnType = COMMENT; - break; - case "s-expr-comment": // s-expr commenting mode - state.mode = false; - if(stream.peek() == "(" || stream.peek() == "["){ - // actually start scheme s-expr commenting mode - state.sExprComment = 0; - }else{ - // if not we just comment the entire of the next token - stream.eatWhile(/[^/s]/); // eat non spaces - returnType = COMMENT; - break; - } - default: // default parsing mode - var ch = stream.next(); - - if (ch == "\"") { - state.mode = "string"; - returnType = STRING; - - } else if (ch == "'") { - returnType = ATOM; - } else if (ch == '#') { - if (stream.eat("|")) { // Multi-line comment - state.mode = "comment"; // toggle to comment mode - returnType = COMMENT; - } else if (stream.eat(/[tf]/i)) { // #t/#f (atom) - returnType = ATOM; - } else if (stream.eat(';')) { // S-Expr comment - state.mode = "s-expr-comment"; - returnType = COMMENT; - } else { - var numTest = null, hasExactness = false, hasRadix = true; - if (stream.eat(/[ei]/i)) { - hasExactness = true; - } else { - stream.backUp(1); // must be radix specifier - } - if (stream.match(/^#b/i)) { - numTest = isBinaryNumber; - } else if (stream.match(/^#o/i)) { - numTest = isOctalNumber; - } else if (stream.match(/^#x/i)) { - numTest = isHexNumber; - } else if (stream.match(/^#d/i)) { - numTest = isDecimalNumber; - } else if (stream.match(/^[-+0-9.]/, false)) { - hasRadix = false; - numTest = isDecimalNumber; - // re-consume the intial # if all matches failed - } else if (!hasExactness) { - stream.eat('#'); - } - if (numTest != null) { - if (hasRadix && !hasExactness) { - // consume optional exactness after radix - stream.match(/^#[ei]/i); - } - if (numTest(stream)) - returnType = NUMBER; - } - } - } else if (/^[-+0-9.]/.test(ch) && isDecimalNumber(stream, true)) { // match non-prefixed number, must be decimal - returnType = NUMBER; - } else if (ch == ";") { // comment - stream.skipToEnd(); // rest of the line is a comment - returnType = COMMENT; - } else if (ch == "(" || ch == "[") { - var keyWord = ''; var indentTemp = stream.column(), letter; - /** - Either - (indent-word .. - (non-indent-word .. - (;something else, bracket, etc. - */ - - while ((letter = stream.eat(/[^\s\(\[\;\)\]]/)) != null) { - keyWord += letter; - } - - if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word - - pushStack(state, indentTemp + INDENT_WORD_SKIP, ch); - } else { // non-indent word - // we continue eating the spaces - stream.eatSpace(); - if (stream.eol() || stream.peek() == ";") { - // nothing significant after - // we restart indentation 1 space after - pushStack(state, indentTemp + 1, ch); - } else { - pushStack(state, indentTemp + stream.current().length, ch); // else we match - } - } - stream.backUp(stream.current().length - 1); // undo all the eating - - if(typeof state.sExprComment == "number") state.sExprComment++; - - returnType = BRACKET; - } else if (ch == ")" || ch == "]") { - returnType = BRACKET; - if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) { - popStack(state); - - if(typeof state.sExprComment == "number"){ - if(--state.sExprComment == 0){ - returnType = COMMENT; // final closing bracket - state.sExprComment = false; // turn off s-expr commenting mode - } - } - } - } else { - stream.eatWhile(/[\w\$_\-!$%&*+\.\/:<=>?@\^~]/); - - if (keywords && keywords.propertyIsEnumerable(stream.current())) { - returnType = BUILTIN; - } else returnType = "variable"; - } - } - return (typeof state.sExprComment == "number") ? COMMENT : returnType; - }, - - indent: function (state) { - if (state.indentStack == null) return state.indentation; - return state.indentStack.indent; - }, - - lineComment: ";;" - }; -}); - -CodeMirror.defineMIME("text/x-scheme", "scheme"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/shell/index.html b/shared/html/libs/codemirror/5.0.0/mode/shell/index.html deleted file mode 100644 index 0b56300..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/shell/index.html +++ /dev/null @@ -1,66 +0,0 @@ - - -CodeMirror: Shell mode - - - - - - - - - - -
-

Shell mode

- - - - - - -

MIME types defined: text/x-sh.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/shell/shell.js b/shared/html/libs/codemirror/5.0.0/mode/shell/shell.js deleted file mode 100644 index a684e8c..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/shell/shell.js +++ /dev/null @@ -1,139 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('shell', function() { - - var words = {}; - function define(style, string) { - var split = string.split(' '); - for(var i = 0; i < split.length; i++) { - words[split[i]] = style; - } - }; - - // Atoms - define('atom', 'true false'); - - // Keywords - define('keyword', 'if then do else elif while until for in esac fi fin ' + - 'fil done exit set unset export function'); - - // Commands - define('builtin', 'ab awk bash beep cat cc cd chown chmod chroot clear cp ' + - 'curl cut diff echo find gawk gcc get git grep kill killall ln ls make ' + - 'mkdir openssl mv nc node npm ping ps restart rm rmdir sed service sh ' + - 'shopt shred source sort sleep ssh start stop su sudo tee telnet top ' + - 'touch vi vim wall wc wget who write yes zsh'); - - function tokenBase(stream, state) { - if (stream.eatSpace()) return null; - - var sol = stream.sol(); - var ch = stream.next(); - - if (ch === '\\') { - stream.next(); - return null; - } - if (ch === '\'' || ch === '"' || ch === '`') { - state.tokens.unshift(tokenString(ch)); - return tokenize(stream, state); - } - if (ch === '#') { - if (sol && stream.eat('!')) { - stream.skipToEnd(); - return 'meta'; // 'comment'? - } - stream.skipToEnd(); - return 'comment'; - } - if (ch === '$') { - state.tokens.unshift(tokenDollar); - return tokenize(stream, state); - } - if (ch === '+' || ch === '=') { - return 'operator'; - } - if (ch === '-') { - stream.eat('-'); - stream.eatWhile(/\w/); - return 'attribute'; - } - if (/\d/.test(ch)) { - stream.eatWhile(/\d/); - if(stream.eol() || !/\w/.test(stream.peek())) { - return 'number'; - } - } - stream.eatWhile(/[\w-]/); - var cur = stream.current(); - if (stream.peek() === '=' && /\w+/.test(cur)) return 'def'; - return words.hasOwnProperty(cur) ? words[cur] : null; - } - - function tokenString(quote) { - return function(stream, state) { - var next, end = false, escaped = false; - while ((next = stream.next()) != null) { - if (next === quote && !escaped) { - end = true; - break; - } - if (next === '$' && !escaped && quote !== '\'') { - escaped = true; - stream.backUp(1); - state.tokens.unshift(tokenDollar); - break; - } - escaped = !escaped && next === '\\'; - } - if (end || !escaped) { - state.tokens.shift(); - } - return (quote === '`' || quote === ')' ? 'quote' : 'string'); - }; - }; - - var tokenDollar = function(stream, state) { - if (state.tokens.length > 1) stream.eat('$'); - var ch = stream.next(), hungry = /\w/; - if (ch === '{') hungry = /[^}]/; - if (ch === '(') { - state.tokens[0] = tokenString(')'); - return tokenize(stream, state); - } - if (!/\d/.test(ch)) { - stream.eatWhile(hungry); - stream.eat('}'); - } - state.tokens.shift(); - return 'def'; - }; - - function tokenize(stream, state) { - return (state.tokens[0] || tokenBase) (stream, state); - }; - - return { - startState: function() {return {tokens:[]};}, - token: function(stream, state) { - return tokenize(stream, state); - }, - lineComment: '#', - fold: "brace" - }; -}); - -CodeMirror.defineMIME('text/x-sh', 'shell'); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/shell/test.js b/shared/html/libs/codemirror/5.0.0/mode/shell/test.js deleted file mode 100644 index a413b5a..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/shell/test.js +++ /dev/null @@ -1,58 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({}, "shell"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("var", - "text [def $var] text"); - MT("varBraces", - "text[def ${var}]text"); - MT("varVar", - "text [def $a$b] text"); - MT("varBracesVarBraces", - "text[def ${a}${b}]text"); - - MT("singleQuotedVar", - "[string 'text $var text']"); - MT("singleQuotedVarBraces", - "[string 'text ${var} text']"); - - MT("doubleQuotedVar", - '[string "text ][def $var][string text"]'); - MT("doubleQuotedVarBraces", - '[string "text][def ${var}][string text"]'); - MT("doubleQuotedVarPunct", - '[string "text ][def $@][string text"]'); - MT("doubleQuotedVarVar", - '[string "][def $a$b][string "]'); - MT("doubleQuotedVarBracesVarBraces", - '[string "][def ${a}${b}][string "]'); - - MT("notAString", - "text\\'text"); - MT("escapes", - "outside\\'\\\"\\`\\\\[string \"inside\\`\\'\\\"\\\\`\\$notAVar\"]outside\\$\\(notASubShell\\)"); - - MT("subshell", - "[builtin echo] [quote $(whoami)] s log, stardate [quote `date`]."); - MT("doubleQuotedSubshell", - "[builtin echo] [string \"][quote $(whoami)][string 's log, stardate `date`.\"]"); - - MT("hashbang", - "[meta #!/bin/bash]"); - MT("comment", - "text [comment # Blurb]"); - - MT("numbers", - "[number 0] [number 1] [number 2]"); - MT("keywords", - "[keyword while] [atom true]; [keyword do]", - " [builtin sleep] [number 3]", - "[keyword done]"); - MT("options", - "[builtin ls] [attribute -l] [attribute --human-readable]"); - MT("operator", - "[def var][operator =]value"); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/sieve/index.html b/shared/html/libs/codemirror/5.0.0/mode/sieve/index.html deleted file mode 100644 index 6f029b6..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/sieve/index.html +++ /dev/null @@ -1,93 +0,0 @@ - - -CodeMirror: Sieve (RFC5228) mode - - - - - - - - - -
-

Sieve (RFC5228) mode

-
- - -

MIME types defined: application/sieve.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/sieve/sieve.js b/shared/html/libs/codemirror/5.0.0/mode/sieve/sieve.js deleted file mode 100644 index f67db2f..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/sieve/sieve.js +++ /dev/null @@ -1,193 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("sieve", function(config) { - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var keywords = words("if elsif else stop require"); - var atoms = words("true false not"); - var indentUnit = config.indentUnit; - - function tokenBase(stream, state) { - - var ch = stream.next(); - if (ch == "/" && stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } - - if (ch === '#') { - stream.skipToEnd(); - return "comment"; - } - - if (ch == "\"") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - - if (ch == "(") { - state._indent.push("("); - // add virtual angel wings so that editor behaves... - // ...more sane incase of broken brackets - state._indent.push("{"); - return null; - } - - if (ch === "{") { - state._indent.push("{"); - return null; - } - - if (ch == ")") { - state._indent.pop(); - state._indent.pop(); - } - - if (ch === "}") { - state._indent.pop(); - return null; - } - - if (ch == ",") - return null; - - if (ch == ";") - return null; - - - if (/[{}\(\),;]/.test(ch)) - return null; - - // 1*DIGIT "K" / "M" / "G" - if (/\d/.test(ch)) { - stream.eatWhile(/[\d]/); - stream.eat(/[KkMmGg]/); - return "number"; - } - - // ":" (ALPHA / "_") *(ALPHA / DIGIT / "_") - if (ch == ":") { - stream.eatWhile(/[a-zA-Z_]/); - stream.eatWhile(/[a-zA-Z0-9_]/); - - return "operator"; - } - - stream.eatWhile(/\w/); - var cur = stream.current(); - - // "text:" *(SP / HTAB) (hash-comment / CRLF) - // *(multiline-literal / multiline-dotstart) - // "." CRLF - if ((cur == "text") && stream.eat(":")) - { - state.tokenize = tokenMultiLineString; - return "string"; - } - - if (keywords.propertyIsEnumerable(cur)) - return "keyword"; - - if (atoms.propertyIsEnumerable(cur)) - return "atom"; - - return null; - } - - function tokenMultiLineString(stream, state) - { - state._multiLineString = true; - // the first line is special it may contain a comment - if (!stream.sol()) { - stream.eatSpace(); - - if (stream.peek() == "#") { - stream.skipToEnd(); - return "comment"; - } - - stream.skipToEnd(); - return "string"; - } - - if ((stream.next() == ".") && (stream.eol())) - { - state._multiLineString = false; - state.tokenize = tokenBase; - } - - return "string"; - } - - function tokenCComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (maybeEnd && ch == "/") { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) - break; - escaped = !escaped && ch == "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return "string"; - }; - } - - return { - startState: function(base) { - return {tokenize: tokenBase, - baseIndent: base || 0, - _indent: []}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) - return null; - - return (state.tokenize || tokenBase)(stream, state);; - }, - - indent: function(state, _textAfter) { - var length = state._indent.length; - if (_textAfter && (_textAfter[0] == "}")) - length--; - - if (length <0) - length = 0; - - return length * indentUnit; - }, - - electricChars: "}" - }; -}); - -CodeMirror.defineMIME("application/sieve", "sieve"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/slim/index.html b/shared/html/libs/codemirror/5.0.0/mode/slim/index.html deleted file mode 100644 index 7fa4e50..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/slim/index.html +++ /dev/null @@ -1,96 +0,0 @@ - - -CodeMirror: SLIM mode - - - - - - - - - - - - - - - - - - - - -
-

SLIM mode

-
- - -

MIME types defined: application/x-slim.

- -

- Parsing/Highlighting Tests: - normal, - verbose. -

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/slim/slim.js b/shared/html/libs/codemirror/5.0.0/mode/slim/slim.js deleted file mode 100644 index 164464d..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/slim/slim.js +++ /dev/null @@ -1,575 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - - CodeMirror.defineMode("slim", function(config) { - var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"}); - var rubyMode = CodeMirror.getMode(config, "ruby"); - var modes = { html: htmlMode, ruby: rubyMode }; - var embedded = { - ruby: "ruby", - javascript: "javascript", - css: "text/css", - sass: "text/x-sass", - scss: "text/x-scss", - less: "text/x-less", - styl: "text/x-styl", // no highlighting so far - coffee: "coffeescript", - asciidoc: "text/x-asciidoc", - markdown: "text/x-markdown", - textile: "text/x-textile", // no highlighting so far - creole: "text/x-creole", // no highlighting so far - wiki: "text/x-wiki", // no highlighting so far - mediawiki: "text/x-mediawiki", // no highlighting so far - rdoc: "text/x-rdoc", // no highlighting so far - builder: "text/x-builder", // no highlighting so far - nokogiri: "text/x-nokogiri", // no highlighting so far - erb: "application/x-erb" - }; - var embeddedRegexp = function(map){ - var arr = []; - for(var key in map) arr.push(key); - return new RegExp("^("+arr.join('|')+"):"); - }(embedded); - - var styleMap = { - "commentLine": "comment", - "slimSwitch": "operator special", - "slimTag": "tag", - "slimId": "attribute def", - "slimClass": "attribute qualifier", - "slimAttribute": "attribute", - "slimSubmode": "keyword special", - "closeAttributeTag": null, - "slimDoctype": null, - "lineContinuation": null - }; - var closing = { - "{": "}", - "[": "]", - "(": ")" - }; - - var nameStartChar = "_a-zA-Z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD"; - var nameChar = nameStartChar + "\\-0-9\xB7\u0300-\u036F\u203F-\u2040"; - var nameRegexp = new RegExp("^[:"+nameStartChar+"](?::["+nameChar+"]|["+nameChar+"]*)"); - var attributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*(?=\\s*=)"); - var wrappedAttributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*"); - var classNameRegexp = /^\.-?[_a-zA-Z]+[\w\-]*/; - var classIdRegexp = /^#[_a-zA-Z]+[\w\-]*/; - - function backup(pos, tokenize, style) { - var restore = function(stream, state) { - state.tokenize = tokenize; - if (stream.pos < pos) { - stream.pos = pos; - return style; - } - return state.tokenize(stream, state); - }; - return function(stream, state) { - state.tokenize = restore; - return tokenize(stream, state); - }; - } - - function maybeBackup(stream, state, pat, offset, style) { - var cur = stream.current(); - var idx = cur.search(pat); - if (idx > -1) { - state.tokenize = backup(stream.pos, state.tokenize, style); - stream.backUp(cur.length - idx - offset); - } - return style; - } - - function continueLine(state, column) { - state.stack = { - parent: state.stack, - style: "continuation", - indented: column, - tokenize: state.line - }; - state.line = state.tokenize; - } - function finishContinue(state) { - if (state.line == state.tokenize) { - state.line = state.stack.tokenize; - state.stack = state.stack.parent; - } - } - - function lineContinuable(column, tokenize) { - return function(stream, state) { - finishContinue(state); - if (stream.match(/^\\$/)) { - continueLine(state, column); - return "lineContinuation"; - } - var style = tokenize(stream, state); - if (stream.eol() && stream.current().match(/(?:^|[^\\])(?:\\\\)*\\$/)) { - stream.backUp(1); - } - return style; - }; - } - function commaContinuable(column, tokenize) { - return function(stream, state) { - finishContinue(state); - var style = tokenize(stream, state); - if (stream.eol() && stream.current().match(/,$/)) { - continueLine(state, column); - } - return style; - }; - } - - function rubyInQuote(endQuote, tokenize) { - // TODO: add multi line support - return function(stream, state) { - var ch = stream.peek(); - if (ch == endQuote && state.rubyState.tokenize.length == 1) { - // step out of ruby context as it seems to complete processing all the braces - stream.next(); - state.tokenize = tokenize; - return "closeAttributeTag"; - } else { - return ruby(stream, state); - } - }; - } - function startRubySplat(tokenize) { - var rubyState; - var runSplat = function(stream, state) { - if (state.rubyState.tokenize.length == 1 && !state.rubyState.context.prev) { - stream.backUp(1); - if (stream.eatSpace()) { - state.rubyState = rubyState; - state.tokenize = tokenize; - return tokenize(stream, state); - } - stream.next(); - } - return ruby(stream, state); - }; - return function(stream, state) { - rubyState = state.rubyState; - state.rubyState = rubyMode.startState(); - state.tokenize = runSplat; - return ruby(stream, state); - }; - } - - function ruby(stream, state) { - return rubyMode.token(stream, state.rubyState); - } - - function htmlLine(stream, state) { - if (stream.match(/^\\$/)) { - return "lineContinuation"; - } - return html(stream, state); - } - function html(stream, state) { - if (stream.match(/^#\{/)) { - state.tokenize = rubyInQuote("}", state.tokenize); - return null; - } - return maybeBackup(stream, state, /[^\\]#\{/, 1, htmlMode.token(stream, state.htmlState)); - } - - function startHtmlLine(lastTokenize) { - return function(stream, state) { - var style = htmlLine(stream, state); - if (stream.eol()) state.tokenize = lastTokenize; - return style; - }; - } - - function startHtmlMode(stream, state, offset) { - state.stack = { - parent: state.stack, - style: "html", - indented: stream.column() + offset, // pipe + space - tokenize: state.line - }; - state.line = state.tokenize = html; - return null; - } - - function comment(stream, state) { - stream.skipToEnd(); - return state.stack.style; - } - - function commentMode(stream, state) { - state.stack = { - parent: state.stack, - style: "comment", - indented: state.indented + 1, - tokenize: state.line - }; - state.line = comment; - return comment(stream, state); - } - - function attributeWrapper(stream, state) { - if (stream.eat(state.stack.endQuote)) { - state.line = state.stack.line; - state.tokenize = state.stack.tokenize; - state.stack = state.stack.parent; - return null; - } - if (stream.match(wrappedAttributeNameRegexp)) { - state.tokenize = attributeWrapperAssign; - return "slimAttribute"; - } - stream.next(); - return null; - } - function attributeWrapperAssign(stream, state) { - if (stream.match(/^==?/)) { - state.tokenize = attributeWrapperValue; - return null; - } - return attributeWrapper(stream, state); - } - function attributeWrapperValue(stream, state) { - var ch = stream.peek(); - if (ch == '"' || ch == "\'") { - state.tokenize = readQuoted(ch, "string", true, false, attributeWrapper); - stream.next(); - return state.tokenize(stream, state); - } - if (ch == '[') { - return startRubySplat(attributeWrapper)(stream, state); - } - if (stream.match(/^(true|false|nil)\b/)) { - state.tokenize = attributeWrapper; - return "keyword"; - } - return startRubySplat(attributeWrapper)(stream, state); - } - - function startAttributeWrapperMode(state, endQuote, tokenize) { - state.stack = { - parent: state.stack, - style: "wrapper", - indented: state.indented + 1, - tokenize: tokenize, - line: state.line, - endQuote: endQuote - }; - state.line = state.tokenize = attributeWrapper; - return null; - } - - function sub(stream, state) { - if (stream.match(/^#\{/)) { - state.tokenize = rubyInQuote("}", state.tokenize); - return null; - } - var subStream = new CodeMirror.StringStream(stream.string.slice(state.stack.indented), stream.tabSize); - subStream.pos = stream.pos - state.stack.indented; - subStream.start = stream.start - state.stack.indented; - subStream.lastColumnPos = stream.lastColumnPos - state.stack.indented; - subStream.lastColumnValue = stream.lastColumnValue - state.stack.indented; - var style = state.subMode.token(subStream, state.subState); - stream.pos = subStream.pos + state.stack.indented; - return style; - } - function firstSub(stream, state) { - state.stack.indented = stream.column(); - state.line = state.tokenize = sub; - return state.tokenize(stream, state); - } - - function createMode(mode) { - var query = embedded[mode]; - var spec = CodeMirror.mimeModes[query]; - if (spec) { - return CodeMirror.getMode(config, spec); - } - var factory = CodeMirror.modes[query]; - if (factory) { - return factory(config, {name: query}); - } - return CodeMirror.getMode(config, "null"); - } - - function getMode(mode) { - if (!modes.hasOwnProperty(mode)) { - return modes[mode] = createMode(mode); - } - return modes[mode]; - } - - function startSubMode(mode, state) { - var subMode = getMode(mode); - var subState = subMode.startState && subMode.startState(); - - state.subMode = subMode; - state.subState = subState; - - state.stack = { - parent: state.stack, - style: "sub", - indented: state.indented + 1, - tokenize: state.line - }; - state.line = state.tokenize = firstSub; - return "slimSubmode"; - } - - function doctypeLine(stream, _state) { - stream.skipToEnd(); - return "slimDoctype"; - } - - function startLine(stream, state) { - var ch = stream.peek(); - if (ch == '<') { - return (state.tokenize = startHtmlLine(state.tokenize))(stream, state); - } - if (stream.match(/^[|']/)) { - return startHtmlMode(stream, state, 1); - } - if (stream.match(/^\/(!|\[\w+])?/)) { - return commentMode(stream, state); - } - if (stream.match(/^(-|==?[<>]?)/)) { - state.tokenize = lineContinuable(stream.column(), commaContinuable(stream.column(), ruby)); - return "slimSwitch"; - } - if (stream.match(/^doctype\b/)) { - state.tokenize = doctypeLine; - return "keyword"; - } - - var m = stream.match(embeddedRegexp); - if (m) { - return startSubMode(m[1], state); - } - - return slimTag(stream, state); - } - - function slim(stream, state) { - if (state.startOfLine) { - return startLine(stream, state); - } - return slimTag(stream, state); - } - - function slimTag(stream, state) { - if (stream.eat('*')) { - state.tokenize = startRubySplat(slimTagExtras); - return null; - } - if (stream.match(nameRegexp)) { - state.tokenize = slimTagExtras; - return "slimTag"; - } - return slimClass(stream, state); - } - function slimTagExtras(stream, state) { - if (stream.match(/^(<>?|> state.indented && state.last != "slimSubmode") { - state.line = state.tokenize = state.stack.tokenize; - state.stack = state.stack.parent; - state.subMode = null; - state.subState = null; - } - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - state.startOfLine = false; - if (style) state.last = style; - return styleMap.hasOwnProperty(style) ? styleMap[style] : style; - }, - - blankLine: function(state) { - if (state.subMode && state.subMode.blankLine) { - return state.subMode.blankLine(state.subState); - } - }, - - innerMode: function(state) { - if (state.subMode) return {state: state.subState, mode: state.subMode}; - return {state: state, mode: mode}; - } - - //indent: function(state) { - // return state.indented; - //} - }; - return mode; - }, "htmlmixed", "ruby"); - - CodeMirror.defineMIME("text/x-slim", "slim"); - CodeMirror.defineMIME("application/x-slim", "slim"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/slim/test.js b/shared/html/libs/codemirror/5.0.0/mode/slim/test.js deleted file mode 100644 index be4ddac..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/slim/test.js +++ /dev/null @@ -1,96 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh - -(function() { - var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "slim"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - // Requires at least one media query - MT("elementName", - "[tag h1] Hey There"); - - MT("oneElementPerLine", - "[tag h1] Hey There .h2"); - - MT("idShortcut", - "[attribute&def #test] Hey There"); - - MT("tagWithIdShortcuts", - "[tag h1][attribute&def #test] Hey There"); - - MT("classShortcut", - "[attribute&qualifier .hello] Hey There"); - - MT("tagWithIdAndClassShortcuts", - "[tag h1][attribute&def #test][attribute&qualifier .hello] Hey There"); - - MT("docType", - "[keyword doctype] xml"); - - MT("comment", - "[comment / Hello WORLD]"); - - MT("notComment", - "[tag h1] This is not a / comment "); - - MT("attributes", - "[tag a]([attribute title]=[string \"test\"]) [attribute href]=[string \"link\"]}"); - - MT("multiLineAttributes", - "[tag a]([attribute title]=[string \"test\"]", - " ) [attribute href]=[string \"link\"]}"); - - MT("htmlCode", - "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket ]"); - - MT("rubyBlock", - "[operator&special =][variable-2 @item]"); - - MT("selectorRubyBlock", - "[tag a][attribute&qualifier .test][operator&special =] [variable-2 @item]"); - - MT("nestedRubyBlock", - "[tag a]", - " [operator&special =][variable puts] [string \"test\"]"); - - MT("multilinePlaintext", - "[tag p]", - " | Hello,", - " World"); - - MT("multilineRuby", - "[tag p]", - " [comment /# this is a comment]", - " [comment and this is a comment too]", - " | Date/Time", - " [operator&special -] [variable now] [operator =] [tag DateTime][operator .][property now]", - " [tag strong][operator&special =] [variable now]", - " [operator&special -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])", - " [operator&special =][string \"Happy\"]", - " [operator&special =][string \"Belated\"]", - " [operator&special =][string \"Birthday\"]"); - - MT("multilineComment", - "[comment /]", - " [comment Multiline]", - " [comment Comment]"); - - MT("hamlAfterRubyTag", - "[attribute&qualifier .block]", - " [tag strong][operator&special =] [variable now]", - " [attribute&qualifier .test]", - " [operator&special =][variable now]", - " [attribute&qualifier .right]"); - - MT("stretchedRuby", - "[operator&special =] [variable puts] [string \"Hello\"],", - " [string \"World\"]"); - - MT("interpolationInHashAttribute", - "[tag div]{[attribute id] = [string \"]#{[variable test]}[string _]#{[variable ting]}[string \"]} test"); - - MT("interpolationInHTMLAttribute", - "[tag div]([attribute title]=[string \"]#{[variable test]}[string _]#{[variable ting]()}[string \"]) Test"); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/smalltalk/index.html b/shared/html/libs/codemirror/5.0.0/mode/smalltalk/index.html deleted file mode 100644 index 2155ebc..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/smalltalk/index.html +++ /dev/null @@ -1,68 +0,0 @@ - - -CodeMirror: Smalltalk mode - - - - - - - - - - -
-

Smalltalk mode

-
- - - -

Simple Smalltalk mode.

- -

MIME types defined: text/x-stsrc.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/smalltalk/smalltalk.js b/shared/html/libs/codemirror/5.0.0/mode/smalltalk/smalltalk.js deleted file mode 100644 index bb510ba..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/smalltalk/smalltalk.js +++ /dev/null @@ -1,168 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('smalltalk', function(config) { - - var specialChars = /[+\-\/\\*~<>=@%|&?!.,:;^]/; - var keywords = /true|false|nil|self|super|thisContext/; - - var Context = function(tokenizer, parent) { - this.next = tokenizer; - this.parent = parent; - }; - - var Token = function(name, context, eos) { - this.name = name; - this.context = context; - this.eos = eos; - }; - - var State = function() { - this.context = new Context(next, null); - this.expectVariable = true; - this.indentation = 0; - this.userIndentationDelta = 0; - }; - - State.prototype.userIndent = function(indentation) { - this.userIndentationDelta = indentation > 0 ? (indentation / config.indentUnit - this.indentation) : 0; - }; - - var next = function(stream, context, state) { - var token = new Token(null, context, false); - var aChar = stream.next(); - - if (aChar === '"') { - token = nextComment(stream, new Context(nextComment, context)); - - } else if (aChar === '\'') { - token = nextString(stream, new Context(nextString, context)); - - } else if (aChar === '#') { - if (stream.peek() === '\'') { - stream.next(); - token = nextSymbol(stream, new Context(nextSymbol, context)); - } else { - if (stream.eatWhile(/[^\s.{}\[\]()]/)) - token.name = 'string-2'; - else - token.name = 'meta'; - } - - } else if (aChar === '$') { - if (stream.next() === '<') { - stream.eatWhile(/[^\s>]/); - stream.next(); - } - token.name = 'string-2'; - - } else if (aChar === '|' && state.expectVariable) { - token.context = new Context(nextTemporaries, context); - - } else if (/[\[\]{}()]/.test(aChar)) { - token.name = 'bracket'; - token.eos = /[\[{(]/.test(aChar); - - if (aChar === '[') { - state.indentation++; - } else if (aChar === ']') { - state.indentation = Math.max(0, state.indentation - 1); - } - - } else if (specialChars.test(aChar)) { - stream.eatWhile(specialChars); - token.name = 'operator'; - token.eos = aChar !== ';'; // ; cascaded message expression - - } else if (/\d/.test(aChar)) { - stream.eatWhile(/[\w\d]/); - token.name = 'number'; - - } else if (/[\w_]/.test(aChar)) { - stream.eatWhile(/[\w\d_]/); - token.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null; - - } else { - token.eos = state.expectVariable; - } - - return token; - }; - - var nextComment = function(stream, context) { - stream.eatWhile(/[^"]/); - return new Token('comment', stream.eat('"') ? context.parent : context, true); - }; - - var nextString = function(stream, context) { - stream.eatWhile(/[^']/); - return new Token('string', stream.eat('\'') ? context.parent : context, false); - }; - - var nextSymbol = function(stream, context) { - stream.eatWhile(/[^']/); - return new Token('string-2', stream.eat('\'') ? context.parent : context, false); - }; - - var nextTemporaries = function(stream, context) { - var token = new Token(null, context, false); - var aChar = stream.next(); - - if (aChar === '|') { - token.context = context.parent; - token.eos = true; - - } else { - stream.eatWhile(/[^|]/); - token.name = 'variable'; - } - - return token; - }; - - return { - startState: function() { - return new State; - }, - - token: function(stream, state) { - state.userIndent(stream.indentation()); - - if (stream.eatSpace()) { - return null; - } - - var token = state.context.next(stream, state.context, state); - state.context = token.context; - state.expectVariable = token.eos; - - return token.name; - }, - - blankLine: function(state) { - state.userIndent(0); - }, - - indent: function(state, textAfter) { - var i = state.context.next === next && textAfter && textAfter.charAt(0) === ']' ? -1 : state.userIndentationDelta; - return (state.indentation + i) * config.indentUnit; - }, - - electricChars: ']' - }; - -}); - -CodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'}); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/smarty/index.html b/shared/html/libs/codemirror/5.0.0/mode/smarty/index.html deleted file mode 100644 index 8d88c9a..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/smarty/index.html +++ /dev/null @@ -1,136 +0,0 @@ - - -CodeMirror: Smarty mode - - - - - - - - - -
-

Smarty mode

-
- - - -
- -

Smarty 2, custom delimiters

-
- - - -
- -

Smarty 3

- - - - - - -

A plain text/Smarty version 2 or 3 mode, which allows for custom delimiter tags.

- -

MIME types defined: text/x-smarty

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/smarty/smarty.js b/shared/html/libs/codemirror/5.0.0/mode/smarty/smarty.js deleted file mode 100644 index bb05324..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/smarty/smarty.js +++ /dev/null @@ -1,221 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Smarty 2 and 3 mode. - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("smarty", function(config) { - "use strict"; - - // our default settings; check to see if they're overridden - var settings = { - rightDelimiter: '}', - leftDelimiter: '{', - smartyVersion: 2 // for backward compatibility - }; - if (config.hasOwnProperty("leftDelimiter")) { - settings.leftDelimiter = config.leftDelimiter; - } - if (config.hasOwnProperty("rightDelimiter")) { - settings.rightDelimiter = config.rightDelimiter; - } - if (config.hasOwnProperty("smartyVersion") && config.smartyVersion === 3) { - settings.smartyVersion = 3; - } - - var keyFunctions = ["debug", "extends", "function", "include", "literal"]; - var last; - var regs = { - operatorChars: /[+\-*&%=<>!?]/, - validIdentifier: /[a-zA-Z0-9_]/, - stringChar: /['"]/ - }; - - var helpers = { - cont: function(style, lastType) { - last = lastType; - return style; - }, - chain: function(stream, state, parser) { - state.tokenize = parser; - return parser(stream, state); - } - }; - - - // our various parsers - var parsers = { - - // the main tokenizer - tokenizer: function(stream, state) { - if (stream.match(settings.leftDelimiter, true)) { - if (stream.eat("*")) { - return helpers.chain(stream, state, parsers.inBlock("comment", "*" + settings.rightDelimiter)); - } else { - // Smarty 3 allows { and } surrounded by whitespace to NOT slip into Smarty mode - state.depth++; - var isEol = stream.eol(); - var isFollowedByWhitespace = /\s/.test(stream.peek()); - if (settings.smartyVersion === 3 && settings.leftDelimiter === "{" && (isEol || isFollowedByWhitespace)) { - state.depth--; - return null; - } else { - state.tokenize = parsers.smarty; - last = "startTag"; - return "tag"; - } - } - } else { - stream.next(); - return null; - } - }, - - // parsing Smarty content - smarty: function(stream, state) { - if (stream.match(settings.rightDelimiter, true)) { - if (settings.smartyVersion === 3) { - state.depth--; - if (state.depth <= 0) { - state.tokenize = parsers.tokenizer; - } - } else { - state.tokenize = parsers.tokenizer; - } - return helpers.cont("tag", null); - } - - if (stream.match(settings.leftDelimiter, true)) { - state.depth++; - return helpers.cont("tag", "startTag"); - } - - var ch = stream.next(); - if (ch == "$") { - stream.eatWhile(regs.validIdentifier); - return helpers.cont("variable-2", "variable"); - } else if (ch == "|") { - return helpers.cont("operator", "pipe"); - } else if (ch == ".") { - return helpers.cont("operator", "property"); - } else if (regs.stringChar.test(ch)) { - state.tokenize = parsers.inAttribute(ch); - return helpers.cont("string", "string"); - } else if (regs.operatorChars.test(ch)) { - stream.eatWhile(regs.operatorChars); - return helpers.cont("operator", "operator"); - } else if (ch == "[" || ch == "]") { - return helpers.cont("bracket", "bracket"); - } else if (ch == "(" || ch == ")") { - return helpers.cont("bracket", "operator"); - } else if (/\d/.test(ch)) { - stream.eatWhile(/\d/); - return helpers.cont("number", "number"); - } else { - - if (state.last == "variable") { - if (ch == "@") { - stream.eatWhile(regs.validIdentifier); - return helpers.cont("property", "property"); - } else if (ch == "|") { - stream.eatWhile(regs.validIdentifier); - return helpers.cont("qualifier", "modifier"); - } - } else if (state.last == "pipe") { - stream.eatWhile(regs.validIdentifier); - return helpers.cont("qualifier", "modifier"); - } else if (state.last == "whitespace") { - stream.eatWhile(regs.validIdentifier); - return helpers.cont("attribute", "modifier"); - } if (state.last == "property") { - stream.eatWhile(regs.validIdentifier); - return helpers.cont("property", null); - } else if (/\s/.test(ch)) { - last = "whitespace"; - return null; - } - - var str = ""; - if (ch != "/") { - str += ch; - } - var c = null; - while (c = stream.eat(regs.validIdentifier)) { - str += c; - } - for (var i=0, j=keyFunctions.length; i - -CodeMirror: Smarty mixed mode - - - - - - - - - - - - - -
-

Smarty mixed mode

-
- - - -

The Smarty mixed mode depends on the Smarty and HTML mixed modes. HTML - mixed mode itself depends on XML, JavaScript, and CSS modes.

- -

It takes the same options, as Smarty and HTML mixed modes.

- -

MIME types defined: text/x-smarty.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/smartymixed/smartymixed.js b/shared/html/libs/codemirror/5.0.0/mode/smartymixed/smartymixed.js deleted file mode 100644 index 4fc7ca4..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/smartymixed/smartymixed.js +++ /dev/null @@ -1,197 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** -* @file smartymixed.js -* @brief Smarty Mixed Codemirror mode (Smarty + Mixed HTML) -* @author Ruslan Osmanov -* @version 3.0 -* @date 05.07.2013 -*/ - -// Warning: Don't base other modes on this one. This here is a -// terrible way to write a mixed mode. - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../smarty/smarty")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../smarty/smarty"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("smartymixed", function(config) { - var htmlMixedMode = CodeMirror.getMode(config, "htmlmixed"); - var smartyMode = CodeMirror.getMode(config, "smarty"); - - var settings = { - rightDelimiter: '}', - leftDelimiter: '{' - }; - - if (config.hasOwnProperty("leftDelimiter")) { - settings.leftDelimiter = config.leftDelimiter; - } - if (config.hasOwnProperty("rightDelimiter")) { - settings.rightDelimiter = config.rightDelimiter; - } - - function reEsc(str) { return str.replace(/[^\s\w]/g, "\\$&"); } - - var reLeft = reEsc(settings.leftDelimiter), reRight = reEsc(settings.rightDelimiter); - var regs = { - smartyComment: new RegExp("^" + reRight + "\\*"), - literalOpen: new RegExp(reLeft + "literal" + reRight), - literalClose: new RegExp(reLeft + "\/literal" + reRight), - hasLeftDelimeter: new RegExp(".*" + reLeft), - htmlHasLeftDelimeter: new RegExp("[^<>]*" + reLeft) - }; - - var helpers = { - chain: function(stream, state, parser) { - state.tokenize = parser; - return parser(stream, state); - }, - - cleanChain: function(stream, state, parser) { - state.tokenize = null; - state.localState = null; - state.localMode = null; - return (typeof parser == "string") ? (parser ? parser : null) : parser(stream, state); - }, - - maybeBackup: function(stream, pat, style) { - var cur = stream.current(); - var close = cur.search(pat), - m; - if (close > - 1) stream.backUp(cur.length - close); - else if (m = cur.match(/<\/?$/)) { - stream.backUp(cur.length); - if (!stream.match(pat, false)) stream.match(cur[0]); - } - return style; - } - }; - - var parsers = { - html: function(stream, state) { - var htmlTagName = state.htmlMixedState.htmlState.context && state.htmlMixedState.htmlState.context.tagName - ? state.htmlMixedState.htmlState.context.tagName - : null; - - if (!state.inLiteral && stream.match(regs.htmlHasLeftDelimeter, false) && htmlTagName === null) { - state.tokenize = parsers.smarty; - state.localMode = smartyMode; - state.localState = smartyMode.startState(htmlMixedMode.indent(state.htmlMixedState, "")); - return helpers.maybeBackup(stream, settings.leftDelimiter, smartyMode.token(stream, state.localState)); - } else if (!state.inLiteral && stream.match(settings.leftDelimiter, false)) { - state.tokenize = parsers.smarty; - state.localMode = smartyMode; - state.localState = smartyMode.startState(htmlMixedMode.indent(state.htmlMixedState, "")); - return helpers.maybeBackup(stream, settings.leftDelimiter, smartyMode.token(stream, state.localState)); - } - return htmlMixedMode.token(stream, state.htmlMixedState); - }, - - smarty: function(stream, state) { - if (stream.match(settings.leftDelimiter, false)) { - if (stream.match(regs.smartyComment, false)) { - return helpers.chain(stream, state, parsers.inBlock("comment", "*" + settings.rightDelimiter)); - } - } else if (stream.match(settings.rightDelimiter, false)) { - stream.eat(settings.rightDelimiter); - state.tokenize = parsers.html; - state.localMode = htmlMixedMode; - state.localState = state.htmlMixedState; - return "tag"; - } - - return helpers.maybeBackup(stream, settings.rightDelimiter, smartyMode.token(stream, state.localState)); - }, - - inBlock: function(style, terminator) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.match(terminator)) { - helpers.cleanChain(stream, state, ""); - break; - } - stream.next(); - } - return style; - }; - } - }; - - return { - startState: function() { - var state = htmlMixedMode.startState(); - return { - token: parsers.html, - localMode: null, - localState: null, - htmlMixedState: state, - tokenize: null, - inLiteral: false - }; - }, - - copyState: function(state) { - var local = null, tok = (state.tokenize || state.token); - if (state.localState) { - local = CodeMirror.copyState((tok != parsers.html ? smartyMode : htmlMixedMode), state.localState); - } - return { - token: state.token, - tokenize: state.tokenize, - localMode: state.localMode, - localState: local, - htmlMixedState: CodeMirror.copyState(htmlMixedMode, state.htmlMixedState), - inLiteral: state.inLiteral - }; - }, - - token: function(stream, state) { - if (stream.match(settings.leftDelimiter, false)) { - if (!state.inLiteral && stream.match(regs.literalOpen, true)) { - state.inLiteral = true; - return "keyword"; - } else if (state.inLiteral && stream.match(regs.literalClose, true)) { - state.inLiteral = false; - return "keyword"; - } - } - if (state.inLiteral && state.localState != state.htmlMixedState) { - state.tokenize = parsers.html; - state.localMode = htmlMixedMode; - state.localState = state.htmlMixedState; - } - - var style = (state.tokenize || state.token)(stream, state); - return style; - }, - - indent: function(state, textAfter) { - if (state.localMode == smartyMode - || (state.inLiteral && !state.localMode) - || regs.hasLeftDelimeter.test(textAfter)) { - return CodeMirror.Pass; - } - return htmlMixedMode.indent(state.htmlMixedState, textAfter); - }, - - innerMode: function(state) { - return { - state: state.localState || state.htmlMixedState, - mode: state.localMode || htmlMixedMode - }; - } - }; -}, "htmlmixed", "smarty"); - -CodeMirror.defineMIME("text/x-smarty", "smartymixed"); -// vim: et ts=2 sts=2 sw=2 - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/solr/index.html b/shared/html/libs/codemirror/5.0.0/mode/solr/index.html deleted file mode 100644 index 4b18c25..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/solr/index.html +++ /dev/null @@ -1,57 +0,0 @@ - - -CodeMirror: Solr mode - - - - - - - - - -
-

Solr mode

- -
- -
- - - -

MIME types defined: text/x-solr.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/solr/solr.js b/shared/html/libs/codemirror/5.0.0/mode/solr/solr.js deleted file mode 100644 index f7f7087..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/solr/solr.js +++ /dev/null @@ -1,104 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("solr", function() { - "use strict"; - - var isStringChar = /[^\s\|\!\+\-\*\?\~\^\&\:\(\)\[\]\{\}\^\"\\]/; - var isOperatorChar = /[\|\!\+\-\*\?\~\^\&]/; - var isOperatorString = /^(OR|AND|NOT|TO)$/i; - - function isNumber(word) { - return parseFloat(word, 10).toString() === word; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) break; - escaped = !escaped && next == "\\"; - } - - if (!escaped) state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenOperator(operator) { - return function(stream, state) { - var style = "operator"; - if (operator == "+") - style += " positive"; - else if (operator == "-") - style += " negative"; - else if (operator == "|") - stream.eat(/\|/); - else if (operator == "&") - stream.eat(/\&/); - else if (operator == "^") - style += " boost"; - - state.tokenize = tokenBase; - return style; - }; - } - - function tokenWord(ch) { - return function(stream, state) { - var word = ch; - while ((ch = stream.peek()) && ch.match(isStringChar) != null) { - word += stream.next(); - } - - state.tokenize = tokenBase; - if (isOperatorString.test(word)) - return "operator"; - else if (isNumber(word)) - return "number"; - else if (stream.peek() == ":") - return "field"; - else - return "string"; - }; - } - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"') - state.tokenize = tokenString(ch); - else if (isOperatorChar.test(ch)) - state.tokenize = tokenOperator(ch); - else if (isStringChar.test(ch)) - state.tokenize = tokenWord(ch); - - return (state.tokenize != tokenBase) ? state.tokenize(stream, state) : null; - } - - return { - startState: function() { - return { - tokenize: tokenBase - }; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - } - }; -}); - -CodeMirror.defineMIME("text/x-solr", "solr"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/soy/index.html b/shared/html/libs/codemirror/5.0.0/mode/soy/index.html deleted file mode 100644 index f0216f0..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/soy/index.html +++ /dev/null @@ -1,68 +0,0 @@ - - -CodeMirror: Soy (Closure Template) mode - - - - - - - - - - - - - - -
-

Soy (Closure Template) mode

-
- - - -

A mode for Closure Templates (Soy).

-

MIME type defined: text/x-soy.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/soy/soy.js b/shared/html/libs/codemirror/5.0.0/mode/soy/soy.js deleted file mode 100644 index 7e81e8d..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/soy/soy.js +++ /dev/null @@ -1,198 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var indentingTags = ["template", "literal", "msg", "fallbackmsg", "let", "if", "elseif", - "else", "switch", "case", "default", "foreach", "ifempty", "for", - "call", "param", "deltemplate", "delcall", "log"]; - - CodeMirror.defineMode("soy", function(config) { - var textMode = CodeMirror.getMode(config, "text/plain"); - var modes = { - html: CodeMirror.getMode(config, {name: "text/html", multilineTagIndentFactor: 2, multilineTagIndentPastTag: false}), - attributes: textMode, - text: textMode, - uri: textMode, - css: CodeMirror.getMode(config, "text/css"), - js: CodeMirror.getMode(config, {name: "text/javascript", statementIndent: 2 * config.indentUnit}) - }; - - function last(array) { - return array[array.length - 1]; - } - - function tokenUntil(stream, state, untilRegExp) { - var oldString = stream.string; - var match = untilRegExp.exec(oldString.substr(stream.pos)); - if (match) { - // We don't use backUp because it backs up just the position, not the state. - // This uses an undocumented API. - stream.string = oldString.substr(0, stream.pos + match.index); - } - var result = stream.hideFirstChars(state.indent, function() { - return state.localMode.token(stream, state.localState); - }); - stream.string = oldString; - return result; - } - - return { - startState: function() { - return { - kind: [], - kindTag: [], - soyState: [], - indent: 0, - localMode: modes.html, - localState: CodeMirror.startState(modes.html) - }; - }, - - copyState: function(state) { - return { - tag: state.tag, // Last seen Soy tag. - kind: state.kind.concat([]), // Values of kind="" attributes. - kindTag: state.kindTag.concat([]), // Opened tags with kind="" attributes. - soyState: state.soyState.concat([]), - indent: state.indent, // Indentation of the following line. - localMode: state.localMode, - localState: CodeMirror.copyState(state.localMode, state.localState) - }; - }, - - token: function(stream, state) { - var match; - - switch (last(state.soyState)) { - case "comment": - if (stream.match(/^.*?\*\//)) { - state.soyState.pop(); - } else { - stream.skipToEnd(); - } - return "comment"; - - case "variable": - if (stream.match(/^}/)) { - state.indent -= 2 * config.indentUnit; - state.soyState.pop(); - return "variable-2"; - } - stream.next(); - return null; - - case "tag": - if (stream.match(/^\/?}/)) { - if (state.tag == "/template" || state.tag == "/deltemplate") state.indent = 0; - else state.indent -= (stream.current() == "/}" || indentingTags.indexOf(state.tag) == -1 ? 2 : 1) * config.indentUnit; - state.soyState.pop(); - return "keyword"; - } else if (stream.match(/^(\w+)(?==)/)) { - if (stream.current() == "kind" && (match = stream.match(/^="([^"]+)/, false))) { - var kind = match[1]; - state.kind.push(kind); - state.kindTag.push(state.tag); - state.localMode = modes[kind] || modes.html; - state.localState = CodeMirror.startState(state.localMode); - } - return "attribute"; - } else if (stream.match(/^"/)) { - state.soyState.push("string"); - return "string"; - } - stream.next(); - return null; - - case "literal": - if (stream.match(/^(?=\{\/literal})/)) { - state.indent -= config.indentUnit; - state.soyState.pop(); - return this.token(stream, state); - } - return tokenUntil(stream, state, /\{\/literal}/); - - case "string": - if (stream.match(/^.*?"/)) { - state.soyState.pop(); - } else { - stream.skipToEnd(); - } - return "string"; - } - - if (stream.match(/^\/\*/)) { - state.soyState.push("comment"); - return "comment"; - } else if (stream.match(stream.sol() ? /^\s*\/\/.*/ : /^\s+\/\/.*/)) { - return "comment"; - } else if (stream.match(/^\{\$\w*/)) { - state.indent += 2 * config.indentUnit; - state.soyState.push("variable"); - return "variable-2"; - } else if (stream.match(/^\{literal}/)) { - state.indent += config.indentUnit; - state.soyState.push("literal"); - return "keyword"; - } else if (match = stream.match(/^\{([\/@\\]?\w*)/)) { - if (match[1] != "/switch") - state.indent += (/^(\/|(else|elseif|case|default)$)/.test(match[1]) && state.tag != "switch" ? 1 : 2) * config.indentUnit; - state.tag = match[1]; - if (state.tag == "/" + last(state.kindTag)) { - // We found the tag that opened the current kind="". - state.kind.pop(); - state.kindTag.pop(); - state.localMode = modes[last(state.kind)] || modes.html; - state.localState = CodeMirror.startState(state.localMode); - } - state.soyState.push("tag"); - return "keyword"; - } - - return tokenUntil(stream, state, /\{|\s+\/\/|\/\*/); - }, - - indent: function(state, textAfter) { - var indent = state.indent, top = last(state.soyState); - if (top == "comment") return CodeMirror.Pass; - - if (top == "literal") { - if (/^\{\/literal}/.test(textAfter)) indent -= config.indentUnit; - } else { - if (/^\s*\{\/(template|deltemplate)\b/.test(textAfter)) return 0; - if (/^\{(\/|(fallbackmsg|elseif|else|ifempty)\b)/.test(textAfter)) indent -= config.indentUnit; - if (state.tag != "switch" && /^\{(case|default)\b/.test(textAfter)) indent -= config.indentUnit; - if (/^\{\/switch\b/.test(textAfter)) indent -= config.indentUnit; - } - if (indent && state.localMode.indent) - indent += state.localMode.indent(state.localState, textAfter); - return indent; - }, - - innerMode: function(state) { - if (state.soyState.length && last(state.soyState) != "literal") return null; - else return {state: state.localState, mode: state.localMode}; - }, - - electricInput: /^\s*\{(\/|\/template|\/deltemplate|\/switch|fallbackmsg|elseif|else|case|default|ifempty|\/literal\})$/, - lineComment: "//", - blockCommentStart: "/*", - blockCommentEnd: "*/", - blockCommentContinue: " * ", - fold: "indent" - }; - }, "htmlmixed"); - - CodeMirror.registerHelper("hintWords", "soy", indentingTags.concat( - ["delpackage", "namespace", "alias", "print", "css", "debugger"])); - - CodeMirror.defineMIME("text/x-soy", "soy"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/sparql/index.html b/shared/html/libs/codemirror/5.0.0/mode/sparql/index.html deleted file mode 100644 index 84ef4d3..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/sparql/index.html +++ /dev/null @@ -1,61 +0,0 @@ - - -CodeMirror: SPARQL mode - - - - - - - - - - -
-

SPARQL mode

-
- - -

MIME types defined: application/sparql-query.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/sparql/sparql.js b/shared/html/libs/codemirror/5.0.0/mode/sparql/sparql.js deleted file mode 100644 index bbf8a76..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/sparql/sparql.js +++ /dev/null @@ -1,174 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("sparql", function(config) { - var indentUnit = config.indentUnit; - var curPunc; - - function wordRegexp(words) { - return new RegExp("^(?:" + words.join("|") + ")$", "i"); - } - var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri", - "iri", "uri", "bnode", "count", "sum", "min", "max", "avg", "sample", - "group_concat", "rand", "abs", "ceil", "floor", "round", "concat", "substr", "strlen", - "replace", "ucase", "lcase", "encode_for_uri", "contains", "strstarts", "strends", - "strbefore", "strafter", "year", "month", "day", "hours", "minutes", "seconds", - "timezone", "tz", "now", "uuid", "struuid", "md5", "sha1", "sha256", "sha384", - "sha512", "coalesce", "if", "strlang", "strdt", "isnumeric", "regex", "exists", - "isblank", "isliteral", "a"]); - var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe", - "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional", - "graph", "by", "asc", "desc", "as", "having", "undef", "values", "group", - "minus", "in", "not", "service", "silent", "using", "insert", "delete", "union", - "true", "false", "with", - "data", "copy", "to", "move", "add", "create", "drop", "clear", "load"]); - var operatorChars = /[*+\-<>=&|\^\/!\?]/; - - function tokenBase(stream, state) { - var ch = stream.next(); - curPunc = null; - if (ch == "$" || ch == "?") { - if(ch == "?" && stream.match(/\s/, false)){ - return "operator"; - } - stream.match(/^[\w\d]*/); - return "variable-2"; - } - else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) { - stream.match(/^[^\s\u00a0>]*>?/); - return "atom"; - } - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenLiteral(ch); - return state.tokenize(stream, state); - } - else if (/[{}\(\),\.;\[\]]/.test(ch)) { - curPunc = ch; - return "bracket"; - } - else if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - else if (operatorChars.test(ch)) { - stream.eatWhile(operatorChars); - return "operator"; - } - else if (ch == ":") { - stream.eatWhile(/[\w\d\._\-]/); - return "atom"; - } - else if (ch == "@") { - stream.eatWhile(/[a-z\d\-]/i); - return "meta"; - } - else { - stream.eatWhile(/[_\w\d]/); - if (stream.eat(":")) { - stream.eatWhile(/[\w\d_\-]/); - return "atom"; - } - var word = stream.current(); - if (ops.test(word)) - return "builtin"; - else if (keywords.test(word)) - return "keyword"; - else - return "variable"; - } - } - - function tokenLiteral(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && ch == "\\"; - } - return "string"; - }; - } - - function pushContext(state, type, col) { - state.context = {prev: state.context, indent: state.indent, col: col, type: type}; - } - function popContext(state) { - state.indent = state.context.indent; - state.context = state.context.prev; - } - - return { - startState: function() { - return {tokenize: tokenBase, - context: null, - indent: 0, - col: 0}; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (state.context && state.context.align == null) state.context.align = false; - state.indent = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - - if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") { - state.context.align = true; - } - - if (curPunc == "(") pushContext(state, ")", stream.column()); - else if (curPunc == "[") pushContext(state, "]", stream.column()); - else if (curPunc == "{") pushContext(state, "}", stream.column()); - else if (/[\]\}\)]/.test(curPunc)) { - while (state.context && state.context.type == "pattern") popContext(state); - if (state.context && curPunc == state.context.type) popContext(state); - } - else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state); - else if (/atom|string|variable/.test(style) && state.context) { - if (/[\}\]]/.test(state.context.type)) - pushContext(state, "pattern", stream.column()); - else if (state.context.type == "pattern" && !state.context.align) { - state.context.align = true; - state.context.col = stream.column(); - } - } - - return style; - }, - - indent: function(state, textAfter) { - var firstChar = textAfter && textAfter.charAt(0); - var context = state.context; - if (/[\]\}]/.test(firstChar)) - while (context && context.type == "pattern") context = context.prev; - - var closing = context && firstChar == context.type; - if (!context) - return 0; - else if (context.type == "pattern") - return context.col; - else if (context.align) - return context.col + (closing ? 0 : 1); - else - return context.indent + (closing ? 0 : indentUnit); - } - }; -}); - -CodeMirror.defineMIME("application/sparql-query", "sparql"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/spreadsheet/index.html b/shared/html/libs/codemirror/5.0.0/mode/spreadsheet/index.html deleted file mode 100644 index a52f76f..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/spreadsheet/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - -CodeMirror: Spreadsheet mode - - - - - - - - - - -
-

Spreadsheet mode

-
- - - -

MIME types defined: text/x-spreadsheet.

- -

The Spreadsheet Mode

-

Created by Robert Plummer

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/spreadsheet/spreadsheet.js b/shared/html/libs/codemirror/5.0.0/mode/spreadsheet/spreadsheet.js deleted file mode 100644 index 6fab00f..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/spreadsheet/spreadsheet.js +++ /dev/null @@ -1,109 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("spreadsheet", function () { - return { - startState: function () { - return { - stringType: null, - stack: [] - }; - }, - token: function (stream, state) { - if (!stream) return; - - //check for state changes - if (state.stack.length === 0) { - //strings - if ((stream.peek() == '"') || (stream.peek() == "'")) { - state.stringType = stream.peek(); - stream.next(); // Skip quote - state.stack.unshift("string"); - } - } - - //return state - //stack has - switch (state.stack[0]) { - case "string": - while (state.stack[0] === "string" && !stream.eol()) { - if (stream.peek() === state.stringType) { - stream.next(); // Skip quote - state.stack.shift(); // Clear flag - } else if (stream.peek() === "\\") { - stream.next(); - stream.next(); - } else { - stream.match(/^.[^\\\"\']*/); - } - } - return "string"; - - case "characterClass": - while (state.stack[0] === "characterClass" && !stream.eol()) { - if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) - state.stack.shift(); - } - return "operator"; - } - - var peek = stream.peek(); - - //no stack - switch (peek) { - case "[": - stream.next(); - state.stack.unshift("characterClass"); - return "bracket"; - case ":": - stream.next(); - return "operator"; - case "\\": - if (stream.match(/\\[a-z]+/)) return "string-2"; - else return null; - case ".": - case ",": - case ";": - case "*": - case "-": - case "+": - case "^": - case "<": - case "/": - case "=": - stream.next(); - return "atom"; - case "$": - stream.next(); - return "builtin"; - } - - if (stream.match(/\d+/)) { - if (stream.match(/^\w+/)) return "error"; - return "number"; - } else if (stream.match(/^[a-zA-Z_]\w*/)) { - if (stream.match(/(?=[\(.])/, false)) return "keyword"; - return "variable-2"; - } else if (["[", "]", "(", ")", "{", "}"].indexOf(peek) != -1) { - stream.next(); - return "bracket"; - } else if (!stream.eatSpace()) { - stream.next(); - } - return null; - } - }; - }); - - CodeMirror.defineMIME("text/x-spreadsheet", "spreadsheet"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/sql/index.html b/shared/html/libs/codemirror/5.0.0/mode/sql/index.html deleted file mode 100644 index a0d8d9e..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/sql/index.html +++ /dev/null @@ -1,84 +0,0 @@ - - -CodeMirror: SQL Mode for CodeMirror - - - - - - - - - - - - -
-

SQL Mode for CodeMirror

-
- -
-

MIME types defined: - text/x-sql, - text/x-mysql, - text/x-mariadb, - text/x-cassandra, - text/x-plsql, - text/x-mssql, - text/x-hive. -

- - -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/sql/sql.js b/shared/html/libs/codemirror/5.0.0/mode/sql/sql.js deleted file mode 100644 index ee6c194..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/sql/sql.js +++ /dev/null @@ -1,391 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("sql", function(config, parserConfig) { - "use strict"; - - var client = parserConfig.client || {}, - atoms = parserConfig.atoms || {"false": true, "true": true, "null": true}, - builtin = parserConfig.builtin || {}, - keywords = parserConfig.keywords || {}, - operatorChars = parserConfig.operatorChars || /^[*+\-%<>!=&|~^]/, - support = parserConfig.support || {}, - hooks = parserConfig.hooks || {}, - dateSQL = parserConfig.dateSQL || {"date" : true, "time" : true, "timestamp" : true}; - - function tokenBase(stream, state) { - var ch = stream.next(); - - // call hooks from the mime type - if (hooks[ch]) { - var result = hooks[ch](stream, state); - if (result !== false) return result; - } - - if (support.hexNumber == true && - ((ch == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) - || (ch == "x" || ch == "X") && stream.match(/^'[0-9a-fA-F]+'/))) { - // hex - // ref: http://dev.mysql.com/doc/refman/5.5/en/hexadecimal-literals.html - return "number"; - } else if (support.binaryNumber == true && - (((ch == "b" || ch == "B") && stream.match(/^'[01]+'/)) - || (ch == "0" && stream.match(/^b[01]+/)))) { - // bitstring - // ref: http://dev.mysql.com/doc/refman/5.5/en/bit-field-literals.html - return "number"; - } else if (ch.charCodeAt(0) > 47 && ch.charCodeAt(0) < 58) { - // numbers - // ref: http://dev.mysql.com/doc/refman/5.5/en/number-literals.html - stream.match(/^[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/); - support.decimallessFloat == true && stream.eat('.'); - return "number"; - } else if (ch == "?" && (stream.eatSpace() || stream.eol() || stream.eat(";"))) { - // placeholders - return "variable-3"; - } else if (ch == "'" || (ch == '"' && support.doubleQuote)) { - // strings - // ref: http://dev.mysql.com/doc/refman/5.5/en/string-literals.html - state.tokenize = tokenLiteral(ch); - return state.tokenize(stream, state); - } else if ((((support.nCharCast == true && (ch == "n" || ch == "N")) - || (support.charsetCast == true && ch == "_" && stream.match(/[a-z][a-z0-9]*/i))) - && (stream.peek() == "'" || stream.peek() == '"'))) { - // charset casting: _utf8'str', N'str', n'str' - // ref: http://dev.mysql.com/doc/refman/5.5/en/string-literals.html - return "keyword"; - } else if (/^[\(\),\;\[\]]/.test(ch)) { - // no highlightning - return null; - } else if (support.commentSlashSlash && ch == "/" && stream.eat("/")) { - // 1-line comment - stream.skipToEnd(); - return "comment"; - } else if ((support.commentHash && ch == "#") - || (ch == "-" && stream.eat("-") && (!support.commentSpaceRequired || stream.eat(" ")))) { - // 1-line comments - // ref: https://kb.askmonty.org/en/comment-syntax/ - stream.skipToEnd(); - return "comment"; - } else if (ch == "/" && stream.eat("*")) { - // multi-line comments - // ref: https://kb.askmonty.org/en/comment-syntax/ - state.tokenize = tokenComment; - return state.tokenize(stream, state); - } else if (ch == ".") { - // .1 for 0.1 - if (support.zerolessFloat == true && stream.match(/^(?:\d+(?:e[+-]?\d+)?)/i)) { - return "number"; - } - // .table_name (ODBC) - // // ref: http://dev.mysql.com/doc/refman/5.6/en/identifier-qualifiers.html - if (support.ODBCdotTable == true && stream.match(/^[a-zA-Z_]+/)) { - return "variable-2"; - } - } else if (operatorChars.test(ch)) { - // operators - stream.eatWhile(operatorChars); - return null; - } else if (ch == '{' && - (stream.match(/^( )*(d|D|t|T|ts|TS)( )*'[^']*'( )*}/) || stream.match(/^( )*(d|D|t|T|ts|TS)( )*"[^"]*"( )*}/))) { - // dates (weird ODBC syntax) - // ref: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-literals.html - return "number"; - } else { - stream.eatWhile(/^[_\w\d]/); - var word = stream.current().toLowerCase(); - // dates (standard SQL syntax) - // ref: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-literals.html - if (dateSQL.hasOwnProperty(word) && (stream.match(/^( )+'[^']*'/) || stream.match(/^( )+"[^"]*"/))) - return "number"; - if (atoms.hasOwnProperty(word)) return "atom"; - if (builtin.hasOwnProperty(word)) return "builtin"; - if (keywords.hasOwnProperty(word)) return "keyword"; - if (client.hasOwnProperty(word)) return "string-2"; - return null; - } - } - - // 'string', with char specified in quote escaped by '\' - function tokenLiteral(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && ch == "\\"; - } - return "string"; - }; - } - function tokenComment(stream, state) { - while (true) { - if (stream.skipTo("*")) { - stream.next(); - if (stream.eat("/")) { - state.tokenize = tokenBase; - break; - } - } else { - stream.skipToEnd(); - break; - } - } - return "comment"; - } - - function pushContext(stream, state, type) { - state.context = { - prev: state.context, - indent: stream.indentation(), - col: stream.column(), - type: type - }; - } - - function popContext(state) { - state.indent = state.context.indent; - state.context = state.context.prev; - } - - return { - startState: function() { - return {tokenize: tokenBase, context: null}; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (state.context && state.context.align == null) - state.context.align = false; - } - if (stream.eatSpace()) return null; - - var style = state.tokenize(stream, state); - if (style == "comment") return style; - - if (state.context && state.context.align == null) - state.context.align = true; - - var tok = stream.current(); - if (tok == "(") - pushContext(stream, state, ")"); - else if (tok == "[") - pushContext(stream, state, "]"); - else if (state.context && state.context.type == tok) - popContext(state); - return style; - }, - - indent: function(state, textAfter) { - var cx = state.context; - if (!cx) return CodeMirror.Pass; - var closing = textAfter.charAt(0) == cx.type; - if (cx.align) return cx.col + (closing ? 0 : 1); - else return cx.indent + (closing ? 0 : config.indentUnit); - }, - - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: support.commentSlashSlash ? "//" : support.commentHash ? "#" : null - }; -}); - -(function() { - "use strict"; - - // `identifier` - function hookIdentifier(stream) { - // MySQL/MariaDB identifiers - // ref: http://dev.mysql.com/doc/refman/5.6/en/identifier-qualifiers.html - var ch; - while ((ch = stream.next()) != null) { - if (ch == "`" && !stream.eat("`")) return "variable-2"; - } - stream.backUp(stream.current().length - 1); - return stream.eatWhile(/\w/) ? "variable-2" : null; - } - - // variable token - function hookVar(stream) { - // variables - // @@prefix.varName @varName - // varName can be quoted with ` or ' or " - // ref: http://dev.mysql.com/doc/refman/5.5/en/user-variables.html - if (stream.eat("@")) { - stream.match(/^session\./); - stream.match(/^local\./); - stream.match(/^global\./); - } - - if (stream.eat("'")) { - stream.match(/^.*'/); - return "variable-2"; - } else if (stream.eat('"')) { - stream.match(/^.*"/); - return "variable-2"; - } else if (stream.eat("`")) { - stream.match(/^.*`/); - return "variable-2"; - } else if (stream.match(/^[0-9a-zA-Z$\.\_]+/)) { - return "variable-2"; - } - return null; - }; - - // short client keyword token - function hookClient(stream) { - // \N means NULL - // ref: http://dev.mysql.com/doc/refman/5.5/en/null-values.html - if (stream.eat("N")) { - return "atom"; - } - // \g, etc - // ref: http://dev.mysql.com/doc/refman/5.5/en/mysql-commands.html - return stream.match(/^[a-zA-Z.#!?]/) ? "variable-2" : null; - } - - // these keywords are used by all SQL dialects (however, a mode can still overwrite it) - var sqlKeywords = "alter and as asc between by count create delete desc distinct drop from having in insert into is join like not on or order select set table union update values where "; - - // turn a space-separated list into an array - function set(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - // A generic SQL Mode. It's not a standard, it just try to support what is generally supported - CodeMirror.defineMIME("text/x-sql", { - name: "sql", - keywords: set(sqlKeywords + "begin"), - builtin: set("bool boolean bit blob enum long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision real date datetime year unsigned signed decimal numeric"), - atoms: set("false true null unknown"), - operatorChars: /^[*+\-%<>!=]/, - dateSQL: set("date time timestamp"), - support: set("ODBCdotTable doubleQuote binaryNumber hexNumber") - }); - - CodeMirror.defineMIME("text/x-mssql", { - name: "sql", - client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"), - keywords: set(sqlKeywords + "begin trigger proc view index for add constraint key primary foreign collate clustered nonclustered"), - builtin: set("bigint numeric bit smallint decimal smallmoney int tinyint money float real char varchar text nchar nvarchar ntext binary varbinary image cursor timestamp hierarchyid uniqueidentifier sql_variant xml table "), - atoms: set("false true null unknown"), - operatorChars: /^[*+\-%<>!=]/, - dateSQL: set("date datetimeoffset datetime2 smalldatetime datetime time"), - hooks: { - "@": hookVar - } - }); - - CodeMirror.defineMIME("text/x-mysql", { - name: "sql", - client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"), - keywords: set(sqlKeywords + "accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group groupby_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"), - builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"), - atoms: set("false true null unknown"), - operatorChars: /^[*+\-%<>!=&|^]/, - dateSQL: set("date time timestamp"), - support: set("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"), - hooks: { - "@": hookVar, - "`": hookIdentifier, - "\\": hookClient - } - }); - - CodeMirror.defineMIME("text/x-mariadb", { - name: "sql", - client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"), - keywords: set(sqlKeywords + "accessible action add after algorithm all always analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general generated get global grant grants group groupby_concat handler hard hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password persistent phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show shutdown signal slave slow smallint snapshot soft soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views virtual warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"), - builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"), - atoms: set("false true null unknown"), - operatorChars: /^[*+\-%<>!=&|^]/, - dateSQL: set("date time timestamp"), - support: set("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"), - hooks: { - "@": hookVar, - "`": hookIdentifier, - "\\": hookClient - } - }); - - // the query language used by Apache Cassandra is called CQL, but this mime type - // is called Cassandra to avoid confusion with Contextual Query Language - CodeMirror.defineMIME("text/x-cassandra", { - name: "sql", - client: { }, - keywords: set("use select from using consistency where limit first reversed first and in insert into values using consistency ttl update set delete truncate begin batch apply create keyspace with columnfamily primary key index on drop alter type add any one quorum all local_quorum each_quorum"), - builtin: set("ascii bigint blob boolean counter decimal double float int text timestamp uuid varchar varint"), - atoms: set("false true"), - operatorChars: /^[<>=]/, - dateSQL: { }, - support: set("commentSlashSlash decimallessFloat"), - hooks: { } - }); - - // this is based on Peter Raganitsch's 'plsql' mode - CodeMirror.defineMIME("text/x-plsql", { - name: "sql", - client: set("appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap"), - keywords: set("abort accept access add all alter and any array arraylen as asc assert assign at attributes audit authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elseif elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning returns reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work"), - builtin: set("abs acos add_months ascii asin atan atan2 average bfile bfilename bigserial bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim serial sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid unlogged upper user userenv varchar varchar2 variance varying vsize xml"), - operatorChars: /^[*+\-%<>!=~]/, - dateSQL: set("date time timestamp"), - support: set("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber") - }); - - // Created to support specific hive keywords - CodeMirror.defineMIME("text/x-hive", { - name: "sql", - keywords: set("select alter $elem$ $key$ $value$ add after all analyze and archive as asc before between binary both bucket buckets by cascade case cast change cluster clustered clusterstatus collection column columns comment compute concatenate continue create cross cursor data database databases dbproperties deferred delete delimited desc describe directory disable distinct distribute drop else enable end escaped exclusive exists explain export extended external false fetch fields fileformat first format formatted from full function functions grant group having hold_ddltime idxproperties if import in index indexes inpath inputdriver inputformat insert intersect into is items join keys lateral left like limit lines load local location lock locks mapjoin materialized minus msck no_drop nocompress not of offline on option or order out outer outputdriver outputformat overwrite partition partitioned partitions percent plus preserve procedure purge range rcfile read readonly reads rebuild recordreader recordwriter recover reduce regexp rename repair replace restrict revoke right rlike row schema schemas semi sequencefile serde serdeproperties set shared show show_database sort sorted ssl statistics stored streamtable table tables tablesample tblproperties temporary terminated textfile then tmp to touch transform trigger true unarchive undo union uniquejoin unlock update use using utc utc_tmestamp view when where while with"), - builtin: set("bool boolean long timestamp tinyint smallint bigint int float double date datetime unsigned string array struct map uniontype"), - atoms: set("false true null unknown"), - operatorChars: /^[*+\-%<>!=]/, - dateSQL: set("date timestamp"), - support: set("ODBCdotTable doubleQuote binaryNumber hexNumber") - }); -}()); - -}); - -/* - How Properties of Mime Types are used by SQL Mode - ================================================= - - keywords: - A list of keywords you want to be highlighted. - builtin: - A list of builtin types you want to be highlighted (if you want types to be of class "builtin" instead of "keyword"). - operatorChars: - All characters that must be handled as operators. - client: - Commands parsed and executed by the client (not the server). - support: - A list of supported syntaxes which are not common, but are supported by more than 1 DBMS. - * ODBCdotTable: .tableName - * zerolessFloat: .1 - * doubleQuote - * nCharCast: N'string' - * charsetCast: _utf8'string' - * commentHash: use # char for comments - * commentSlashSlash: use // for comments - * commentSpaceRequired: require a space after -- for comments - atoms: - Keywords that must be highlighted as atoms,. Some DBMS's support more atoms than others: - UNKNOWN, INFINITY, UNDERFLOW, NaN... - dateSQL: - Used for date/time SQL standard syntax, because not all DBMS's support same temporal types. -*/ diff --git a/shared/html/libs/codemirror/5.0.0/mode/stex/index.html b/shared/html/libs/codemirror/5.0.0/mode/stex/index.html deleted file mode 100644 index 14679da..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/stex/index.html +++ /dev/null @@ -1,110 +0,0 @@ - - -CodeMirror: sTeX mode - - - - - - - - - -
-

sTeX mode

-
- - -

MIME types defined: text/x-stex.

- -

Parsing/Highlighting Tests: normal, verbose.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/stex/stex.js b/shared/html/libs/codemirror/5.0.0/mode/stex/stex.js deleted file mode 100644 index 835ed46..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/stex/stex.js +++ /dev/null @@ -1,251 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* - * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de) - * Licence: MIT - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("stex", function() { - "use strict"; - - function pushCommand(state, command) { - state.cmdState.push(command); - } - - function peekCommand(state) { - if (state.cmdState.length > 0) { - return state.cmdState[state.cmdState.length - 1]; - } else { - return null; - } - } - - function popCommand(state) { - var plug = state.cmdState.pop(); - if (plug) { - plug.closeBracket(); - } - } - - // returns the non-default plugin closest to the end of the list - function getMostPowerful(state) { - var context = state.cmdState; - for (var i = context.length - 1; i >= 0; i--) { - var plug = context[i]; - if (plug.name == "DEFAULT") { - continue; - } - return plug; - } - return { styleIdentifier: function() { return null; } }; - } - - function addPluginPattern(pluginName, cmdStyle, styles) { - return function () { - this.name = pluginName; - this.bracketNo = 0; - this.style = cmdStyle; - this.styles = styles; - this.argument = null; // \begin and \end have arguments that follow. These are stored in the plugin - - this.styleIdentifier = function() { - return this.styles[this.bracketNo - 1] || null; - }; - this.openBracket = function() { - this.bracketNo++; - return "bracket"; - }; - this.closeBracket = function() {}; - }; - } - - var plugins = {}; - - plugins["importmodule"] = addPluginPattern("importmodule", "tag", ["string", "builtin"]); - plugins["documentclass"] = addPluginPattern("documentclass", "tag", ["", "atom"]); - plugins["usepackage"] = addPluginPattern("usepackage", "tag", ["atom"]); - plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]); - plugins["end"] = addPluginPattern("end", "tag", ["atom"]); - - plugins["DEFAULT"] = function () { - this.name = "DEFAULT"; - this.style = "tag"; - - this.styleIdentifier = this.openBracket = this.closeBracket = function() {}; - }; - - function setState(state, f) { - state.f = f; - } - - // called when in a normal (no environment) context - function normal(source, state) { - var plug; - // Do we look like '\command' ? If so, attempt to apply the plugin 'command' - if (source.match(/^\\[a-zA-Z@]+/)) { - var cmdName = source.current().slice(1); - plug = plugins[cmdName] || plugins["DEFAULT"]; - plug = new plug(); - pushCommand(state, plug); - setState(state, beginParams); - return plug.style; - } - - // escape characters - if (source.match(/^\\[$&%#{}_]/)) { - return "tag"; - } - - // white space control characters - if (source.match(/^\\[,;!\/\\]/)) { - return "tag"; - } - - // find if we're starting various math modes - if (source.match("\\[")) { - setState(state, function(source, state){ return inMathMode(source, state, "\\]"); }); - return "keyword"; - } - if (source.match("$$")) { - setState(state, function(source, state){ return inMathMode(source, state, "$$"); }); - return "keyword"; - } - if (source.match("$")) { - setState(state, function(source, state){ return inMathMode(source, state, "$"); }); - return "keyword"; - } - - var ch = source.next(); - if (ch == "%") { - source.skipToEnd(); - return "comment"; - } else if (ch == '}' || ch == ']') { - plug = peekCommand(state); - if (plug) { - plug.closeBracket(ch); - setState(state, beginParams); - } else { - return "error"; - } - return "bracket"; - } else if (ch == '{' || ch == '[') { - plug = plugins["DEFAULT"]; - plug = new plug(); - pushCommand(state, plug); - return "bracket"; - } else if (/\d/.test(ch)) { - source.eatWhile(/[\w.%]/); - return "atom"; - } else { - source.eatWhile(/[\w\-_]/); - plug = getMostPowerful(state); - if (plug.name == 'begin') { - plug.argument = source.current(); - } - return plug.styleIdentifier(); - } - } - - function inMathMode(source, state, endModeSeq) { - if (source.eatSpace()) { - return null; - } - if (source.match(endModeSeq)) { - setState(state, normal); - return "keyword"; - } - if (source.match(/^\\[a-zA-Z@]+/)) { - return "tag"; - } - if (source.match(/^[a-zA-Z]+/)) { - return "variable-2"; - } - // escape characters - if (source.match(/^\\[$&%#{}_]/)) { - return "tag"; - } - // white space control characters - if (source.match(/^\\[,;!\/]/)) { - return "tag"; - } - // special math-mode characters - if (source.match(/^[\^_&]/)) { - return "tag"; - } - // non-special characters - if (source.match(/^[+\-<>|=,\/@!*:;'"`~#?]/)) { - return null; - } - if (source.match(/^(\d+\.\d*|\d*\.\d+|\d+)/)) { - return "number"; - } - var ch = source.next(); - if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") { - return "bracket"; - } - - if (ch == "%") { - source.skipToEnd(); - return "comment"; - } - return "error"; - } - - function beginParams(source, state) { - var ch = source.peek(), lastPlug; - if (ch == '{' || ch == '[') { - lastPlug = peekCommand(state); - lastPlug.openBracket(ch); - source.eat(ch); - setState(state, normal); - return "bracket"; - } - if (/[ \t\r]/.test(ch)) { - source.eat(ch); - return null; - } - setState(state, normal); - popCommand(state); - - return normal(source, state); - } - - return { - startState: function() { - return { - cmdState: [], - f: normal - }; - }, - copyState: function(s) { - return { - cmdState: s.cmdState.slice(), - f: s.f - }; - }, - token: function(stream, state) { - return state.f(stream, state); - }, - blankLine: function(state) { - state.f = normal; - state.cmdState.length = 0; - }, - lineComment: "%" - }; - }); - - CodeMirror.defineMIME("text/x-stex", "stex"); - CodeMirror.defineMIME("text/x-latex", "stex"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/stex/test.js b/shared/html/libs/codemirror/5.0.0/mode/stex/test.js deleted file mode 100644 index 22f027e..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/stex/test.js +++ /dev/null @@ -1,123 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({tabSize: 4}, "stex"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("word", - "foo"); - - MT("twoWords", - "foo bar"); - - MT("beginEndDocument", - "[tag \\begin][bracket {][atom document][bracket }]", - "[tag \\end][bracket {][atom document][bracket }]"); - - MT("beginEndEquation", - "[tag \\begin][bracket {][atom equation][bracket }]", - " E=mc^2", - "[tag \\end][bracket {][atom equation][bracket }]"); - - MT("beginModule", - "[tag \\begin][bracket {][atom module][bracket }[[]]]"); - - MT("beginModuleId", - "[tag \\begin][bracket {][atom module][bracket }[[]id=bbt-size[bracket ]]]"); - - MT("importModule", - "[tag \\importmodule][bracket [[][string b-b-t][bracket ]]{][builtin b-b-t][bracket }]"); - - MT("importModulePath", - "[tag \\importmodule][bracket [[][tag \\KWARCslides][bracket {][string dmath/en/cardinality][bracket }]]{][builtin card][bracket }]"); - - MT("psForPDF", - "[tag \\PSforPDF][bracket [[][atom 1][bracket ]]{]#1[bracket }]"); - - MT("comment", - "[comment % foo]"); - - MT("tagComment", - "[tag \\item][comment % bar]"); - - MT("commentTag", - " [comment % \\item]"); - - MT("commentLineBreak", - "[comment %]", - "foo"); - - MT("tagErrorCurly", - "[tag \\begin][error }][bracket {]"); - - MT("tagErrorSquare", - "[tag \\item][error ]]][bracket {]"); - - MT("commentCurly", - "[comment % }]"); - - MT("tagHash", - "the [tag \\#] key"); - - MT("tagNumber", - "a [tag \\$][atom 5] stetson"); - - MT("tagPercent", - "[atom 100][tag \\%] beef"); - - MT("tagAmpersand", - "L [tag \\&] N"); - - MT("tagUnderscore", - "foo[tag \\_]bar"); - - MT("tagBracketOpen", - "[tag \\emph][bracket {][tag \\{][bracket }]"); - - MT("tagBracketClose", - "[tag \\emph][bracket {][tag \\}][bracket }]"); - - MT("tagLetterNumber", - "section [tag \\S][atom 1]"); - - MT("textTagNumber", - "para [tag \\P][atom 2]"); - - MT("thinspace", - "x[tag \\,]y"); - - MT("thickspace", - "x[tag \\;]y"); - - MT("negativeThinspace", - "x[tag \\!]y"); - - MT("periodNotSentence", - "J.\\ L.\\ is"); - - MT("periodSentence", - "X[tag \\@]. The"); - - MT("italicCorrection", - "[bracket {][tag \\em] If[tag \\/][bracket }] I"); - - MT("tagBracket", - "[tag \\newcommand][bracket {][tag \\pop][bracket }]"); - - MT("inlineMathTagFollowedByNumber", - "[keyword $][tag \\pi][number 2][keyword $]"); - - MT("inlineMath", - "[keyword $][number 3][variable-2 x][tag ^][number 2.45]-[tag \\sqrt][bracket {][tag \\$\\alpha][bracket }] = [number 2][keyword $] other text"); - - MT("displayMath", - "More [keyword $$]\t[variable-2 S][tag ^][variable-2 n][tag \\sum] [variable-2 i][keyword $$] other text"); - - MT("mathWithComment", - "[keyword $][variable-2 x] [comment % $]", - "[variable-2 y][keyword $] other text"); - - MT("lineBreakArgument", - "[tag \\\\][bracket [[][atom 1cm][bracket ]]]"); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/stylus/index.html b/shared/html/libs/codemirror/5.0.0/mode/stylus/index.html deleted file mode 100644 index 354bf30..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/stylus/index.html +++ /dev/null @@ -1,104 +0,0 @@ - - -CodeMirror: Stylus mode - - - - - - - - - - - -
-

Stylus mode

-
-
- - -

MIME types defined: text/x-styl.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/stylus/stylus.js b/shared/html/libs/codemirror/5.0.0/mode/stylus/stylus.js deleted file mode 100644 index 6f7c754..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/stylus/stylus.js +++ /dev/null @@ -1,444 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("stylus", function(config) { - - var operatorsRegexp = /^(\?:?|\+[+=]?|-[\-=]?|\*[\*=]?|\/=?|[=!:\?]?=|<=?|>=?|%=?|&&|\|=?|\~|!|\^|\\)/, - delimitersRegexp = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/, - wordOperatorsRegexp = wordRegexp(wordOperators), - commonKeywordsRegexp = wordRegexp(commonKeywords), - commonAtomsRegexp = wordRegexp(commonAtoms), - commonDefRegexp = wordRegexp(commonDef), - vendorPrefixesRegexp = new RegExp(/^\-(moz|ms|o|webkit)-/), - cssValuesWithBracketsRegexp = new RegExp("^(" + cssValuesWithBrackets_.join("|") + ")\\([\\w\-\\#\\,\\.\\%\\s\\(\\)]*\\)"); - - var tokenBase = function(stream, state) { - - if (stream.eatSpace()) return null; - - var ch = stream.peek(); - - // Single line Comment - if (stream.match('//')) { - stream.skipToEnd(); - return "comment"; - } - - // Multiline Comment - if (stream.match('/*')) { - state.tokenizer = multilineComment; - return state.tokenizer(stream, state); - } - - // Strings - if (ch === '"' || ch === "'") { - stream.next(); - state.tokenizer = buildStringTokenizer(ch); - return "string"; - } - - // Def - if (ch === "@") { - stream.next(); - if (stream.match(/extend/)) { - dedent(state); // remove indentation after selectors - } else if (stream.match(/media[\w-\s]*[\w-]/)) { - indent(state); - } else if(stream.eatWhile(/[\w-]/)) { - if(stream.current().match(commonDefRegexp)) { - indent(state); - } - } - return "def"; - } - - // Number - if (stream.match(/^-?[0-9\.]/, false)) { - - // Floats - if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i) || stream.match(/^-?\d+\.\d*/)) { - - // Prevent from getting extra . on 1.. - if (stream.peek() == ".") { - stream.backUp(1); - } - // Units - stream.eatWhile(/[a-z%]/i); - return "number"; - } - // Integers - if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/) || stream.match(/^-?0(?![\dx])/i)) { - // Units - stream.eatWhile(/[a-z%]/i); - return "number"; - } - } - - // Hex color and id selector - if (ch === "#") { - stream.next(); - - // Hex color - if (stream.match(/^[0-9a-f]{6}|[0-9a-f]{3}/i)) { - return "atom"; - } - - // ID selector - if (stream.match(/^[\w-]+/i)) { - indent(state); - return "builtin"; - } - } - - // Vendor prefixes - if (stream.match(vendorPrefixesRegexp)) { - return "meta"; - } - - // Gradients and animation as CSS value - if (stream.match(cssValuesWithBracketsRegexp)) { - return "atom"; - } - - // Mixins / Functions with indentation - if (stream.sol() && stream.match(/^\.?[a-z][\w-]*\(/i)) { - stream.backUp(1); - indent(state); - return "keyword"; - } - - // Mixins / Functions - if (stream.match(/^\.?[a-z][\w-]*\(/i)) { - stream.backUp(1); - return "keyword"; - } - - // +Block mixins - if (stream.match(/^(\+|\-)[a-z][\w-]+\(/i)) { - stream.backUp(1); - indent(state); - return "keyword"; - } - - // url tokens - if (stream.match(/^url/) && stream.peek() === "(") { - state.tokenizer = urlTokens; - if(!stream.peek()) { - state.cursorHalf = 0; - } - return "atom"; - } - - // Class - if (stream.match(/^\.[a-z][\w-]*/i)) { - indent(state); - return "qualifier"; - } - - // & Parent Reference with BEM naming - if (stream.match(/^(_|__|-|--)[a-z0-9-]+/)) { - return "qualifier"; - } - - // Pseudo elements/classes - if (ch == ':' && stream.match(/^::?[\w-]+/)) { - indent(state); - return "variable-3"; - } - - // Conditionals - if (stream.match(wordRegexp(["for", "if", "else", "unless"]))) { - indent(state); - return "keyword"; - } - - // Keywords - if (stream.match(commonKeywordsRegexp)) { - return "keyword"; - } - - // Atoms - if (stream.match(commonAtomsRegexp)) { - return "atom"; - } - - // Variables - if (stream.match(/^\$?[a-z][\w-]+\s?=(\s|[\w-'"\$])/i)) { - stream.backUp(2); - var cssPropertie = stream.current().toLowerCase().match(/[\w-]+/)[0]; - return cssProperties[cssPropertie] === undefined ? "variable-2" : "property"; - } else if (stream.match(/\$[\w-\.]+/i)) { - return "variable-2"; - } else if (stream.match(/\$?[\w-]+\.[\w-]+/i)) { - var cssTypeSelector = stream.current().toLowerCase().match(/[\w]+/)[0]; - if(cssTypeSelectors[cssTypeSelector] === undefined) { - return "variable-2"; - } else stream.backUp(stream.current().length); - } - - // !important - if (ch === "!") { - stream.next(); - return stream.match(/^[\w]+/) ? "keyword": "operator"; - } - - // / Root Reference - if (stream.match(/^\/(:|\.|#|[a-z])/)) { - stream.backUp(1); - return "variable-3"; - } - - // Operators and delimiters - if (stream.match(operatorsRegexp) || stream.match(wordOperatorsRegexp)) { - return "operator"; - } - if (stream.match(delimitersRegexp)) { - return null; - } - - // & Parent Reference - if (ch === "&") { - stream.next(); - return "variable-3"; - } - - // Font family - if (stream.match(/^[A-Z][a-z0-9-]+/)) { - return "string"; - } - - // CSS rule - // NOTE: Some css selectors and property values have the same name - // (embed, menu, pre, progress, sub, table), - // so they will have the same color (.cm-atom). - if (stream.match(/[\w-]*/i)) { - - var word = stream.current().toLowerCase(); - - if(cssProperties[word] !== undefined) { - // CSS property - if(!stream.eol()) - return "property"; - else - return "variable-2"; - - } else if(cssValues[word] !== undefined) { - // CSS value - return "atom"; - - } else if(cssTypeSelectors[word] !== undefined) { - // CSS type selectors - indent(state); - return "tag"; - - } else if(word) { - // By default variable-2 - return "variable-2"; - } - } - - // Handle non-detected items - stream.next(); - return null; - - }; - - var tokenLexer = function(stream, state) { - - if (stream.sol()) { - state.indentCount = 0; - } - - var style = state.tokenizer(stream, state); - var current = stream.current(); - - if (stream.eol() && (current === "}" || current === ",")) { - dedent(state); - } - - if (style !== null) { - var startOfToken = stream.pos - current.length; - var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount); - - var newScopes = []; - - for (var i = 0; i < state.scopes.length; i++) { - var scope = state.scopes[i]; - - if (scope.offset <= withCurrentIndent) { - newScopes.push(scope); - } - } - - state.scopes = newScopes; - } - - return style; - }; - - return { - startState: function() { - return { - tokenizer: tokenBase, - scopes: [{offset: 0, type: 'styl'}] - }; - }, - - token: function(stream, state) { - var style = tokenLexer(stream, state); - state.lastToken = { style: style, content: stream.current() }; - return style; - }, - - indent: function(state) { - return state.scopes[0].offset; - }, - - lineComment: "//", - fold: "indent" - - }; - - function urlTokens(stream, state) { - var ch = stream.peek(); - - if (ch === ")") { - stream.next(); - state.tokenizer = tokenBase; - return "operator"; - } else if (ch === "(") { - stream.next(); - stream.eatSpace(); - - return "operator"; - } else if (ch === "'" || ch === '"') { - state.tokenizer = buildStringTokenizer(stream.next()); - return "string"; - } else { - state.tokenizer = buildStringTokenizer(")", false); - return "string"; - } - } - - function multilineComment(stream, state) { - if (stream.skipTo("*/")) { - stream.next(); - stream.next(); - state.tokenizer = tokenBase; - } else { - stream.next(); - } - return "comment"; - } - - function buildStringTokenizer(quote, greedy) { - - if(greedy == null) { - greedy = true; - } - - function stringTokenizer(stream, state) { - var nextChar = stream.next(); - var peekChar = stream.peek(); - var previousChar = stream.string.charAt(stream.pos-2); - - var endingString = ((nextChar !== "\\" && peekChar === quote) || - (nextChar === quote && previousChar !== "\\")); - - if (endingString) { - if (nextChar !== quote && greedy) { - stream.next(); - } - state.tokenizer = tokenBase; - return "string"; - } else if (nextChar === "#" && peekChar === "{") { - state.tokenizer = buildInterpolationTokenizer(stringTokenizer); - stream.next(); - return "operator"; - } else { - return "string"; - } - } - - return stringTokenizer; - } - - function buildInterpolationTokenizer(currentTokenizer) { - return function(stream, state) { - if (stream.peek() === "}") { - stream.next(); - state.tokenizer = currentTokenizer; - return "operator"; - } else { - return tokenBase(stream, state); - } - }; - } - - function indent(state) { - if (state.indentCount == 0) { - state.indentCount++; - var lastScopeOffset = state.scopes[0].offset; - var currentOffset = lastScopeOffset + config.indentUnit; - state.scopes.unshift({ offset:currentOffset }); - } - } - - function dedent(state) { - if (state.scopes.length == 1) { return true; } - state.scopes.shift(); - } - - }); - - // https://developer.mozilla.org/en-US/docs/Web/HTML/Element - var cssTypeSelectors_ = ["a","abbr","address","area","article","aside","audio", "b", "base","bdi","bdo","bgsound","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","keygen","label","legend","li","link","main","map","mark","marquee","menu","menuitem","meta","meter","nav","nobr","noframes","noscript","object","ol","optgroup","option","output","p","param","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr"]; - // https://github.com/csscomb/csscomb.js/blob/master/config/zen.json - var cssProperties_ = ["position","top","right","bottom","left","z-index","display","visibility","flex-direction","flex-order","flex-pack","float","clear","flex-align","overflow","overflow-x","overflow-y","overflow-scrolling","clip","box-sizing","margin","margin-top","margin-right","margin-bottom","margin-left","padding","padding-top","padding-right","padding-bottom","padding-left","min-width","min-height","max-width","max-height","width","height","outline","outline-width","outline-style","outline-color","outline-offset","border","border-spacing","border-collapse","border-width","border-style","border-color","border-top","border-top-width","border-top-style","border-top-color","border-right","border-right-width","border-right-style","border-right-color","border-bottom","border-bottom-width","border-bottom-style","border-bottom-color","border-left","border-left-width","border-left-style","border-left-color","border-radius","border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius","border-image","border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat","border-top-image","border-right-image","border-bottom-image","border-left-image","border-corner-image","border-top-left-image","border-top-right-image","border-bottom-right-image","border-bottom-left-image","background","filter:progid:DXImageTransform\\.Microsoft\\.AlphaImageLoader","background-color","background-image","background-attachment","background-position","background-position-x","background-position-y","background-clip","background-origin","background-size","background-repeat","box-decoration-break","box-shadow","color","table-layout","caption-side","empty-cells","list-style","list-style-position","list-style-type","list-style-image","quotes","content","counter-increment","counter-reset","writing-mode","vertical-align","text-align","text-align-last","text-decoration","text-emphasis","text-emphasis-position","text-emphasis-style","text-emphasis-color","text-indent","-ms-text-justify","text-justify","text-outline","text-transform","text-wrap","text-overflow","text-overflow-ellipsis","text-overflow-mode","text-size-adjust","text-shadow","white-space","word-spacing","word-wrap","word-break","tab-size","hyphens","letter-spacing","font","font-weight","font-style","font-variant","font-size-adjust","font-stretch","font-size","font-family","src","line-height","opacity","filter:\\\\\\\\'progid:DXImageTransform.Microsoft.Alpha","filter:progid:DXImageTransform.Microsoft.Alpha\\(Opacity","interpolation-mode","filter","resize","cursor","nav-index","nav-up","nav-right","nav-down","nav-left","transition","transition-delay","transition-timing-function","transition-duration","transition-property","transform","transform-origin","animation","animation-name","animation-duration","animation-play-state","animation-timing-function","animation-delay","animation-iteration-count","animation-direction","pointer-events","unicode-bidi","direction","columns","column-span","column-width","column-count","column-fill","column-gap","column-rule","column-rule-width","column-rule-style","column-rule-color","break-before","break-inside","break-after","page-break-before","page-break-inside","page-break-after","orphans","widows","zoom","max-zoom","min-zoom","user-zoom","orientation","text-rendering","speak","animation-fill-mode","backface-visibility","user-drag","user-select","appearance"]; - // https://github.com/codemirror/CodeMirror/blob/master/mode/css/css.js#L501 - var cssValues_ = ["above","absolute","activeborder","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","cambodian","capitalize","caps-lock-indicator","captiontext","caret","cell","center","checkbox","circle","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","contain","content","content-box","context-menu","continuous","copy","cover","crop","cross","crosshair","currentcolor","cursive","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ew-resize","expanded","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-table","inset","inside","intrinsic","invert","italic","justify","kannada","katakana","katakana-iroha","keep-all","khmer","landscape","lao","large","larger","left","level","lighter","line-through","linear","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scroll","scrollbar","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","single","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","telugu","text","text-bottom","text-top","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","x-large","x-small","xor","xx-large","xx-small","bicubic","optimizespeed","grayscale"]; - var cssColorValues_ = ["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"]; - var cssValuesWithBrackets_ = ["gradient","linear-gradient","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","cubic-bezier","translateX","translateY","translate3d","rotate3d","scale","scale3d","perspective","skewX"]; - - var wordOperators = ["in", "and", "or", "not", "is a", "is", "isnt", "defined", "if unless"], - commonKeywords = ["for", "if", "else", "unless", "return"], - commonAtoms = ["null", "true", "false", "href", "title", "type", "not-allowed", "readonly", "disabled"], - commonDef = ["@font-face", "@keyframes", "@media", "@viewport", "@page", "@host", "@supports", "@block", "@css"], - cssTypeSelectors = keySet(cssTypeSelectors_), - cssProperties = keySet(cssProperties_), - cssValues = keySet(cssValues_.concat(cssColorValues_)), - hintWords = wordOperators.concat(commonKeywords, - commonAtoms, - commonDef, - cssTypeSelectors_, - cssProperties_, - cssValues_, - cssValuesWithBrackets_, - cssColorValues_); - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); - }; - - function keySet(array) { - var keys = {}; - for (var i = 0; i < array.length; ++i) { - keys[array[i]] = true; - } - return keys; - }; - - CodeMirror.registerHelper("hintWords", "stylus", hintWords); - CodeMirror.defineMIME("text/x-styl", "stylus"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/tcl/index.html b/shared/html/libs/codemirror/5.0.0/mode/tcl/index.html deleted file mode 100644 index ce4ad34..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/tcl/index.html +++ /dev/null @@ -1,142 +0,0 @@ - - -CodeMirror: Tcl mode - - - - - - - - - - -
-

Tcl mode

-
- - -

MIME types defined: text/x-tcl.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/tcl/tcl.js b/shared/html/libs/codemirror/5.0.0/mode/tcl/tcl.js deleted file mode 100644 index 056accb..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/tcl/tcl.js +++ /dev/null @@ -1,147 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -//tcl mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("tcl", function() { - function parseWords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var keywords = parseWords("Tcl safe after append array auto_execok auto_import auto_load " + - "auto_mkindex auto_mkindex_old auto_qualify auto_reset bgerror " + - "binary break catch cd close concat continue dde eof encoding error " + - "eval exec exit expr fblocked fconfigure fcopy file fileevent filename " + - "filename flush for foreach format gets glob global history http if " + - "incr info interp join lappend lindex linsert list llength load lrange " + - "lreplace lsearch lset lsort memory msgcat namespace open package parray " + - "pid pkg::create pkg_mkIndex proc puts pwd re_syntax read regex regexp " + - "registry regsub rename resource return scan seek set socket source split " + - "string subst switch tcl_endOfWord tcl_findLibrary tcl_startOfNextWord " + - "tcl_wordBreakAfter tcl_startOfPreviousWord tcl_wordBreakBefore tcltest " + - "tclvars tell time trace unknown unset update uplevel upvar variable " + - "vwait"); - var functions = parseWords("if elseif else and not or eq ne in ni for foreach while switch"); - var isOperatorChar = /[+\-*&%=<>!?^\/\|]/; - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - function tokenBase(stream, state) { - var beforeParams = state.beforeParams; - state.beforeParams = false; - var ch = stream.next(); - if ((ch == '"' || ch == "'") && state.inParams) - return chain(stream, state, tokenString(ch)); - else if (/[\[\]{}\(\),;\.]/.test(ch)) { - if (ch == "(" && beforeParams) state.inParams = true; - else if (ch == ")") state.inParams = false; - return null; - } - else if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - else if (ch == "#" && stream.eat("*")) { - return chain(stream, state, tokenComment); - } - else if (ch == "#" && stream.match(/ *\[ *\[/)) { - return chain(stream, state, tokenUnparsed); - } - else if (ch == "#" && stream.eat("#")) { - stream.skipToEnd(); - return "comment"; - } - else if (ch == '"') { - stream.skipTo(/"/); - return "comment"; - } - else if (ch == "$") { - stream.eatWhile(/[$_a-z0-9A-Z\.{:]/); - stream.eatWhile(/}/); - state.beforeParams = true; - return "builtin"; - } - else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "comment"; - } - else { - stream.eatWhile(/[\w\$_{}\xa1-\uffff]/); - var word = stream.current().toLowerCase(); - if (keywords && keywords.propertyIsEnumerable(word)) - return "keyword"; - if (functions && functions.propertyIsEnumerable(word)) { - state.beforeParams = true; - return "keyword"; - } - return null; - } - } - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) { - end = true; - break; - } - escaped = !escaped && next == "\\"; - } - if (end) state.tokenize = tokenBase; - return "string"; - }; - } - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "#" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - function tokenUnparsed(stream, state) { - var maybeEnd = 0, ch; - while (ch = stream.next()) { - if (ch == "#" && maybeEnd == 2) { - state.tokenize = tokenBase; - break; - } - if (ch == "]") - maybeEnd++; - else if (ch != " ") - maybeEnd = 0; - } - return "meta"; - } - return { - startState: function() { - return { - tokenize: tokenBase, - beforeParams: false, - inParams: false - }; - }, - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - } - }; -}); -CodeMirror.defineMIME("text/x-tcl", "tcl"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/textile/index.html b/shared/html/libs/codemirror/5.0.0/mode/textile/index.html deleted file mode 100644 index 42b156b..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/textile/index.html +++ /dev/null @@ -1,191 +0,0 @@ - - -CodeMirror: Textile mode - - - - - - - - - -
-

Textile mode

-
- - -

MIME types defined: text/x-textile.

- -

Parsing/Highlighting Tests: normal, verbose.

- -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/textile/test.js b/shared/html/libs/codemirror/5.0.0/mode/textile/test.js deleted file mode 100644 index 49cdaf9..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/textile/test.js +++ /dev/null @@ -1,417 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({tabSize: 4}, 'textile'); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT('simpleParagraphs', - 'Some text.', - '', - 'Some more text.'); - - /* - * Phrase Modifiers - */ - - MT('em', - 'foo [em _bar_]'); - - MT('emBoogus', - 'code_mirror'); - - MT('strong', - 'foo [strong *bar*]'); - - MT('strongBogus', - '3 * 3 = 9'); - - MT('italic', - 'foo [em __bar__]'); - - MT('italicBogus', - 'code__mirror'); - - MT('bold', - 'foo [strong **bar**]'); - - MT('boldBogus', - '3 ** 3 = 27'); - - MT('simpleLink', - '[link "CodeMirror":http://codemirror.net]'); - - MT('referenceLink', - '[link "CodeMirror":code_mirror]', - 'Normal Text.', - '[link [[code_mirror]]http://codemirror.net]'); - - MT('footCite', - 'foo bar[qualifier [[1]]]'); - - MT('footCiteBogus', - 'foo bar[[1a2]]'); - - MT('special-characters', - 'Registered [tag (r)], ' + - 'Trademark [tag (tm)], and ' + - 'Copyright [tag (c)] 2008'); - - MT('cite', - "A book is [keyword ??The Count of Monte Cristo??] by Dumas."); - - MT('additionAndDeletion', - 'The news networks declared [negative -Al Gore-] ' + - '[positive +George W. Bush+] the winner in Florida.'); - - MT('subAndSup', - 'f(x, n) = log [builtin ~4~] x [builtin ^n^]'); - - MT('spanAndCode', - 'A [quote %span element%] and [atom @code element@]'); - - MT('spanBogus', - 'Percentage 25% is not a span.'); - - MT('citeBogus', - 'Question? is not a citation.'); - - MT('codeBogus', - 'user@example.com'); - - MT('subBogus', - '~username'); - - MT('supBogus', - 'foo ^ bar'); - - MT('deletionBogus', - '3 - 3 = 0'); - - MT('additionBogus', - '3 + 3 = 6'); - - MT('image', - 'An image: [string !http://www.example.com/image.png!]'); - - MT('imageWithAltText', - 'An image: [string !http://www.example.com/image.png (Alt Text)!]'); - - MT('imageWithUrl', - 'An image: [string !http://www.example.com/image.png!:http://www.example.com/]'); - - /* - * Headers - */ - - MT('h1', - '[header&header-1 h1. foo]'); - - MT('h2', - '[header&header-2 h2. foo]'); - - MT('h3', - '[header&header-3 h3. foo]'); - - MT('h4', - '[header&header-4 h4. foo]'); - - MT('h5', - '[header&header-5 h5. foo]'); - - MT('h6', - '[header&header-6 h6. foo]'); - - MT('h7Bogus', - 'h7. foo'); - - MT('multipleHeaders', - '[header&header-1 h1. Heading 1]', - '', - 'Some text.', - '', - '[header&header-2 h2. Heading 2]', - '', - 'More text.'); - - MT('h1inline', - '[header&header-1 h1. foo ][header&header-1&em _bar_][header&header-1 baz]'); - - /* - * Lists - */ - - MT('ul', - 'foo', - 'bar', - '', - '[variable-2 * foo]', - '[variable-2 * bar]'); - - MT('ulNoBlank', - 'foo', - 'bar', - '[variable-2 * foo]', - '[variable-2 * bar]'); - - MT('ol', - 'foo', - 'bar', - '', - '[variable-2 # foo]', - '[variable-2 # bar]'); - - MT('olNoBlank', - 'foo', - 'bar', - '[variable-2 # foo]', - '[variable-2 # bar]'); - - MT('ulFormatting', - '[variable-2 * ][variable-2&em _foo_][variable-2 bar]', - '[variable-2 * ][variable-2&strong *][variable-2&em&strong _foo_]' + - '[variable-2&strong *][variable-2 bar]', - '[variable-2 * ][variable-2&strong *foo*][variable-2 bar]'); - - MT('olFormatting', - '[variable-2 # ][variable-2&em _foo_][variable-2 bar]', - '[variable-2 # ][variable-2&strong *][variable-2&em&strong _foo_]' + - '[variable-2&strong *][variable-2 bar]', - '[variable-2 # ][variable-2&strong *foo*][variable-2 bar]'); - - MT('ulNested', - '[variable-2 * foo]', - '[variable-3 ** bar]', - '[keyword *** bar]', - '[variable-2 **** bar]', - '[variable-3 ** bar]'); - - MT('olNested', - '[variable-2 # foo]', - '[variable-3 ## bar]', - '[keyword ### bar]', - '[variable-2 #### bar]', - '[variable-3 ## bar]'); - - MT('ulNestedWithOl', - '[variable-2 * foo]', - '[variable-3 ## bar]', - '[keyword *** bar]', - '[variable-2 #### bar]', - '[variable-3 ** bar]'); - - MT('olNestedWithUl', - '[variable-2 # foo]', - '[variable-3 ** bar]', - '[keyword ### bar]', - '[variable-2 **** bar]', - '[variable-3 ## bar]'); - - MT('definitionList', - '[number - coffee := Hot ][number&em _and_][number black]', - '', - 'Normal text.'); - - MT('definitionListSpan', - '[number - coffee :=]', - '', - '[number Hot ][number&em _and_][number black =:]', - '', - 'Normal text.'); - - MT('boo', - '[number - dog := woof woof]', - '[number - cat := meow meow]', - '[number - whale :=]', - '[number Whale noises.]', - '', - '[number Also, ][number&em _splashing_][number . =:]'); - - /* - * Attributes - */ - - MT('divWithAttribute', - '[punctuation div][punctuation&attribute (#my-id)][punctuation . foo bar]'); - - MT('divWithAttributeAnd2emRightPadding', - '[punctuation div][punctuation&attribute (#my-id)((][punctuation . foo bar]'); - - MT('divWithClassAndId', - '[punctuation div][punctuation&attribute (my-class#my-id)][punctuation . foo bar]'); - - MT('paragraphWithCss', - 'p[attribute {color:red;}]. foo bar'); - - MT('paragraphNestedStyles', - 'p. [strong *foo ][strong&em _bar_][strong *]'); - - MT('paragraphWithLanguage', - 'p[attribute [[fr]]]. Parlez-vous français?'); - - MT('paragraphLeftAlign', - 'p[attribute <]. Left'); - - MT('paragraphRightAlign', - 'p[attribute >]. Right'); - - MT('paragraphRightAlign', - 'p[attribute =]. Center'); - - MT('paragraphJustified', - 'p[attribute <>]. Justified'); - - MT('paragraphWithLeftIndent1em', - 'p[attribute (]. Left'); - - MT('paragraphWithRightIndent1em', - 'p[attribute )]. Right'); - - MT('paragraphWithLeftIndent2em', - 'p[attribute ((]. Left'); - - MT('paragraphWithRightIndent2em', - 'p[attribute ))]. Right'); - - MT('paragraphWithLeftIndent3emRightIndent2em', - 'p[attribute ((())]. Right'); - - MT('divFormatting', - '[punctuation div. ][punctuation&strong *foo ]' + - '[punctuation&strong&em _bar_][punctuation&strong *]'); - - MT('phraseModifierAttributes', - 'p[attribute (my-class)]. This is a paragraph that has a class and' + - ' this [em _][em&attribute (#special-phrase)][em emphasized phrase_]' + - ' has an id.'); - - MT('linkWithClass', - '[link "(my-class). This is a link with class":http://redcloth.org]'); - - /* - * Layouts - */ - - MT('paragraphLayouts', - 'p. This is one paragraph.', - '', - 'p. This is another.'); - - MT('div', - '[punctuation div. foo bar]'); - - MT('pre', - '[operator pre. Text]'); - - MT('bq.', - '[bracket bq. foo bar]', - '', - 'Normal text.'); - - MT('footnote', - '[variable fn123. foo ][variable&strong *bar*]'); - - /* - * Spanning Layouts - */ - - MT('bq..ThenParagraph', - '[bracket bq.. foo bar]', - '', - '[bracket More quote.]', - 'p. Normal Text'); - - MT('bq..ThenH1', - '[bracket bq.. foo bar]', - '', - '[bracket More quote.]', - '[header&header-1 h1. Header Text]'); - - MT('bc..ThenParagraph', - '[atom bc.. # Some ruby code]', - '[atom obj = {foo: :bar}]', - '[atom puts obj]', - '', - '[atom obj[[:love]] = "*love*"]', - '[atom puts obj.love.upcase]', - '', - 'p. Normal text.'); - - MT('fn1..ThenParagraph', - '[variable fn1.. foo bar]', - '', - '[variable More.]', - 'p. Normal Text'); - - MT('pre..ThenParagraph', - '[operator pre.. foo bar]', - '', - '[operator More.]', - 'p. Normal Text'); - - /* - * Tables - */ - - MT('table', - '[variable-3&operator |_. name |_. age|]', - '[variable-3 |][variable-3&strong *Walter*][variable-3 | 5 |]', - '[variable-3 |Florence| 6 |]', - '', - 'p. Normal text.'); - - MT('tableWithAttributes', - '[variable-3&operator |_. name |_. age|]', - '[variable-3 |][variable-3&attribute /2.][variable-3 Jim |]', - '[variable-3 |][variable-3&attribute \\2{color: red}.][variable-3 Sam |]'); - - /* - * HTML - */ - - MT('html', - '[comment
]', - '[comment
]', - '', - '[header&header-1 h1. Welcome]', - '', - '[variable-2 * Item one]', - '[variable-2 * Item two]', - '', - '[comment Example]', - '', - '[comment
]', - '[comment
]'); - - MT('inlineHtml', - 'I can use HTML directly in my [comment Textile].'); - - /* - * No-Textile - */ - - MT('notextile', - '[string-2 notextile. *No* formatting]'); - - MT('notextileInline', - 'Use [string-2 ==*asterisks*==] for [strong *strong*] text.'); - - MT('notextileWithPre', - '[operator pre. *No* formatting]'); - - MT('notextileWithSpanningPre', - '[operator pre.. *No* formatting]', - '', - '[operator *No* formatting]'); - - /* Only toggling phrases between non-word chars. */ - - MT('phrase-in-word', - 'foo_bar_baz'); - - MT('phrase-non-word', - '[negative -x-] aaa-bbb ccc-ddd [negative -eee-] fff [negative -ggg-]'); - - MT('phrase-lone-dash', - 'foo - bar - baz'); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/textile/textile.js b/shared/html/libs/codemirror/5.0.0/mode/textile/textile.js deleted file mode 100644 index a6f7576..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/textile/textile.js +++ /dev/null @@ -1,469 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") { // CommonJS - mod(require("../../lib/codemirror")); - } else if (typeof define == "function" && define.amd) { // AMD - define(["../../lib/codemirror"], mod); - } else { // Plain browser env - mod(CodeMirror); - } -})(function(CodeMirror) { - "use strict"; - - var TOKEN_STYLES = { - addition: "positive", - attributes: "attribute", - bold: "strong", - cite: "keyword", - code: "atom", - definitionList: "number", - deletion: "negative", - div: "punctuation", - em: "em", - footnote: "variable", - footCite: "qualifier", - header: "header", - html: "comment", - image: "string", - italic: "em", - link: "link", - linkDefinition: "link", - list1: "variable-2", - list2: "variable-3", - list3: "keyword", - notextile: "string-2", - pre: "operator", - p: "property", - quote: "bracket", - span: "quote", - specialChar: "tag", - strong: "strong", - sub: "builtin", - sup: "builtin", - table: "variable-3", - tableHeading: "operator" - }; - - function startNewLine(stream, state) { - state.mode = Modes.newLayout; - state.tableHeading = false; - - if (state.layoutType === "definitionList" && state.spanningLayout && - stream.match(RE("definitionListEnd"), false)) - state.spanningLayout = false; - } - - function handlePhraseModifier(stream, state, ch) { - if (ch === "_") { - if (stream.eat("_")) - return togglePhraseModifier(stream, state, "italic", /__/, 2); - else - return togglePhraseModifier(stream, state, "em", /_/, 1); - } - - if (ch === "*") { - if (stream.eat("*")) { - return togglePhraseModifier(stream, state, "bold", /\*\*/, 2); - } - return togglePhraseModifier(stream, state, "strong", /\*/, 1); - } - - if (ch === "[") { - if (stream.match(/\d+\]/)) state.footCite = true; - return tokenStyles(state); - } - - if (ch === "(") { - var spec = stream.match(/^(r|tm|c)\)/); - if (spec) - return tokenStylesWith(state, TOKEN_STYLES.specialChar); - } - - if (ch === "<" && stream.match(/(\w+)[^>]+>[^<]+<\/\1>/)) - return tokenStylesWith(state, TOKEN_STYLES.html); - - if (ch === "?" && stream.eat("?")) - return togglePhraseModifier(stream, state, "cite", /\?\?/, 2); - - if (ch === "=" && stream.eat("=")) - return togglePhraseModifier(stream, state, "notextile", /==/, 2); - - if (ch === "-" && !stream.eat("-")) - return togglePhraseModifier(stream, state, "deletion", /-/, 1); - - if (ch === "+") - return togglePhraseModifier(stream, state, "addition", /\+/, 1); - - if (ch === "~") - return togglePhraseModifier(stream, state, "sub", /~/, 1); - - if (ch === "^") - return togglePhraseModifier(stream, state, "sup", /\^/, 1); - - if (ch === "%") - return togglePhraseModifier(stream, state, "span", /%/, 1); - - if (ch === "@") - return togglePhraseModifier(stream, state, "code", /@/, 1); - - if (ch === "!") { - var type = togglePhraseModifier(stream, state, "image", /(?:\([^\)]+\))?!/, 1); - stream.match(/^:\S+/); // optional Url portion - return type; - } - return tokenStyles(state); - } - - function togglePhraseModifier(stream, state, phraseModifier, closeRE, openSize) { - var charBefore = stream.pos > openSize ? stream.string.charAt(stream.pos - openSize - 1) : null; - var charAfter = stream.peek(); - if (state[phraseModifier]) { - if ((!charAfter || /\W/.test(charAfter)) && charBefore && /\S/.test(charBefore)) { - var type = tokenStyles(state); - state[phraseModifier] = false; - return type; - } - } else if ((!charBefore || /\W/.test(charBefore)) && charAfter && /\S/.test(charAfter) && - stream.match(new RegExp("^.*\\S" + closeRE.source + "(?:\\W|$)"), false)) { - state[phraseModifier] = true; - state.mode = Modes.attributes; - } - return tokenStyles(state); - }; - - function tokenStyles(state) { - var disabled = textileDisabled(state); - if (disabled) return disabled; - - var styles = []; - if (state.layoutType) styles.push(TOKEN_STYLES[state.layoutType]); - - styles = styles.concat(activeStyles( - state, "addition", "bold", "cite", "code", "deletion", "em", "footCite", - "image", "italic", "link", "span", "strong", "sub", "sup", "table", "tableHeading")); - - if (state.layoutType === "header") - styles.push(TOKEN_STYLES.header + "-" + state.header); - - return styles.length ? styles.join(" ") : null; - } - - function textileDisabled(state) { - var type = state.layoutType; - - switch(type) { - case "notextile": - case "code": - case "pre": - return TOKEN_STYLES[type]; - default: - if (state.notextile) - return TOKEN_STYLES.notextile + (type ? (" " + TOKEN_STYLES[type]) : ""); - return null; - } - } - - function tokenStylesWith(state, extraStyles) { - var disabled = textileDisabled(state); - if (disabled) return disabled; - - var type = tokenStyles(state); - if (extraStyles) - return type ? (type + " " + extraStyles) : extraStyles; - else - return type; - } - - function activeStyles(state) { - var styles = []; - for (var i = 1; i < arguments.length; ++i) { - if (state[arguments[i]]) - styles.push(TOKEN_STYLES[arguments[i]]); - } - return styles; - } - - function blankLine(state) { - var spanningLayout = state.spanningLayout, type = state.layoutType; - - for (var key in state) if (state.hasOwnProperty(key)) - delete state[key]; - - state.mode = Modes.newLayout; - if (spanningLayout) { - state.layoutType = type; - state.spanningLayout = true; - } - } - - var REs = { - cache: {}, - single: { - bc: "bc", - bq: "bq", - definitionList: /- [^(?::=)]+:=+/, - definitionListEnd: /.*=:\s*$/, - div: "div", - drawTable: /\|.*\|/, - foot: /fn\d+/, - header: /h[1-6]/, - html: /\s*<(?:\/)?(\w+)(?:[^>]+)?>(?:[^<]+<\/\1>)?/, - link: /[^"]+":\S/, - linkDefinition: /\[[^\s\]]+\]\S+/, - list: /(?:#+|\*+)/, - notextile: "notextile", - para: "p", - pre: "pre", - table: "table", - tableCellAttributes: /[\/\\]\d+/, - tableHeading: /\|_\./, - tableText: /[^"_\*\[\(\?\+~\^%@|-]+/, - text: /[^!"_=\*\[\(<\?\+~\^%@-]+/ - }, - attributes: { - align: /(?:<>|<|>|=)/, - selector: /\([^\(][^\)]+\)/, - lang: /\[[^\[\]]+\]/, - pad: /(?:\(+|\)+){1,2}/, - css: /\{[^\}]+\}/ - }, - createRe: function(name) { - switch (name) { - case "drawTable": - return REs.makeRe("^", REs.single.drawTable, "$"); - case "html": - return REs.makeRe("^", REs.single.html, "(?:", REs.single.html, ")*", "$"); - case "linkDefinition": - return REs.makeRe("^", REs.single.linkDefinition, "$"); - case "listLayout": - return REs.makeRe("^", REs.single.list, RE("allAttributes"), "*\\s+"); - case "tableCellAttributes": - return REs.makeRe("^", REs.choiceRe(REs.single.tableCellAttributes, - RE("allAttributes")), "+\\."); - case "type": - return REs.makeRe("^", RE("allTypes")); - case "typeLayout": - return REs.makeRe("^", RE("allTypes"), RE("allAttributes"), - "*\\.\\.?", "(\\s+|$)"); - case "attributes": - return REs.makeRe("^", RE("allAttributes"), "+"); - - case "allTypes": - return REs.choiceRe(REs.single.div, REs.single.foot, - REs.single.header, REs.single.bc, REs.single.bq, - REs.single.notextile, REs.single.pre, REs.single.table, - REs.single.para); - - case "allAttributes": - return REs.choiceRe(REs.attributes.selector, REs.attributes.css, - REs.attributes.lang, REs.attributes.align, REs.attributes.pad); - - default: - return REs.makeRe("^", REs.single[name]); - } - }, - makeRe: function() { - var pattern = ""; - for (var i = 0; i < arguments.length; ++i) { - var arg = arguments[i]; - pattern += (typeof arg === "string") ? arg : arg.source; - } - return new RegExp(pattern); - }, - choiceRe: function() { - var parts = [arguments[0]]; - for (var i = 1; i < arguments.length; ++i) { - parts[i * 2 - 1] = "|"; - parts[i * 2] = arguments[i]; - } - - parts.unshift("(?:"); - parts.push(")"); - return REs.makeRe.apply(null, parts); - } - }; - - function RE(name) { - return (REs.cache[name] || (REs.cache[name] = REs.createRe(name))); - } - - var Modes = { - newLayout: function(stream, state) { - if (stream.match(RE("typeLayout"), false)) { - state.spanningLayout = false; - return (state.mode = Modes.blockType)(stream, state); - } - var newMode; - if (!textileDisabled(state)) { - if (stream.match(RE("listLayout"), false)) - newMode = Modes.list; - else if (stream.match(RE("drawTable"), false)) - newMode = Modes.table; - else if (stream.match(RE("linkDefinition"), false)) - newMode = Modes.linkDefinition; - else if (stream.match(RE("definitionList"))) - newMode = Modes.definitionList; - else if (stream.match(RE("html"), false)) - newMode = Modes.html; - } - return (state.mode = (newMode || Modes.text))(stream, state); - }, - - blockType: function(stream, state) { - var match, type; - state.layoutType = null; - - if (match = stream.match(RE("type"))) - type = match[0]; - else - return (state.mode = Modes.text)(stream, state); - - if (match = type.match(RE("header"))) { - state.layoutType = "header"; - state.header = parseInt(match[0][1]); - } else if (type.match(RE("bq"))) { - state.layoutType = "quote"; - } else if (type.match(RE("bc"))) { - state.layoutType = "code"; - } else if (type.match(RE("foot"))) { - state.layoutType = "footnote"; - } else if (type.match(RE("notextile"))) { - state.layoutType = "notextile"; - } else if (type.match(RE("pre"))) { - state.layoutType = "pre"; - } else if (type.match(RE("div"))) { - state.layoutType = "div"; - } else if (type.match(RE("table"))) { - state.layoutType = "table"; - } - - state.mode = Modes.attributes; - return tokenStyles(state); - }, - - text: function(stream, state) { - if (stream.match(RE("text"))) return tokenStyles(state); - - var ch = stream.next(); - if (ch === '"') - return (state.mode = Modes.link)(stream, state); - return handlePhraseModifier(stream, state, ch); - }, - - attributes: function(stream, state) { - state.mode = Modes.layoutLength; - - if (stream.match(RE("attributes"))) - return tokenStylesWith(state, TOKEN_STYLES.attributes); - else - return tokenStyles(state); - }, - - layoutLength: function(stream, state) { - if (stream.eat(".") && stream.eat(".")) - state.spanningLayout = true; - - state.mode = Modes.text; - return tokenStyles(state); - }, - - list: function(stream, state) { - var match = stream.match(RE("list")); - state.listDepth = match[0].length; - var listMod = (state.listDepth - 1) % 3; - if (!listMod) - state.layoutType = "list1"; - else if (listMod === 1) - state.layoutType = "list2"; - else - state.layoutType = "list3"; - - state.mode = Modes.attributes; - return tokenStyles(state); - }, - - link: function(stream, state) { - state.mode = Modes.text; - if (stream.match(RE("link"))) { - stream.match(/\S+/); - return tokenStylesWith(state, TOKEN_STYLES.link); - } - return tokenStyles(state); - }, - - linkDefinition: function(stream, state) { - stream.skipToEnd(); - return tokenStylesWith(state, TOKEN_STYLES.linkDefinition); - }, - - definitionList: function(stream, state) { - stream.match(RE("definitionList")); - - state.layoutType = "definitionList"; - - if (stream.match(/\s*$/)) - state.spanningLayout = true; - else - state.mode = Modes.attributes; - - return tokenStyles(state); - }, - - html: function(stream, state) { - stream.skipToEnd(); - return tokenStylesWith(state, TOKEN_STYLES.html); - }, - - table: function(stream, state) { - state.layoutType = "table"; - return (state.mode = Modes.tableCell)(stream, state); - }, - - tableCell: function(stream, state) { - if (stream.match(RE("tableHeading"))) - state.tableHeading = true; - else - stream.eat("|"); - - state.mode = Modes.tableCellAttributes; - return tokenStyles(state); - }, - - tableCellAttributes: function(stream, state) { - state.mode = Modes.tableText; - - if (stream.match(RE("tableCellAttributes"))) - return tokenStylesWith(state, TOKEN_STYLES.attributes); - else - return tokenStyles(state); - }, - - tableText: function(stream, state) { - if (stream.match(RE("tableText"))) - return tokenStyles(state); - - if (stream.peek() === "|") { // end of cell - state.mode = Modes.tableCell; - return tokenStyles(state); - } - return handlePhraseModifier(stream, state, stream.next()); - } - }; - - CodeMirror.defineMode("textile", function() { - return { - startState: function() { - return { mode: Modes.newLayout }; - }, - token: function(stream, state) { - if (stream.sol()) startNewLine(stream, state); - return state.mode(stream, state); - }, - blankLine: blankLine - }; - }); - - CodeMirror.defineMIME("text/x-textile", "textile"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/index.html b/shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/index.html deleted file mode 100644 index 77dd045..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/index.html +++ /dev/null @@ -1,154 +0,0 @@ - - -CodeMirror: TiddlyWiki mode - - - - - - - - - - - -
-

TiddlyWiki mode

- - -
- - - -

TiddlyWiki mode supports a single configuration.

- -

MIME types defined: text/x-tiddlywiki.

-
diff --git a/shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/tiddlywiki.css b/shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/tiddlywiki.css deleted file mode 100644 index 9a69b63..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/tiddlywiki.css +++ /dev/null @@ -1,14 +0,0 @@ -span.cm-underlined { - text-decoration: underline; -} -span.cm-strikethrough { - text-decoration: line-through; -} -span.cm-brace { - color: #170; - font-weight: bold; -} -span.cm-table { - color: blue; - font-weight: bold; -} diff --git a/shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/tiddlywiki.js b/shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/tiddlywiki.js deleted file mode 100644 index 88c9768..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/tiddlywiki/tiddlywiki.js +++ /dev/null @@ -1,369 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/*** - |''Name''|tiddlywiki.js| - |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror| - |''Author''|PMario| - |''Version''|0.1.7| - |''Status''|''stable''| - |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]| - |''Documentation''|http://codemirror.tiddlyspace.com/| - |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]| - |''CoreVersion''|2.5.0| - |''Requires''|codemirror.js| - |''Keywords''|syntax highlighting color code mirror codemirror| - ! Info - CoreVersion parameter is needed for TiddlyWiki only! -***/ -//{{{ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("tiddlywiki", function () { - // Tokenizer - var textwords = {}; - - var keywords = function () { - function kw(type) { - return { type: type, style: "macro"}; - } - return { - "allTags": kw('allTags'), "closeAll": kw('closeAll'), "list": kw('list'), - "newJournal": kw('newJournal'), "newTiddler": kw('newTiddler'), - "permaview": kw('permaview'), "saveChanges": kw('saveChanges'), - "search": kw('search'), "slider": kw('slider'), "tabs": kw('tabs'), - "tag": kw('tag'), "tagging": kw('tagging'), "tags": kw('tags'), - "tiddler": kw('tiddler'), "timeline": kw('timeline'), - "today": kw('today'), "version": kw('version'), "option": kw('option'), - - "with": kw('with'), - "filter": kw('filter') - }; - }(); - - var isSpaceName = /[\w_\-]/i, - reHR = /^\-\-\-\-+$/, //
- reWikiCommentStart = /^\/\*\*\*$/, // /*** - reWikiCommentStop = /^\*\*\*\/$/, // ***/ - reBlockQuote = /^<<<$/, - - reJsCodeStart = /^\/\/\{\{\{$/, // //{{{ js block start - reJsCodeStop = /^\/\/\}\}\}$/, // //}}} js stop - reXmlCodeStart = /^$/, // xml block start - reXmlCodeStop = /^$/, // xml stop - - reCodeBlockStart = /^\{\{\{$/, // {{{ TW text div block start - reCodeBlockStop = /^\}\}\}$/, // }}} TW text stop - - reUntilCodeStop = /.*?\}\}\}/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - - function ret(tp, style, cont) { - type = tp; - content = cont; - return style; - } - - function jsTokenBase(stream, state) { - var sol = stream.sol(), ch; - - state.block = false; // indicates the start of a code block. - - ch = stream.peek(); // don't eat, to make matching simpler - - // check start of blocks - if (sol && /[<\/\*{}\-]/.test(ch)) { - if (stream.match(reCodeBlockStart)) { - state.block = true; - return chain(stream, state, twTokenCode); - } - if (stream.match(reBlockQuote)) { - return ret('quote', 'quote'); - } - if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) { - return ret('code', 'comment'); - } - if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) { - return ret('code', 'comment'); - } - if (stream.match(reHR)) { - return ret('hr', 'hr'); - } - } // sol - ch = stream.next(); - - if (sol && /[\/\*!#;:>|]/.test(ch)) { - if (ch == "!") { // tw header - stream.skipToEnd(); - return ret("header", "header"); - } - if (ch == "*") { // tw list - stream.eatWhile('*'); - return ret("list", "comment"); - } - if (ch == "#") { // tw numbered list - stream.eatWhile('#'); - return ret("list", "comment"); - } - if (ch == ";") { // definition list, term - stream.eatWhile(';'); - return ret("list", "comment"); - } - if (ch == ":") { // definition list, description - stream.eatWhile(':'); - return ret("list", "comment"); - } - if (ch == ">") { // single line quote - stream.eatWhile(">"); - return ret("quote", "quote"); - } - if (ch == '|') { - return ret('table', 'header'); - } - } - - if (ch == '{' && stream.match(/\{\{/)) { - return chain(stream, state, twTokenCode); - } - - // rudimentary html:// file:// link matching. TW knows much more ... - if (/[hf]/i.test(ch)) { - if (/[ti]/i.test(stream.peek()) && stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i)) { - return ret("link", "link"); - } - } - // just a little string indicator, don't want to have the whole string covered - if (ch == '"') { - return ret('string', 'string'); - } - if (ch == '~') { // _no_ CamelCase indicator should be bold - return ret('text', 'brace'); - } - if (/[\[\]]/.test(ch)) { // check for [[..]] - if (stream.peek() == ch) { - stream.next(); - return ret('brace', 'brace'); - } - } - if (ch == "@") { // check for space link. TODO fix @@...@@ highlighting - stream.eatWhile(isSpaceName); - return ret("link", "link"); - } - if (/\d/.test(ch)) { // numbers - stream.eatWhile(/\d/); - return ret("number", "number"); - } - if (ch == "/") { // tw invisible comment - if (stream.eat("%")) { - return chain(stream, state, twTokenComment); - } - else if (stream.eat("/")) { // - return chain(stream, state, twTokenEm); - } - } - if (ch == "_") { // tw underline - if (stream.eat("_")) { - return chain(stream, state, twTokenUnderline); - } - } - // strikethrough and mdash handling - if (ch == "-") { - if (stream.eat("-")) { - // if strikethrough looks ugly, change CSS. - if (stream.peek() != ' ') - return chain(stream, state, twTokenStrike); - // mdash - if (stream.peek() == ' ') - return ret('text', 'brace'); - } - } - if (ch == "'") { // tw bold - if (stream.eat("'")) { - return chain(stream, state, twTokenStrong); - } - } - if (ch == "<") { // tw macro - if (stream.eat("<")) { - return chain(stream, state, twTokenMacro); - } - } - else { - return ret(ch); - } - - // core macro handling - stream.eatWhile(/[\w\$_]/); - var word = stream.current(), - known = textwords.propertyIsEnumerable(word) && textwords[word]; - - return known ? ret(known.type, known.style, word) : ret("text", null, word); - - } // jsTokenBase() - - // tw invisible comment - function twTokenComment(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "%"); - } - return ret("comment", "comment"); - } - - // tw strong / bold - function twTokenStrong(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "'" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "'"); - } - return ret("text", "strong"); - } - - // tw code - function twTokenCode(stream, state) { - var ch, sb = state.block; - - if (sb && stream.current()) { - return ret("code", "comment"); - } - - if (!sb && stream.match(reUntilCodeStop)) { - state.tokenize = jsTokenBase; - return ret("code", "comment"); - } - - if (sb && stream.sol() && stream.match(reCodeBlockStop)) { - state.tokenize = jsTokenBase; - return ret("code", "comment"); - } - - ch = stream.next(); - return (sb) ? ret("code", "comment") : ret("code", "comment"); - } - - // tw em / italic - function twTokenEm(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "/"); - } - return ret("text", "em"); - } - - // tw underlined text - function twTokenUnderline(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "_" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "_"); - } - return ret("text", "underlined"); - } - - // tw strike through text looks ugly - // change CSS if needed - function twTokenStrike(stream, state) { - var maybeEnd = false, ch; - - while (ch = stream.next()) { - if (ch == "-" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "-"); - } - return ret("text", "strikethrough"); - } - - // macro - function twTokenMacro(stream, state) { - var ch, word, known; - - if (stream.current() == '<<') { - return ret('brace', 'macro'); - } - - ch = stream.next(); - if (!ch) { - state.tokenize = jsTokenBase; - return ret(ch); - } - if (ch == ">") { - if (stream.peek() == '>') { - stream.next(); - state.tokenize = jsTokenBase; - return ret("brace", "macro"); - } - } - - stream.eatWhile(/[\w\$_]/); - word = stream.current(); - known = keywords.propertyIsEnumerable(word) && keywords[word]; - - if (known) { - return ret(known.type, known.style, word); - } - else { - return ret("macro", null, word); - } - } - - // Interface - return { - startState: function () { - return { - tokenize: jsTokenBase, - indented: 0, - level: 0 - }; - }, - - token: function (stream, state) { - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - return style; - }, - - electricChars: "" - }; -}); - -CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki"); -}); - -//}}} diff --git a/shared/html/libs/codemirror/5.0.0/mode/tiki/index.html b/shared/html/libs/codemirror/5.0.0/mode/tiki/index.html deleted file mode 100644 index 091c5fb..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/tiki/index.html +++ /dev/null @@ -1,95 +0,0 @@ - - -CodeMirror: Tiki wiki mode - - - - - - - - - - -
-

Tiki wiki mode

- - -
- - - -
diff --git a/shared/html/libs/codemirror/5.0.0/mode/tiki/tiki.css b/shared/html/libs/codemirror/5.0.0/mode/tiki/tiki.css deleted file mode 100644 index 0dbc3ea..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/tiki/tiki.css +++ /dev/null @@ -1,26 +0,0 @@ -.cm-tw-syntaxerror { - color: #FFF; - background-color: #900; -} - -.cm-tw-deleted { - text-decoration: line-through; -} - -.cm-tw-header5 { - font-weight: bold; -} -.cm-tw-listitem:first-child { /*Added first child to fix duplicate padding when highlighting*/ - padding-left: 10px; -} - -.cm-tw-box { - border-top-width: 0px ! important; - border-style: solid; - border-width: 1px; - border-color: inherit; -} - -.cm-tw-underline { - text-decoration: underline; -} \ No newline at end of file diff --git a/shared/html/libs/codemirror/5.0.0/mode/tiki/tiki.js b/shared/html/libs/codemirror/5.0.0/mode/tiki/tiki.js deleted file mode 100644 index c90aac9..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/tiki/tiki.js +++ /dev/null @@ -1,323 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('tiki', function(config) { - function inBlock(style, terminator, returnTokenizer) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.match(terminator)) { - state.tokenize = inText; - break; - } - stream.next(); - } - - if (returnTokenizer) state.tokenize = returnTokenizer; - - return style; - }; - } - - function inLine(style) { - return function(stream, state) { - while(!stream.eol()) { - stream.next(); - } - state.tokenize = inText; - return style; - }; - } - - function inText(stream, state) { - function chain(parser) { - state.tokenize = parser; - return parser(stream, state); - } - - var sol = stream.sol(); - var ch = stream.next(); - - //non start of line - switch (ch) { //switch is generally much faster than if, so it is used here - case "{": //plugin - stream.eat("/"); - stream.eatSpace(); - var tagName = ""; - var c; - while ((c = stream.eat(/[^\s\u00a0=\"\'\/?(}]/))) tagName += c; - state.tokenize = inPlugin; - return "tag"; - break; - case "_": //bold - if (stream.eat("_")) { - return chain(inBlock("strong", "__", inText)); - } - break; - case "'": //italics - if (stream.eat("'")) { - // Italic text - return chain(inBlock("em", "''", inText)); - } - break; - case "(":// Wiki Link - if (stream.eat("(")) { - return chain(inBlock("variable-2", "))", inText)); - } - break; - case "[":// Weblink - return chain(inBlock("variable-3", "]", inText)); - break; - case "|": //table - if (stream.eat("|")) { - return chain(inBlock("comment", "||")); - } - break; - case "-": - if (stream.eat("=")) {//titleBar - return chain(inBlock("header string", "=-", inText)); - } else if (stream.eat("-")) {//deleted - return chain(inBlock("error tw-deleted", "--", inText)); - } - break; - case "=": //underline - if (stream.match("==")) { - return chain(inBlock("tw-underline", "===", inText)); - } - break; - case ":": - if (stream.eat(":")) { - return chain(inBlock("comment", "::")); - } - break; - case "^": //box - return chain(inBlock("tw-box", "^")); - break; - case "~": //np - if (stream.match("np~")) { - return chain(inBlock("meta", "~/np~")); - } - break; - } - - //start of line types - if (sol) { - switch (ch) { - case "!": //header at start of line - if (stream.match('!!!!!')) { - return chain(inLine("header string")); - } else if (stream.match('!!!!')) { - return chain(inLine("header string")); - } else if (stream.match('!!!')) { - return chain(inLine("header string")); - } else if (stream.match('!!')) { - return chain(inLine("header string")); - } else { - return chain(inLine("header string")); - } - break; - case "*": //unordered list line item, or
  • at start of line - case "#": //ordered list line item, or
  • at start of line - case "+": //ordered list line item, or
  • at start of line - return chain(inLine("tw-listitem bracket")); - break; - } - } - - //stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki - return null; - } - - var indentUnit = config.indentUnit; - - // Return variables for tokenizers - var pluginName, type; - function inPlugin(stream, state) { - var ch = stream.next(); - var peek = stream.peek(); - - if (ch == "}") { - state.tokenize = inText; - //type = ch == ")" ? "endPlugin" : "selfclosePlugin"; inPlugin - return "tag"; - } else if (ch == "(" || ch == ")") { - return "bracket"; - } else if (ch == "=") { - type = "equals"; - - if (peek == ">") { - ch = stream.next(); - peek = stream.peek(); - } - - //here we detect values directly after equal character with no quotes - if (!/[\'\"]/.test(peek)) { - state.tokenize = inAttributeNoQuote(); - } - //end detect values - - return "operator"; - } else if (/[\'\"]/.test(ch)) { - state.tokenize = inAttribute(ch); - return state.tokenize(stream, state); - } else { - stream.eatWhile(/[^\s\u00a0=\"\'\/?]/); - return "keyword"; - } - } - - function inAttribute(quote) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.next() == quote) { - state.tokenize = inPlugin; - break; - } - } - return "string"; - }; - } - - function inAttributeNoQuote() { - return function(stream, state) { - while (!stream.eol()) { - var ch = stream.next(); - var peek = stream.peek(); - if (ch == " " || ch == "," || /[ )}]/.test(peek)) { - state.tokenize = inPlugin; - break; - } - } - return "string"; -}; - } - -var curState, setStyle; -function pass() { - for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]); -} - -function cont() { - pass.apply(null, arguments); - return true; -} - -function pushContext(pluginName, startOfLine) { - var noIndent = curState.context && curState.context.noIndent; - curState.context = { - prev: curState.context, - pluginName: pluginName, - indent: curState.indented, - startOfLine: startOfLine, - noIndent: noIndent - }; -} - -function popContext() { - if (curState.context) curState.context = curState.context.prev; -} - -function element(type) { - if (type == "openPlugin") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));} - else if (type == "closePlugin") { - var err = false; - if (curState.context) { - err = curState.context.pluginName != pluginName; - popContext(); - } else { - err = true; - } - if (err) setStyle = "error"; - return cont(endcloseplugin(err)); - } - else if (type == "string") { - if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata"); - if (curState.tokenize == inText) popContext(); - return cont(); - } - else return cont(); -} - -function endplugin(startOfLine) { - return function(type) { - if ( - type == "selfclosePlugin" || - type == "endPlugin" - ) - return cont(); - if (type == "endPlugin") {pushContext(curState.pluginName, startOfLine); return cont();} - return cont(); - }; -} - -function endcloseplugin(err) { - return function(type) { - if (err) setStyle = "error"; - if (type == "endPlugin") return cont(); - return pass(); - }; -} - -function attributes(type) { - if (type == "keyword") {setStyle = "attribute"; return cont(attributes);} - if (type == "equals") return cont(attvalue, attributes); - return pass(); -} -function attvalue(type) { - if (type == "keyword") {setStyle = "string"; return cont();} - if (type == "string") return cont(attvaluemaybe); - return pass(); -} -function attvaluemaybe(type) { - if (type == "string") return cont(attvaluemaybe); - else return pass(); -} -return { - startState: function() { - return {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null}; - }, - token: function(stream, state) { - if (stream.sol()) { - state.startOfLine = true; - state.indented = stream.indentation(); - } - if (stream.eatSpace()) return null; - - setStyle = type = pluginName = null; - var style = state.tokenize(stream, state); - if ((style || type) && style != "comment") { - curState = state; - while (true) { - var comb = state.cc.pop() || element; - if (comb(type || style)) break; - } - } - state.startOfLine = false; - return setStyle || style; - }, - indent: function(state, textAfter) { - var context = state.context; - if (context && context.noIndent) return 0; - if (context && /^{\//.test(textAfter)) - context = context.prev; - while (context && !context.startOfLine) - context = context.prev; - if (context) return context.indent + indentUnit; - else return 0; - }, - electricChars: "/" - }; -}); - -CodeMirror.defineMIME("text/tiki", "tiki"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/toml/index.html b/shared/html/libs/codemirror/5.0.0/mode/toml/index.html deleted file mode 100644 index 90a2a02..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/toml/index.html +++ /dev/null @@ -1,73 +0,0 @@ - - -CodeMirror: TOML Mode - - - - - - - - - -
    -

    TOML Mode

    -
    - -

    The TOML Mode

    -

    Created by Forbes Lindesay.

    -

    MIME type defined: text/x-toml.

    -
    diff --git a/shared/html/libs/codemirror/5.0.0/mode/toml/toml.js b/shared/html/libs/codemirror/5.0.0/mode/toml/toml.js deleted file mode 100644 index baeca15..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/toml/toml.js +++ /dev/null @@ -1,88 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("toml", function () { - return { - startState: function () { - return { - inString: false, - stringType: "", - lhs: true, - inArray: 0 - }; - }, - token: function (stream, state) { - //check for state changes - if (!state.inString && ((stream.peek() == '"') || (stream.peek() == "'"))) { - state.stringType = stream.peek(); - stream.next(); // Skip quote - state.inString = true; // Update state - } - if (stream.sol() && state.inArray === 0) { - state.lhs = true; - } - //return state - if (state.inString) { - while (state.inString && !stream.eol()) { - if (stream.peek() === state.stringType) { - stream.next(); // Skip quote - state.inString = false; // Clear flag - } else if (stream.peek() === '\\') { - stream.next(); - stream.next(); - } else { - stream.match(/^.[^\\\"\']*/); - } - } - return state.lhs ? "property string" : "string"; // Token style - } else if (state.inArray && stream.peek() === ']') { - stream.next(); - state.inArray--; - return 'bracket'; - } else if (state.lhs && stream.peek() === '[' && stream.skipTo(']')) { - stream.next();//skip closing ] - // array of objects has an extra open & close [] - if (stream.peek() === ']') stream.next(); - return "atom"; - } else if (stream.peek() === "#") { - stream.skipToEnd(); - return "comment"; - } else if (stream.eatSpace()) { - return null; - } else if (state.lhs && stream.eatWhile(function (c) { return c != '=' && c != ' '; })) { - return "property"; - } else if (state.lhs && stream.peek() === "=") { - stream.next(); - state.lhs = false; - return null; - } else if (!state.lhs && stream.match(/^\d\d\d\d[\d\-\:\.T]*Z/)) { - return 'atom'; //date - } else if (!state.lhs && (stream.match('true') || stream.match('false'))) { - return 'atom'; - } else if (!state.lhs && stream.peek() === '[') { - state.inArray++; - stream.next(); - return 'bracket'; - } else if (!state.lhs && stream.match(/^\-?\d+(?:\.\d+)?/)) { - return 'number'; - } else if (!stream.eatSpace()) { - stream.next(); - } - return null; - } - }; -}); - -CodeMirror.defineMIME('text/x-toml', 'toml'); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/tornado/index.html b/shared/html/libs/codemirror/5.0.0/mode/tornado/index.html deleted file mode 100644 index 8ee7ef5..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/tornado/index.html +++ /dev/null @@ -1,63 +0,0 @@ - - -CodeMirror: Tornado template mode - - - - - - - - - - - - -
    -

    Tornado template mode

    -
    - - - -

    Mode for HTML with embedded Tornado template markup.

    - -

    MIME types defined: text/x-tornado

    -
    diff --git a/shared/html/libs/codemirror/5.0.0/mode/tornado/tornado.js b/shared/html/libs/codemirror/5.0.0/mode/tornado/tornado.js deleted file mode 100644 index dbfbc34..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/tornado/tornado.js +++ /dev/null @@ -1,68 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), - require("../../addon/mode/overlay")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", - "../../addon/mode/overlay"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("tornado:inner", function() { - var keywords = ["and","as","assert","autoescape","block","break","class","comment","context", - "continue","datetime","def","del","elif","else","end","escape","except", - "exec","extends","false","finally","for","from","global","if","import","in", - "include","is","json_encode","lambda","length","linkify","load","module", - "none","not","or","pass","print","put","raise","raw","return","self","set", - "squeeze","super","true","try","url_escape","while","with","without","xhtml_escape","yield"]; - keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b"); - - function tokenBase (stream, state) { - stream.eatWhile(/[^\{]/); - var ch = stream.next(); - if (ch == "{") { - if (ch = stream.eat(/\{|%|#/)) { - state.tokenize = inTag(ch); - return "tag"; - } - } - } - function inTag (close) { - if (close == "{") { - close = "}"; - } - return function (stream, state) { - var ch = stream.next(); - if ((ch == close) && stream.eat("}")) { - state.tokenize = tokenBase; - return "tag"; - } - if (stream.match(keywords)) { - return "keyword"; - } - return close == "#" ? "comment" : "string"; - }; - } - return { - startState: function () { - return {tokenize: tokenBase}; - }, - token: function (stream, state) { - return state.tokenize(stream, state); - } - }; - }); - - CodeMirror.defineMode("tornado", function(config) { - var htmlBase = CodeMirror.getMode(config, "text/html"); - var tornadoInner = CodeMirror.getMode(config, "tornado:inner"); - return CodeMirror.overlayMode(htmlBase, tornadoInner); - }); - - CodeMirror.defineMIME("text/x-tornado", "tornado"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/turtle/index.html b/shared/html/libs/codemirror/5.0.0/mode/turtle/index.html deleted file mode 100644 index a4962b6..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/turtle/index.html +++ /dev/null @@ -1,50 +0,0 @@ - - -CodeMirror: Turtle mode - - - - - - - - - -
    -

    Turtle mode

    -
    - - -

    MIME types defined: text/turtle.

    - -
    diff --git a/shared/html/libs/codemirror/5.0.0/mode/turtle/turtle.js b/shared/html/libs/codemirror/5.0.0/mode/turtle/turtle.js deleted file mode 100644 index 0988f0a..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/turtle/turtle.js +++ /dev/null @@ -1,162 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("turtle", function(config) { - var indentUnit = config.indentUnit; - var curPunc; - - function wordRegexp(words) { - return new RegExp("^(?:" + words.join("|") + ")$", "i"); - } - var ops = wordRegexp([]); - var keywords = wordRegexp(["@prefix", "@base", "a"]); - var operatorChars = /[*+\-<>=&|]/; - - function tokenBase(stream, state) { - var ch = stream.next(); - curPunc = null; - if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) { - stream.match(/^[^\s\u00a0>]*>?/); - return "atom"; - } - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenLiteral(ch); - return state.tokenize(stream, state); - } - else if (/[{}\(\),\.;\[\]]/.test(ch)) { - curPunc = ch; - return null; - } - else if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - else if (operatorChars.test(ch)) { - stream.eatWhile(operatorChars); - return null; - } - else if (ch == ":") { - return "operator"; - } else { - stream.eatWhile(/[_\w\d]/); - if(stream.peek() == ":") { - return "variable-3"; - } else { - var word = stream.current(); - - if(keywords.test(word)) { - return "meta"; - } - - if(ch >= "A" && ch <= "Z") { - return "comment"; - } else { - return "keyword"; - } - } - var word = stream.current(); - if (ops.test(word)) - return null; - else if (keywords.test(word)) - return "meta"; - else - return "variable"; - } - } - - function tokenLiteral(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && ch == "\\"; - } - return "string"; - }; - } - - function pushContext(state, type, col) { - state.context = {prev: state.context, indent: state.indent, col: col, type: type}; - } - function popContext(state) { - state.indent = state.context.indent; - state.context = state.context.prev; - } - - return { - startState: function() { - return {tokenize: tokenBase, - context: null, - indent: 0, - col: 0}; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (state.context && state.context.align == null) state.context.align = false; - state.indent = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - - if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") { - state.context.align = true; - } - - if (curPunc == "(") pushContext(state, ")", stream.column()); - else if (curPunc == "[") pushContext(state, "]", stream.column()); - else if (curPunc == "{") pushContext(state, "}", stream.column()); - else if (/[\]\}\)]/.test(curPunc)) { - while (state.context && state.context.type == "pattern") popContext(state); - if (state.context && curPunc == state.context.type) popContext(state); - } - else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state); - else if (/atom|string|variable/.test(style) && state.context) { - if (/[\}\]]/.test(state.context.type)) - pushContext(state, "pattern", stream.column()); - else if (state.context.type == "pattern" && !state.context.align) { - state.context.align = true; - state.context.col = stream.column(); - } - } - - return style; - }, - - indent: function(state, textAfter) { - var firstChar = textAfter && textAfter.charAt(0); - var context = state.context; - if (/[\]\}]/.test(firstChar)) - while (context && context.type == "pattern") context = context.prev; - - var closing = context && firstChar == context.type; - if (!context) - return 0; - else if (context.type == "pattern") - return context.col; - else if (context.align) - return context.col + (closing ? 0 : 1); - else - return context.indent + (closing ? 0 : indentUnit); - }, - - lineComment: "#" - }; -}); - -CodeMirror.defineMIME("text/turtle", "turtle"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/vb/index.html b/shared/html/libs/codemirror/5.0.0/mode/vb/index.html deleted file mode 100644 index adcc44f..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/vb/index.html +++ /dev/null @@ -1,102 +0,0 @@ - - -CodeMirror: VB.NET mode - - - - - - - - - - - -
    -

    VB.NET mode

    - - - -
    - -
    -
    
    -  

    MIME type defined: text/x-vb.

    - -
    diff --git a/shared/html/libs/codemirror/5.0.0/mode/vb/vb.js b/shared/html/libs/codemirror/5.0.0/mode/vb/vb.js deleted file mode 100644 index 902203e..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/vb/vb.js +++ /dev/null @@ -1,274 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("vb", function(conf, parserConf) { - var ERRORCLASS = 'error'; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b", "i"); - } - - var singleOperators = new RegExp("^[\\+\\-\\*/%&\\\\|\\^~<>!]"); - var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]'); - var doubleOperators = new RegExp("^((==)|(<>)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))"); - var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))"); - var tripleDelimiters = new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))"); - var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*"); - - var openingKeywords = ['class','module', 'sub','enum','select','while','if','function', 'get','set','property', 'try']; - var middleKeywords = ['else','elseif','case', 'catch']; - var endKeywords = ['next','loop']; - - var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'in']); - var commonkeywords = ['as', 'dim', 'break', 'continue','optional', 'then', 'until', - 'goto', 'byval','byref','new','handles','property', 'return', - 'const','private', 'protected', 'friend', 'public', 'shared', 'static', 'true','false']; - var commontypes = ['integer','string','double','decimal','boolean','short','char', 'float','single']; - - var keywords = wordRegexp(commonkeywords); - var types = wordRegexp(commontypes); - var stringPrefixes = '"'; - - var opening = wordRegexp(openingKeywords); - var middle = wordRegexp(middleKeywords); - var closing = wordRegexp(endKeywords); - var doubleClosing = wordRegexp(['end']); - var doOpening = wordRegexp(['do']); - - var indentInfo = null; - - - - - function indent(_stream, state) { - state.currentIndent++; - } - - function dedent(_stream, state) { - state.currentIndent--; - } - // tokenizers - function tokenBase(stream, state) { - if (stream.eatSpace()) { - return null; - } - - var ch = stream.peek(); - - // Handle Comments - if (ch === "'") { - stream.skipToEnd(); - return 'comment'; - } - - - // Handle Number Literals - if (stream.match(/^((&H)|(&O))?[0-9\.a-f]/i, false)) { - var floatLiteral = false; - // Floats - if (stream.match(/^\d*\.\d+F?/i)) { floatLiteral = true; } - else if (stream.match(/^\d+\.\d*F?/)) { floatLiteral = true; } - else if (stream.match(/^\.\d+F?/)) { floatLiteral = true; } - - if (floatLiteral) { - // Float literals may be "imaginary" - stream.eat(/J/i); - return 'number'; - } - // Integers - var intLiteral = false; - // Hex - if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; } - // Octal - else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; } - // Decimal - else if (stream.match(/^[1-9]\d*F?/)) { - // Decimal literals may be "imaginary" - stream.eat(/J/i); - // TODO - Can you have imaginary longs? - intLiteral = true; - } - // Zero by itself with no other piece of number. - else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; } - if (intLiteral) { - // Integer literals may be "long" - stream.eat(/L/i); - return 'number'; - } - } - - // Handle Strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenStringFactory(stream.current()); - return state.tokenize(stream, state); - } - - // Handle operators and Delimiters - if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) { - return null; - } - if (stream.match(doubleOperators) - || stream.match(singleOperators) - || stream.match(wordOperators)) { - return 'operator'; - } - if (stream.match(singleDelimiters)) { - return null; - } - if (stream.match(doOpening)) { - indent(stream,state); - state.doInCurrentLine = true; - return 'keyword'; - } - if (stream.match(opening)) { - if (! state.doInCurrentLine) - indent(stream,state); - else - state.doInCurrentLine = false; - return 'keyword'; - } - if (stream.match(middle)) { - return 'keyword'; - } - - if (stream.match(doubleClosing)) { - dedent(stream,state); - dedent(stream,state); - return 'keyword'; - } - if (stream.match(closing)) { - dedent(stream,state); - return 'keyword'; - } - - if (stream.match(types)) { - return 'keyword'; - } - - if (stream.match(keywords)) { - return 'keyword'; - } - - if (stream.match(identifiers)) { - return 'variable'; - } - - // Handle non-detected items - stream.next(); - return ERRORCLASS; - } - - function tokenStringFactory(delimiter) { - var singleline = delimiter.length == 1; - var OUTCLASS = 'string'; - - return function(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^'"]/); - if (stream.match(delimiter)) { - state.tokenize = tokenBase; - return OUTCLASS; - } else { - stream.eat(/['"]/); - } - } - if (singleline) { - if (parserConf.singleLineStringErrors) { - return ERRORCLASS; - } else { - state.tokenize = tokenBase; - } - } - return OUTCLASS; - }; - } - - - function tokenLexer(stream, state) { - var style = state.tokenize(stream, state); - var current = stream.current(); - - // Handle '.' connected identifiers - if (current === '.') { - style = state.tokenize(stream, state); - current = stream.current(); - if (style === 'variable') { - return 'variable'; - } else { - return ERRORCLASS; - } - } - - - var delimiter_index = '[({'.indexOf(current); - if (delimiter_index !== -1) { - indent(stream, state ); - } - if (indentInfo === 'dedent') { - if (dedent(stream, state)) { - return ERRORCLASS; - } - } - delimiter_index = '])}'.indexOf(current); - if (delimiter_index !== -1) { - if (dedent(stream, state)) { - return ERRORCLASS; - } - } - - return style; - } - - var external = { - electricChars:"dDpPtTfFeE ", - startState: function() { - return { - tokenize: tokenBase, - lastToken: null, - currentIndent: 0, - nextLineIndent: 0, - doInCurrentLine: false - - - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - state.currentIndent += state.nextLineIndent; - state.nextLineIndent = 0; - state.doInCurrentLine = 0; - } - var style = tokenLexer(stream, state); - - state.lastToken = {style:style, content: stream.current()}; - - - - return style; - }, - - indent: function(state, textAfter) { - var trueText = textAfter.replace(/^\s+|\s+$/g, '') ; - if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1); - if(state.currentIndent < 0) return 0; - return state.currentIndent * conf.indentUnit; - } - - }; - return external; -}); - -CodeMirror.defineMIME("text/x-vb", "vb"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/vbscript/index.html b/shared/html/libs/codemirror/5.0.0/mode/vbscript/index.html deleted file mode 100644 index ad7532d..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/vbscript/index.html +++ /dev/null @@ -1,55 +0,0 @@ - - -CodeMirror: VBScript mode - - - - - - - - - -
    -

    VBScript mode

    - - -
    - - - -

    MIME types defined: text/vbscript.

    -
    diff --git a/shared/html/libs/codemirror/5.0.0/mode/vbscript/vbscript.js b/shared/html/libs/codemirror/5.0.0/mode/vbscript/vbscript.js deleted file mode 100644 index b66df22..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/vbscript/vbscript.js +++ /dev/null @@ -1,350 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* -For extra ASP classic objects, initialize CodeMirror instance with this option: - isASP: true - -E.G.: - var editor = CodeMirror.fromTextArea(document.getElementById("code"), { - lineNumbers: true, - isASP: true - }); -*/ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("vbscript", function(conf, parserConf) { - var ERRORCLASS = 'error'; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b", "i"); - } - - var singleOperators = new RegExp("^[\\+\\-\\*/&\\\\\\^<>=]"); - var doubleOperators = new RegExp("^((<>)|(<=)|(>=))"); - var singleDelimiters = new RegExp('^[\\.,]'); - var brakets = new RegExp('^[\\(\\)]'); - var identifiers = new RegExp("^[A-Za-z][_A-Za-z0-9]*"); - - var openingKeywords = ['class','sub','select','while','if','function', 'property', 'with', 'for']; - var middleKeywords = ['else','elseif','case']; - var endKeywords = ['next','loop','wend']; - - var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'is', 'mod', 'eqv', 'imp']); - var commonkeywords = ['dim', 'redim', 'then', 'until', 'randomize', - 'byval','byref','new','property', 'exit', 'in', - 'const','private', 'public', - 'get','set','let', 'stop', 'on error resume next', 'on error goto 0', 'option explicit', 'call', 'me']; - - //This list was from: http://msdn.microsoft.com/en-us/library/f8tbc79x(v=vs.84).aspx - var atomWords = ['true', 'false', 'nothing', 'empty', 'null']; - //This list was from: http://msdn.microsoft.com/en-us/library/3ca8tfek(v=vs.84).aspx - var builtinFuncsWords = ['abs', 'array', 'asc', 'atn', 'cbool', 'cbyte', 'ccur', 'cdate', 'cdbl', 'chr', 'cint', 'clng', 'cos', 'csng', 'cstr', 'date', 'dateadd', 'datediff', 'datepart', - 'dateserial', 'datevalue', 'day', 'escape', 'eval', 'execute', 'exp', 'filter', 'formatcurrency', 'formatdatetime', 'formatnumber', 'formatpercent', 'getlocale', 'getobject', - 'getref', 'hex', 'hour', 'inputbox', 'instr', 'instrrev', 'int', 'fix', 'isarray', 'isdate', 'isempty', 'isnull', 'isnumeric', 'isobject', 'join', 'lbound', 'lcase', 'left', - 'len', 'loadpicture', 'log', 'ltrim', 'rtrim', 'trim', 'maths', 'mid', 'minute', 'month', 'monthname', 'msgbox', 'now', 'oct', 'replace', 'rgb', 'right', 'rnd', 'round', - 'scriptengine', 'scriptenginebuildversion', 'scriptenginemajorversion', 'scriptengineminorversion', 'second', 'setlocale', 'sgn', 'sin', 'space', 'split', 'sqr', 'strcomp', - 'string', 'strreverse', 'tan', 'time', 'timer', 'timeserial', 'timevalue', 'typename', 'ubound', 'ucase', 'unescape', 'vartype', 'weekday', 'weekdayname', 'year']; - - //This list was from: http://msdn.microsoft.com/en-us/library/ydz4cfk3(v=vs.84).aspx - var builtinConsts = ['vbBlack', 'vbRed', 'vbGreen', 'vbYellow', 'vbBlue', 'vbMagenta', 'vbCyan', 'vbWhite', 'vbBinaryCompare', 'vbTextCompare', - 'vbSunday', 'vbMonday', 'vbTuesday', 'vbWednesday', 'vbThursday', 'vbFriday', 'vbSaturday', 'vbUseSystemDayOfWeek', 'vbFirstJan1', 'vbFirstFourDays', 'vbFirstFullWeek', - 'vbGeneralDate', 'vbLongDate', 'vbShortDate', 'vbLongTime', 'vbShortTime', 'vbObjectError', - 'vbOKOnly', 'vbOKCancel', 'vbAbortRetryIgnore', 'vbYesNoCancel', 'vbYesNo', 'vbRetryCancel', 'vbCritical', 'vbQuestion', 'vbExclamation', 'vbInformation', 'vbDefaultButton1', 'vbDefaultButton2', - 'vbDefaultButton3', 'vbDefaultButton4', 'vbApplicationModal', 'vbSystemModal', 'vbOK', 'vbCancel', 'vbAbort', 'vbRetry', 'vbIgnore', 'vbYes', 'vbNo', - 'vbCr', 'VbCrLf', 'vbFormFeed', 'vbLf', 'vbNewLine', 'vbNullChar', 'vbNullString', 'vbTab', 'vbVerticalTab', 'vbUseDefault', 'vbTrue', 'vbFalse', - 'vbEmpty', 'vbNull', 'vbInteger', 'vbLong', 'vbSingle', 'vbDouble', 'vbCurrency', 'vbDate', 'vbString', 'vbObject', 'vbError', 'vbBoolean', 'vbVariant', 'vbDataObject', 'vbDecimal', 'vbByte', 'vbArray']; - //This list was from: http://msdn.microsoft.com/en-us/library/hkc375ea(v=vs.84).aspx - var builtinObjsWords = ['WScript', 'err', 'debug', 'RegExp']; - var knownProperties = ['description', 'firstindex', 'global', 'helpcontext', 'helpfile', 'ignorecase', 'length', 'number', 'pattern', 'source', 'value', 'count']; - var knownMethods = ['clear', 'execute', 'raise', 'replace', 'test', 'write', 'writeline', 'close', 'open', 'state', 'eof', 'update', 'addnew', 'end', 'createobject', 'quit']; - - var aspBuiltinObjsWords = ['server', 'response', 'request', 'session', 'application']; - var aspKnownProperties = ['buffer', 'cachecontrol', 'charset', 'contenttype', 'expires', 'expiresabsolute', 'isclientconnected', 'pics', 'status', //response - 'clientcertificate', 'cookies', 'form', 'querystring', 'servervariables', 'totalbytes', //request - 'contents', 'staticobjects', //application - 'codepage', 'lcid', 'sessionid', 'timeout', //session - 'scripttimeout']; //server - var aspKnownMethods = ['addheader', 'appendtolog', 'binarywrite', 'end', 'flush', 'redirect', //response - 'binaryread', //request - 'remove', 'removeall', 'lock', 'unlock', //application - 'abandon', //session - 'getlasterror', 'htmlencode', 'mappath', 'transfer', 'urlencode']; //server - - var knownWords = knownMethods.concat(knownProperties); - - builtinObjsWords = builtinObjsWords.concat(builtinConsts); - - if (conf.isASP){ - builtinObjsWords = builtinObjsWords.concat(aspBuiltinObjsWords); - knownWords = knownWords.concat(aspKnownMethods, aspKnownProperties); - }; - - var keywords = wordRegexp(commonkeywords); - var atoms = wordRegexp(atomWords); - var builtinFuncs = wordRegexp(builtinFuncsWords); - var builtinObjs = wordRegexp(builtinObjsWords); - var known = wordRegexp(knownWords); - var stringPrefixes = '"'; - - var opening = wordRegexp(openingKeywords); - var middle = wordRegexp(middleKeywords); - var closing = wordRegexp(endKeywords); - var doubleClosing = wordRegexp(['end']); - var doOpening = wordRegexp(['do']); - var noIndentWords = wordRegexp(['on error resume next', 'exit']); - var comment = wordRegexp(['rem']); - - - function indent(_stream, state) { - state.currentIndent++; - } - - function dedent(_stream, state) { - state.currentIndent--; - } - // tokenizers - function tokenBase(stream, state) { - if (stream.eatSpace()) { - return 'space'; - //return null; - } - - var ch = stream.peek(); - - // Handle Comments - if (ch === "'") { - stream.skipToEnd(); - return 'comment'; - } - if (stream.match(comment)){ - stream.skipToEnd(); - return 'comment'; - } - - - // Handle Number Literals - if (stream.match(/^((&H)|(&O))?[0-9\.]/i, false) && !stream.match(/^((&H)|(&O))?[0-9\.]+[a-z_]/i, false)) { - var floatLiteral = false; - // Floats - if (stream.match(/^\d*\.\d+/i)) { floatLiteral = true; } - else if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; } - else if (stream.match(/^\.\d+/)) { floatLiteral = true; } - - if (floatLiteral) { - // Float literals may be "imaginary" - stream.eat(/J/i); - return 'number'; - } - // Integers - var intLiteral = false; - // Hex - if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; } - // Octal - else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; } - // Decimal - else if (stream.match(/^[1-9]\d*F?/)) { - // Decimal literals may be "imaginary" - stream.eat(/J/i); - // TODO - Can you have imaginary longs? - intLiteral = true; - } - // Zero by itself with no other piece of number. - else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; } - if (intLiteral) { - // Integer literals may be "long" - stream.eat(/L/i); - return 'number'; - } - } - - // Handle Strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenStringFactory(stream.current()); - return state.tokenize(stream, state); - } - - // Handle operators and Delimiters - if (stream.match(doubleOperators) - || stream.match(singleOperators) - || stream.match(wordOperators)) { - return 'operator'; - } - if (stream.match(singleDelimiters)) { - return null; - } - - if (stream.match(brakets)) { - return "bracket"; - } - - if (stream.match(noIndentWords)) { - state.doInCurrentLine = true; - - return 'keyword'; - } - - if (stream.match(doOpening)) { - indent(stream,state); - state.doInCurrentLine = true; - - return 'keyword'; - } - if (stream.match(opening)) { - if (! state.doInCurrentLine) - indent(stream,state); - else - state.doInCurrentLine = false; - - return 'keyword'; - } - if (stream.match(middle)) { - return 'keyword'; - } - - - if (stream.match(doubleClosing)) { - dedent(stream,state); - dedent(stream,state); - - return 'keyword'; - } - if (stream.match(closing)) { - if (! state.doInCurrentLine) - dedent(stream,state); - else - state.doInCurrentLine = false; - - return 'keyword'; - } - - if (stream.match(keywords)) { - return 'keyword'; - } - - if (stream.match(atoms)) { - return 'atom'; - } - - if (stream.match(known)) { - return 'variable-2'; - } - - if (stream.match(builtinFuncs)) { - return 'builtin'; - } - - if (stream.match(builtinObjs)){ - return 'variable-2'; - } - - if (stream.match(identifiers)) { - return 'variable'; - } - - // Handle non-detected items - stream.next(); - return ERRORCLASS; - } - - function tokenStringFactory(delimiter) { - var singleline = delimiter.length == 1; - var OUTCLASS = 'string'; - - return function(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^'"]/); - if (stream.match(delimiter)) { - state.tokenize = tokenBase; - return OUTCLASS; - } else { - stream.eat(/['"]/); - } - } - if (singleline) { - if (parserConf.singleLineStringErrors) { - return ERRORCLASS; - } else { - state.tokenize = tokenBase; - } - } - return OUTCLASS; - }; - } - - - function tokenLexer(stream, state) { - var style = state.tokenize(stream, state); - var current = stream.current(); - - // Handle '.' connected identifiers - if (current === '.') { - style = state.tokenize(stream, state); - - current = stream.current(); - if (style && (style.substr(0, 8) === 'variable' || style==='builtin' || style==='keyword')){//|| knownWords.indexOf(current.substring(1)) > -1) { - if (style === 'builtin' || style === 'keyword') style='variable'; - if (knownWords.indexOf(current.substr(1)) > -1) style='variable-2'; - - return style; - } else { - return ERRORCLASS; - } - } - - return style; - } - - var external = { - electricChars:"dDpPtTfFeE ", - startState: function() { - return { - tokenize: tokenBase, - lastToken: null, - currentIndent: 0, - nextLineIndent: 0, - doInCurrentLine: false, - ignoreKeyword: false - - - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - state.currentIndent += state.nextLineIndent; - state.nextLineIndent = 0; - state.doInCurrentLine = 0; - } - var style = tokenLexer(stream, state); - - state.lastToken = {style:style, content: stream.current()}; - - if (style==='space') style=null; - - return style; - }, - - indent: function(state, textAfter) { - var trueText = textAfter.replace(/^\s+|\s+$/g, '') ; - if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1); - if(state.currentIndent < 0) return 0; - return state.currentIndent * conf.indentUnit; - } - - }; - return external; -}); - -CodeMirror.defineMIME("text/vbscript", "vbscript"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/velocity/index.html b/shared/html/libs/codemirror/5.0.0/mode/velocity/index.html deleted file mode 100644 index 2747878..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/velocity/index.html +++ /dev/null @@ -1,118 +0,0 @@ - - -CodeMirror: Velocity mode - - - - - - - - - - -
    -

    Velocity mode

    -
    - - -

    MIME types defined: text/velocity.

    - -
    diff --git a/shared/html/libs/codemirror/5.0.0/mode/velocity/velocity.js b/shared/html/libs/codemirror/5.0.0/mode/velocity/velocity.js deleted file mode 100644 index 8fc4f95..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/velocity/velocity.js +++ /dev/null @@ -1,201 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("velocity", function() { - function parseWords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var keywords = parseWords("#end #else #break #stop #[[ #]] " + - "#{end} #{else} #{break} #{stop}"); - var functions = parseWords("#if #elseif #foreach #set #include #parse #macro #define #evaluate " + - "#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}"); - var specials = parseWords("$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent.count $foreach.parent.hasNext $foreach.parent.first $foreach.parent.last $foreach.parent $velocityCount $!bodyContent $bodyContent"); - var isOperatorChar = /[+\-*&%=<>!?:\/|]/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - function tokenBase(stream, state) { - var beforeParams = state.beforeParams; - state.beforeParams = false; - var ch = stream.next(); - // start of unparsed string? - if ((ch == "'") && state.inParams) { - state.lastTokenWasBuiltin = false; - return chain(stream, state, tokenString(ch)); - } - // start of parsed string? - else if ((ch == '"')) { - state.lastTokenWasBuiltin = false; - if (state.inString) { - state.inString = false; - return "string"; - } - else if (state.inParams) - return chain(stream, state, tokenString(ch)); - } - // is it one of the special signs []{}().,;? Seperator? - else if (/[\[\]{}\(\),;\.]/.test(ch)) { - if (ch == "(" && beforeParams) - state.inParams = true; - else if (ch == ")") { - state.inParams = false; - state.lastTokenWasBuiltin = true; - } - return null; - } - // start of a number value? - else if (/\d/.test(ch)) { - state.lastTokenWasBuiltin = false; - stream.eatWhile(/[\w\.]/); - return "number"; - } - // multi line comment? - else if (ch == "#" && stream.eat("*")) { - state.lastTokenWasBuiltin = false; - return chain(stream, state, tokenComment); - } - // unparsed content? - else if (ch == "#" && stream.match(/ *\[ *\[/)) { - state.lastTokenWasBuiltin = false; - return chain(stream, state, tokenUnparsed); - } - // single line comment? - else if (ch == "#" && stream.eat("#")) { - state.lastTokenWasBuiltin = false; - stream.skipToEnd(); - return "comment"; - } - // variable? - else if (ch == "$") { - stream.eatWhile(/[\w\d\$_\.{}]/); - // is it one of the specials? - if (specials && specials.propertyIsEnumerable(stream.current())) { - return "keyword"; - } - else { - state.lastTokenWasBuiltin = true; - state.beforeParams = true; - return "builtin"; - } - } - // is it a operator? - else if (isOperatorChar.test(ch)) { - state.lastTokenWasBuiltin = false; - stream.eatWhile(isOperatorChar); - return "operator"; - } - else { - // get the whole word - stream.eatWhile(/[\w\$_{}@]/); - var word = stream.current(); - // is it one of the listed keywords? - if (keywords && keywords.propertyIsEnumerable(word)) - return "keyword"; - // is it one of the listed functions? - if (functions && functions.propertyIsEnumerable(word) || - (stream.current().match(/^#@?[a-z0-9_]+ *$/i) && stream.peek()=="(") && - !(functions && functions.propertyIsEnumerable(word.toLowerCase()))) { - state.beforeParams = true; - state.lastTokenWasBuiltin = false; - return "keyword"; - } - if (state.inString) { - state.lastTokenWasBuiltin = false; - return "string"; - } - if (stream.pos > word.length && stream.string.charAt(stream.pos-word.length-1)=="." && state.lastTokenWasBuiltin) - return "builtin"; - // default: just a "word" - state.lastTokenWasBuiltin = false; - return null; - } - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if ((next == quote) && !escaped) { - end = true; - break; - } - if (quote=='"' && stream.peek() == '$' && !escaped) { - state.inString = true; - end = true; - break; - } - escaped = !escaped && next == "\\"; - } - if (end) state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "#" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function tokenUnparsed(stream, state) { - var maybeEnd = 0, ch; - while (ch = stream.next()) { - if (ch == "#" && maybeEnd == 2) { - state.tokenize = tokenBase; - break; - } - if (ch == "]") - maybeEnd++; - else if (ch != " ") - maybeEnd = 0; - } - return "meta"; - } - // Interface - - return { - startState: function() { - return { - tokenize: tokenBase, - beforeParams: false, - inParams: false, - inString: false, - lastTokenWasBuiltin: false - }; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - }, - blockCommentStart: "#*", - blockCommentEnd: "*#", - lineComment: "##", - fold: "velocity" - }; -}); - -CodeMirror.defineMIME("text/velocity", "velocity"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/verilog/index.html b/shared/html/libs/codemirror/5.0.0/mode/verilog/index.html deleted file mode 100644 index 96b3d64..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/verilog/index.html +++ /dev/null @@ -1,120 +0,0 @@ - - -CodeMirror: Verilog/SystemVerilog mode - - - - - - - - - - -
    -

    SystemVerilog mode

    - -
    - - - -

    -Syntax highlighting and indentation for the Verilog and SystemVerilog languages (IEEE 1800). -

    Configuration options:

    -
      -
    • noIndentKeywords - List of keywords which should not cause identation to increase. E.g. ["package", "module"]. Default: None
    • -
    -

    - -

    MIME types defined: text/x-verilog and text/x-systemverilog.

    -
    diff --git a/shared/html/libs/codemirror/5.0.0/mode/verilog/test.js b/shared/html/libs/codemirror/5.0.0/mode/verilog/test.js deleted file mode 100644 index 9c8c094..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/verilog/test.js +++ /dev/null @@ -1,273 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 4}, "verilog"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("binary_literals", - "[number 1'b0]", - "[number 1'b1]", - "[number 1'bx]", - "[number 1'bz]", - "[number 1'bX]", - "[number 1'bZ]", - "[number 1'B0]", - "[number 1'B1]", - "[number 1'Bx]", - "[number 1'Bz]", - "[number 1'BX]", - "[number 1'BZ]", - "[number 1'b0]", - "[number 1'b1]", - "[number 2'b01]", - "[number 2'bxz]", - "[number 2'b11]", - "[number 2'b10]", - "[number 2'b1Z]", - "[number 12'b0101_0101_0101]", - "[number 1'b 0]", - "[number 'b0101]" - ); - - MT("octal_literals", - "[number 3'o7]", - "[number 3'O7]", - "[number 3'so7]", - "[number 3'SO7]" - ); - - MT("decimal_literals", - "[number 0]", - "[number 1]", - "[number 7]", - "[number 123_456]", - "[number 'd33]", - "[number 8'd255]", - "[number 8'D255]", - "[number 8'sd255]", - "[number 8'SD255]", - "[number 32'd123]", - "[number 32 'd123]", - "[number 32 'd 123]" - ); - - MT("hex_literals", - "[number 4'h0]", - "[number 4'ha]", - "[number 4'hF]", - "[number 4'hx]", - "[number 4'hz]", - "[number 4'hX]", - "[number 4'hZ]", - "[number 32'hdc78]", - "[number 32'hDC78]", - "[number 32 'hDC78]", - "[number 32'h DC78]", - "[number 32 'h DC78]", - "[number 32'h44x7]", - "[number 32'hFFF?]" - ); - - MT("real_number_literals", - "[number 1.2]", - "[number 0.1]", - "[number 2394.26331]", - "[number 1.2E12]", - "[number 1.2e12]", - "[number 1.30e-2]", - "[number 0.1e-0]", - "[number 23E10]", - "[number 29E-2]", - "[number 236.123_763_e-12]" - ); - - MT("operators", - "[meta ^]" - ); - - MT("keywords", - "[keyword logic]", - "[keyword logic] [variable foo]", - "[keyword reg] [variable abc]" - ); - - MT("variables", - "[variable _leading_underscore]", - "[variable _if]", - "[number 12] [variable foo]", - "[variable foo] [number 14]" - ); - - MT("tick_defines", - "[def `FOO]", - "[def `foo]", - "[def `FOO_bar]" - ); - - MT("system_calls", - "[meta $display]", - "[meta $vpi_printf]" - ); - - MT("line_comment", "[comment // Hello world]"); - - // Alignment tests - MT("align_port_map_style1", - /** - * mod mod(.a(a), - * .b(b) - * ); - */ - "[variable mod] [variable mod][bracket (].[variable a][bracket (][variable a][bracket )],", - " .[variable b][bracket (][variable b][bracket )]", - " [bracket )];", - "" - ); - - MT("align_port_map_style2", - /** - * mod mod( - * .a(a), - * .b(b) - * ); - */ - "[variable mod] [variable mod][bracket (]", - " .[variable a][bracket (][variable a][bracket )],", - " .[variable b][bracket (][variable b][bracket )]", - "[bracket )];", - "" - ); - - // Indentation tests - MT("indent_single_statement_if", - "[keyword if] [bracket (][variable foo][bracket )]", - " [keyword break];", - "" - ); - - MT("no_indent_after_single_line_if", - "[keyword if] [bracket (][variable foo][bracket )] [keyword break];", - "" - ); - - MT("indent_after_if_begin_same_line", - "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]", - " [keyword break];", - " [keyword break];", - "[keyword end]", - "" - ); - - MT("indent_after_if_begin_next_line", - "[keyword if] [bracket (][variable foo][bracket )]", - " [keyword begin]", - " [keyword break];", - " [keyword break];", - " [keyword end]", - "" - ); - - MT("indent_single_statement_if_else", - "[keyword if] [bracket (][variable foo][bracket )]", - " [keyword break];", - "[keyword else]", - " [keyword break];", - "" - ); - - MT("indent_if_else_begin_same_line", - "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]", - " [keyword break];", - " [keyword break];", - "[keyword end] [keyword else] [keyword begin]", - " [keyword break];", - " [keyword break];", - "[keyword end]", - "" - ); - - MT("indent_if_else_begin_next_line", - "[keyword if] [bracket (][variable foo][bracket )]", - " [keyword begin]", - " [keyword break];", - " [keyword break];", - " [keyword end]", - "[keyword else]", - " [keyword begin]", - " [keyword break];", - " [keyword break];", - " [keyword end]", - "" - ); - - MT("indent_if_nested_without_begin", - "[keyword if] [bracket (][variable foo][bracket )]", - " [keyword if] [bracket (][variable foo][bracket )]", - " [keyword if] [bracket (][variable foo][bracket )]", - " [keyword break];", - "" - ); - - MT("indent_case", - "[keyword case] [bracket (][variable state][bracket )]", - " [variable FOO]:", - " [keyword break];", - " [variable BAR]:", - " [keyword break];", - "[keyword endcase]", - "" - ); - - MT("unindent_after_end_with_preceding_text", - "[keyword begin]", - " [keyword break]; [keyword end]", - "" - ); - - MT("export_function_one_line_does_not_indent", - "[keyword export] [string \"DPI-C\"] [keyword function] [variable helloFromSV];", - "" - ); - - MT("export_task_one_line_does_not_indent", - "[keyword export] [string \"DPI-C\"] [keyword task] [variable helloFromSV];", - "" - ); - - MT("export_function_two_lines_indents_properly", - "[keyword export]", - " [string \"DPI-C\"] [keyword function] [variable helloFromSV];", - "" - ); - - MT("export_task_two_lines_indents_properly", - "[keyword export]", - " [string \"DPI-C\"] [keyword task] [variable helloFromSV];", - "" - ); - - MT("import_function_one_line_does_not_indent", - "[keyword import] [string \"DPI-C\"] [keyword function] [variable helloFromC];", - "" - ); - - MT("import_task_one_line_does_not_indent", - "[keyword import] [string \"DPI-C\"] [keyword task] [variable helloFromC];", - "" - ); - - MT("import_package_single_line_does_not_indent", - "[keyword import] [variable p]::[variable x];", - "[keyword import] [variable p]::[variable y];", - "" - ); - - MT("covergoup_with_function_indents_properly", - "[keyword covergroup] [variable cg] [keyword with] [keyword function] [variable sample][bracket (][keyword bit] [variable b][bracket )];", - " [variable c] : [keyword coverpoint] [variable c];", - "[keyword endgroup]: [variable cg]", - "" - ); - -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/verilog/verilog.js b/shared/html/libs/codemirror/5.0.0/mode/verilog/verilog.js deleted file mode 100644 index 96b9f24..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/verilog/verilog.js +++ /dev/null @@ -1,537 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("verilog", function(config, parserConfig) { - - var indentUnit = config.indentUnit, - statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, - dontAlignCalls = parserConfig.dontAlignCalls, - noIndentKeywords = parserConfig.noIndentKeywords || [], - multiLineStrings = parserConfig.multiLineStrings, - hooks = parserConfig.hooks || {}; - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - /** - * Keywords from IEEE 1800-2012 - */ - var keywords = words( - "accept_on alias always always_comb always_ff always_latch and assert assign assume automatic before begin bind " + - "bins binsof bit break buf bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config " + - "const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable " + - "dist do edge else end endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup " + - "endinterface endmodule endpackage endprimitive endprogram endproperty endspecify endsequence endtable endtask " + - "enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin " + - "function generate genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import " + - "incdir include initial inout input inside instance int integer interconnect interface intersect join join_any " + - "join_none large let liblist library local localparam logic longint macromodule matches medium modport module " + - "nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 null or output package packed " + - "parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup " + - "pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg " + - "reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 s_always s_eventually s_nexttime " + - "s_until s_until_with scalared sequence shortint shortreal showcancelled signed small soft solve specify " + - "specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on " + - "table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior " + - "trireg type typedef union unique unique0 unsigned until until_with untyped use uwire var vectored virtual void " + - "wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor"); - - /** Operators from IEEE 1800-2012 - unary_operator ::= - + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~ - binary_operator ::= - + | - | * | / | % | == | != | === | !== | ==? | !=? | && | || | ** - | < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<< - | -> | <-> - inc_or_dec_operator ::= ++ | -- - unary_module_path_operator ::= - ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~ - binary_module_path_operator ::= - == | != | && | || | & | | | ^ | ^~ | ~^ - */ - var isOperatorChar = /[\+\-\*\/!~&|^%=?:]/; - var isBracketChar = /[\[\]{}()]/; - - var unsignedNumber = /\d[0-9_]*/; - var decimalLiteral = /\d*\s*'s?d\s*\d[0-9_]*/i; - var binaryLiteral = /\d*\s*'s?b\s*[xz01][xz01_]*/i; - var octLiteral = /\d*\s*'s?o\s*[xz0-7][xz0-7_]*/i; - var hexLiteral = /\d*\s*'s?h\s*[0-9a-fxz?][0-9a-fxz?_]*/i; - var realLiteral = /(\d[\d_]*(\.\d[\d_]*)?E-?[\d_]+)|(\d[\d_]*\.\d[\d_]*)/i; - - var closingBracketOrWord = /^((\w+)|[)}\]])/; - var closingBracket = /[)}\]]/; - - var curPunc; - var curKeyword; - - // Block openings which are closed by a matching keyword in the form of ("end" + keyword) - // E.g. "task" => "endtask" - var blockKeywords = words( - "case checker class clocking config function generate interface module package" + - "primitive program property specify sequence table task" - ); - - // Opening/closing pairs - var openClose = {}; - for (var keyword in blockKeywords) { - openClose[keyword] = "end" + keyword; - } - openClose["begin"] = "end"; - openClose["casex"] = "endcase"; - openClose["casez"] = "endcase"; - openClose["do" ] = "while"; - openClose["fork" ] = "join;join_any;join_none"; - openClose["covergroup"] = "endgroup"; - - for (var i in noIndentKeywords) { - var keyword = noIndentKeywords[i]; - if (openClose[keyword]) { - openClose[keyword] = undefined; - } - } - - // Keywords which open statements that are ended with a semi-colon - var statementKeywords = words("always always_comb always_ff always_latch assert assign assume else export for foreach forever if import initial repeat while"); - - function tokenBase(stream, state) { - var ch = stream.peek(), style; - if (hooks[ch] && (style = hooks[ch](stream, state)) != false) return style; - if (hooks.tokenBase && (style = hooks.tokenBase(stream, state)) != false) - return style; - - if (/[,;:\.]/.test(ch)) { - curPunc = stream.next(); - return null; - } - if (isBracketChar.test(ch)) { - curPunc = stream.next(); - return "bracket"; - } - // Macros (tick-defines) - if (ch == '`') { - stream.next(); - if (stream.eatWhile(/[\w\$_]/)) { - return "def"; - } else { - return null; - } - } - // System calls - if (ch == '$') { - stream.next(); - if (stream.eatWhile(/[\w\$_]/)) { - return "meta"; - } else { - return null; - } - } - // Time literals - if (ch == '#') { - stream.next(); - stream.eatWhile(/[\d_.]/); - return "def"; - } - // Strings - if (ch == '"') { - stream.next(); - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - // Comments - if (ch == "/") { - stream.next(); - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - stream.backUp(1); - } - - // Numeric literals - if (stream.match(realLiteral) || - stream.match(decimalLiteral) || - stream.match(binaryLiteral) || - stream.match(octLiteral) || - stream.match(hexLiteral) || - stream.match(unsignedNumber) || - stream.match(realLiteral)) { - return "number"; - } - - // Operators - if (stream.eatWhile(isOperatorChar)) { - return "meta"; - } - - // Keywords / plain variables - if (stream.eatWhile(/[\w\$_]/)) { - var cur = stream.current(); - if (keywords[cur]) { - if (openClose[cur]) { - curPunc = "newblock"; - } - if (statementKeywords[cur]) { - curPunc = "newstatement"; - } - curKeyword = cur; - return "keyword"; - } - return "variable"; - } - - stream.next(); - return null; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - var indent = state.indented; - var c = new Context(indent, col, type, null, state.context); - return state.context = c; - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") { - state.indented = state.context.indented; - } - return state.context = state.context.prev; - } - - function isClosing(text, contextClosing) { - if (text == contextClosing) { - return true; - } else { - // contextClosing may be mulitple keywords separated by ; - var closingKeywords = contextClosing.split(";"); - for (var i in closingKeywords) { - if (text == closingKeywords[i]) { - return true; - } - } - return false; - } - } - - function buildElectricInputRegEx() { - // Reindentation should occur on any bracket char: {}()[] - // or on a match of any of the block closing keywords, at - // the end of a line - var allClosings = []; - for (var i in openClose) { - if (openClose[i]) { - var closings = openClose[i].split(";"); - for (var j in closings) { - allClosings.push(closings[j]); - } - } - } - var re = new RegExp("[{}()\\[\\]]|(" + allClosings.join("|") + ")$"); - return re; - } - - // Interface - return { - - // Regex to force current line to reindent - electricInput: buildElectricInputRegEx(), - - startState: function(basecolumn) { - var state = { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - if (hooks.startState) hooks.startState(state); - return state; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (hooks.token) hooks.token(stream, state); - if (stream.eatSpace()) return null; - curPunc = null; - curKeyword = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta" || style == "variable") return style; - if (ctx.align == null) ctx.align = true; - - if (curPunc == ctx.type) { - popContext(state); - } else if ((curPunc == ";" && ctx.type == "statement") || - (ctx.type && isClosing(curKeyword, ctx.type))) { - ctx = popContext(state); - while (ctx && ctx.type == "statement") ctx = popContext(state); - } else if (curPunc == "{") { - pushContext(state, stream.column(), "}"); - } else if (curPunc == "[") { - pushContext(state, stream.column(), "]"); - } else if (curPunc == "(") { - pushContext(state, stream.column(), ")"); - } else if (ctx && ctx.type == "endcase" && curPunc == ":") { - pushContext(state, stream.column(), "statement"); - } else if (curPunc == "newstatement") { - pushContext(state, stream.column(), "statement"); - } else if (curPunc == "newblock") { - if (curKeyword == "function" && ctx && (ctx.type == "statement" || ctx.type == "endgroup")) { - // The 'function' keyword can appear in some other contexts where it actually does not - // indicate a function (import/export DPI and covergroup definitions). - // Do nothing in this case - } else if (curKeyword == "task" && ctx && ctx.type == "statement") { - // Same thing for task - } else { - var close = openClose[curKeyword]; - pushContext(state, stream.column(), close); - } - } - - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass; - if (hooks.indent) { - var fromHook = hooks.indent(state); - if (fromHook >= 0) return fromHook; - } - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; - var closing = false; - var possibleClosing = textAfter.match(closingBracketOrWord); - if (possibleClosing) - closing = isClosing(possibleClosing[0], ctx.type); - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); - else if (closingBracket.test(ctx.type) && ctx.align && !dontAlignCalls) return ctx.column + (closing ? 0 : 1); - else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit; - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//" - }; -}); - - CodeMirror.defineMIME("text/x-verilog", { - name: "verilog" - }); - - CodeMirror.defineMIME("text/x-systemverilog", { - name: "verilog" - }); - - // SVXVerilog mode - - var svxchScopePrefixes = { - ">": "property", "->": "property", "-": "hr", "|": "link", "?$": "qualifier", "?*": "qualifier", - "@-": "variable-3", "@": "variable-3", "?": "qualifier" - }; - - function svxGenIndent(stream, state) { - var svxindentUnit = 2; - var rtnIndent = -1, indentUnitRq = 0, curIndent = stream.indentation(); - switch (state.svxCurCtlFlowChar) { - case "\\": - curIndent = 0; - break; - case "|": - if (state.svxPrevPrevCtlFlowChar == "@") { - indentUnitRq = -2; //-2 new pipe rq after cur pipe - break; - } - if (svxchScopePrefixes[state.svxPrevCtlFlowChar]) - indentUnitRq = 1; // +1 new scope - break; - case "M": // m4 - if (state.svxPrevPrevCtlFlowChar == "@") { - indentUnitRq = -2; //-2 new inst rq after pipe - break; - } - if (svxchScopePrefixes[state.svxPrevCtlFlowChar]) - indentUnitRq = 1; // +1 new scope - break; - case "@": - if (state.svxPrevCtlFlowChar == "S") - indentUnitRq = -1; // new pipe stage after stmts - if (state.svxPrevCtlFlowChar == "|") - indentUnitRq = 1; // 1st pipe stage - break; - case "S": - if (state.svxPrevCtlFlowChar == "@") - indentUnitRq = 1; // flow in pipe stage - if (svxchScopePrefixes[state.svxPrevCtlFlowChar]) - indentUnitRq = 1; // +1 new scope - break; - } - var statementIndentUnit = svxindentUnit; - rtnIndent = curIndent + (indentUnitRq*statementIndentUnit); - return rtnIndent >= 0 ? rtnIndent : curIndent; - } - - CodeMirror.defineMIME("text/x-svx", { - name: "verilog", - hooks: { - "\\": function(stream, state) { - var vxIndent = 0, style = false; - var curPunc = stream.string; - if ((stream.sol()) && (/\\SV/.test(stream.string))) { - curPunc = (/\\SVX_version/.test(stream.string)) - ? "\\SVX_version" : stream.string; - stream.skipToEnd(); - if (curPunc == "\\SV" && state.vxCodeActive) {state.vxCodeActive = false;}; - if ((/\\SVX/.test(curPunc) && !state.vxCodeActive) - || (curPunc=="\\SVX_version" && state.vxCodeActive)) {state.vxCodeActive = true;}; - style = "keyword"; - state.svxCurCtlFlowChar = state.svxPrevPrevCtlFlowChar - = state.svxPrevCtlFlowChar = ""; - if (state.vxCodeActive == true) { - state.svxCurCtlFlowChar = "\\"; - vxIndent = svxGenIndent(stream, state); - } - state.vxIndentRq = vxIndent; - } - return style; - }, - tokenBase: function(stream, state) { - var vxIndent = 0, style = false; - var svxisOperatorChar = /[\[\]=:]/; - var svxkpScopePrefixs = { - "**":"variable-2", "*":"variable-2", "$$":"variable", "$":"variable", - "^^":"attribute", "^":"attribute"}; - var ch = stream.peek(); - var vxCurCtlFlowCharValueAtStart = state.svxCurCtlFlowChar; - if (state.vxCodeActive == true) { - if (/[\[\]{}\(\);\:]/.test(ch)) { - // bypass nesting and 1 char punc - style = "meta"; - stream.next(); - } else if (ch == "/") { - stream.next(); - if (stream.eat("/")) { - stream.skipToEnd(); - style = "comment"; - state.svxCurCtlFlowChar = "S"; - } else { - stream.backUp(1); - } - } else if (ch == "@") { - // pipeline stage - style = svxchScopePrefixes[ch]; - state.svxCurCtlFlowChar = "@"; - stream.next(); - stream.eatWhile(/[\w\$_]/); - } else if (stream.match(/\b[mM]4+/, true)) { // match: function(pattern, consume, caseInsensitive) - // m4 pre proc - stream.skipTo("("); - style = "def"; - state.svxCurCtlFlowChar = "M"; - } else if (ch == "!" && stream.sol()) { - // v stmt in svx region - // state.svxCurCtlFlowChar = "S"; - style = "comment"; - stream.next(); - } else if (svxisOperatorChar.test(ch)) { - // operators - stream.eatWhile(svxisOperatorChar); - style = "operator"; - } else if (ch == "#") { - // phy hier - state.svxCurCtlFlowChar = (state.svxCurCtlFlowChar == "") - ? ch : state.svxCurCtlFlowChar; - stream.next(); - stream.eatWhile(/[+-]\d/); - style = "tag"; - } else if (svxkpScopePrefixs.propertyIsEnumerable(ch)) { - // special SVX operators - style = svxkpScopePrefixs[ch]; - state.svxCurCtlFlowChar = state.svxCurCtlFlowChar == "" ? "S" : state.svxCurCtlFlowChar; // stmt - stream.next(); - stream.match(/[a-zA-Z_0-9]+/); - } else if (style = svxchScopePrefixes[ch] || false) { - // special SVX operators - state.svxCurCtlFlowChar = state.svxCurCtlFlowChar == "" ? ch : state.svxCurCtlFlowChar; - stream.next(); - stream.match(/[a-zA-Z_0-9]+/); - } - if (state.svxCurCtlFlowChar != vxCurCtlFlowCharValueAtStart) { // flow change - vxIndent = svxGenIndent(stream, state); - state.vxIndentRq = vxIndent; - } - } - return style; - }, - token: function(stream, state) { - if (state.vxCodeActive == true && stream.sol() && state.svxCurCtlFlowChar != "") { - state.svxPrevPrevCtlFlowChar = state.svxPrevCtlFlowChar; - state.svxPrevCtlFlowChar = state.svxCurCtlFlowChar; - state.svxCurCtlFlowChar = ""; - } - }, - indent: function(state) { - return (state.vxCodeActive == true) ? state.vxIndentRq : -1; - }, - startState: function(state) { - state.svxCurCtlFlowChar = ""; - state.svxPrevCtlFlowChar = ""; - state.svxPrevPrevCtlFlowChar = ""; - state.vxCodeActive = true; - state.vxIndentRq = 0; - } - } - }); -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/xml/index.html b/shared/html/libs/codemirror/5.0.0/mode/xml/index.html deleted file mode 100644 index 7149f06..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/xml/index.html +++ /dev/null @@ -1,57 +0,0 @@ - - -CodeMirror: XML mode - - - - - - - - - -
    -

    XML mode

    -
    - -

    The XML mode supports two configuration parameters:

    -
    -
    htmlMode (boolean)
    -
    This switches the mode to parse HTML instead of XML. This - means attributes do not have to be quoted, and some elements - (such as br) do not require a closing tag.
    -
    alignCDATA (boolean)
    -
    Setting this to true will force the opening tag of CDATA - blocks to not be indented.
    -
    - -

    MIME types defined: application/xml, text/html.

    -
    diff --git a/shared/html/libs/codemirror/5.0.0/mode/xml/test.js b/shared/html/libs/codemirror/5.0.0/mode/xml/test.js deleted file mode 100644 index f48156b..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/xml/test.js +++ /dev/null @@ -1,51 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml"; - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); } - - MT("matching", - "[tag&bracket <][tag top][tag&bracket >]", - " text", - " [tag&bracket <][tag inner][tag&bracket />]", - "[tag&bracket ]"); - - MT("nonmatching", - "[tag&bracket <][tag top][tag&bracket >]", - " [tag&bracket <][tag inner][tag&bracket />]", - " [tag&bracket ]"); - - MT("doctype", - "[meta ]", - "[tag&bracket <][tag top][tag&bracket />]"); - - MT("cdata", - "[tag&bracket <][tag top][tag&bracket >]", - " [atom ]", - "[tag&bracket ]"); - - // HTML tests - mode = CodeMirror.getMode({indentUnit: 2}, "text/html"); - - MT("selfclose", - "[tag&bracket <][tag html][tag&bracket >]", - " [tag&bracket <][tag link] [attribute rel]=[string stylesheet] [attribute href]=[string \"/foobar\"][tag&bracket >]", - "[tag&bracket ]"); - - MT("list", - "[tag&bracket <][tag ol][tag&bracket >]", - " [tag&bracket <][tag li][tag&bracket >]one", - " [tag&bracket <][tag li][tag&bracket >]two", - "[tag&bracket ]"); - - MT("valueless", - "[tag&bracket <][tag input] [attribute type]=[string checkbox] [attribute checked][tag&bracket />]"); - - MT("pThenArticle", - "[tag&bracket <][tag p][tag&bracket >]", - " foo", - "[tag&bracket <][tag article][tag&bracket >]bar"); - -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/xml/xml.js b/shared/html/libs/codemirror/5.0.0/mode/xml/xml.js deleted file mode 100644 index 2f3b8f8..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/xml/xml.js +++ /dev/null @@ -1,384 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("xml", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1; - var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag; - if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true; - - var Kludges = parserConfig.htmlMode ? { - autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, - 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, - 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, - 'track': true, 'wbr': true, 'menuitem': true}, - implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, - 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, - 'th': true, 'tr': true}, - contextGrabbers: { - 'dd': {'dd': true, 'dt': true}, - 'dt': {'dd': true, 'dt': true}, - 'li': {'li': true}, - 'option': {'option': true, 'optgroup': true}, - 'optgroup': {'optgroup': true}, - 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, - 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, - 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, - 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, - 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, - 'rp': {'rp': true, 'rt': true}, - 'rt': {'rp': true, 'rt': true}, - 'tbody': {'tbody': true, 'tfoot': true}, - 'td': {'td': true, 'th': true}, - 'tfoot': {'tbody': true}, - 'th': {'td': true, 'th': true}, - 'thead': {'tbody': true, 'tfoot': true}, - 'tr': {'tr': true} - }, - doNotIndent: {"pre": true}, - allowUnquoted: true, - allowMissing: true, - caseFold: true - } : { - autoSelfClosers: {}, - implicitlyClosed: {}, - contextGrabbers: {}, - doNotIndent: {}, - allowUnquoted: false, - allowMissing: false, - caseFold: false - }; - var alignCDATA = parserConfig.alignCDATA; - - // Return variables for tokenizers - var type, setStyle; - - function inText(stream, state) { - function chain(parser) { - state.tokenize = parser; - return parser(stream, state); - } - - var ch = stream.next(); - if (ch == "<") { - if (stream.eat("!")) { - if (stream.eat("[")) { - if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); - else return null; - } else if (stream.match("--")) { - return chain(inBlock("comment", "-->")); - } else if (stream.match("DOCTYPE", true, true)) { - stream.eatWhile(/[\w\._\-]/); - return chain(doctype(1)); - } else { - return null; - } - } else if (stream.eat("?")) { - stream.eatWhile(/[\w\._\-]/); - state.tokenize = inBlock("meta", "?>"); - return "meta"; - } else { - type = stream.eat("/") ? "closeTag" : "openTag"; - state.tokenize = inTag; - return "tag bracket"; - } - } else if (ch == "&") { - var ok; - if (stream.eat("#")) { - if (stream.eat("x")) { - ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";"); - } else { - ok = stream.eatWhile(/[\d]/) && stream.eat(";"); - } - } else { - ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";"); - } - return ok ? "atom" : "error"; - } else { - stream.eatWhile(/[^&<]/); - return null; - } - } - - function inTag(stream, state) { - var ch = stream.next(); - if (ch == ">" || (ch == "/" && stream.eat(">"))) { - state.tokenize = inText; - type = ch == ">" ? "endTag" : "selfcloseTag"; - return "tag bracket"; - } else if (ch == "=") { - type = "equals"; - return null; - } else if (ch == "<") { - state.tokenize = inText; - state.state = baseState; - state.tagName = state.tagStart = null; - var next = state.tokenize(stream, state); - return next ? next + " tag error" : "tag error"; - } else if (/[\'\"]/.test(ch)) { - state.tokenize = inAttribute(ch); - state.stringStartCol = stream.column(); - return state.tokenize(stream, state); - } else { - stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/); - return "word"; - } - } - - function inAttribute(quote) { - var closure = function(stream, state) { - while (!stream.eol()) { - if (stream.next() == quote) { - state.tokenize = inTag; - break; - } - } - return "string"; - }; - closure.isInAttribute = true; - return closure; - } - - function inBlock(style, terminator) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.match(terminator)) { - state.tokenize = inText; - break; - } - stream.next(); - } - return style; - }; - } - function doctype(depth) { - return function(stream, state) { - var ch; - while ((ch = stream.next()) != null) { - if (ch == "<") { - state.tokenize = doctype(depth + 1); - return state.tokenize(stream, state); - } else if (ch == ">") { - if (depth == 1) { - state.tokenize = inText; - break; - } else { - state.tokenize = doctype(depth - 1); - return state.tokenize(stream, state); - } - } - } - return "meta"; - }; - } - - function Context(state, tagName, startOfLine) { - this.prev = state.context; - this.tagName = tagName; - this.indent = state.indented; - this.startOfLine = startOfLine; - if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent)) - this.noIndent = true; - } - function popContext(state) { - if (state.context) state.context = state.context.prev; - } - function maybePopContext(state, nextTagName) { - var parentTagName; - while (true) { - if (!state.context) { - return; - } - parentTagName = state.context.tagName; - if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || - !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { - return; - } - popContext(state); - } - } - - function baseState(type, stream, state) { - if (type == "openTag") { - state.tagStart = stream.column(); - return tagNameState; - } else if (type == "closeTag") { - return closeTagNameState; - } else { - return baseState; - } - } - function tagNameState(type, stream, state) { - if (type == "word") { - state.tagName = stream.current(); - setStyle = "tag"; - return attrState; - } else { - setStyle = "error"; - return tagNameState; - } - } - function closeTagNameState(type, stream, state) { - if (type == "word") { - var tagName = stream.current(); - if (state.context && state.context.tagName != tagName && - Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName)) - popContext(state); - if (state.context && state.context.tagName == tagName) { - setStyle = "tag"; - return closeState; - } else { - setStyle = "tag error"; - return closeStateErr; - } - } else { - setStyle = "error"; - return closeStateErr; - } - } - - function closeState(type, _stream, state) { - if (type != "endTag") { - setStyle = "error"; - return closeState; - } - popContext(state); - return baseState; - } - function closeStateErr(type, stream, state) { - setStyle = "error"; - return closeState(type, stream, state); - } - - function attrState(type, _stream, state) { - if (type == "word") { - setStyle = "attribute"; - return attrEqState; - } else if (type == "endTag" || type == "selfcloseTag") { - var tagName = state.tagName, tagStart = state.tagStart; - state.tagName = state.tagStart = null; - if (type == "selfcloseTag" || - Kludges.autoSelfClosers.hasOwnProperty(tagName)) { - maybePopContext(state, tagName); - } else { - maybePopContext(state, tagName); - state.context = new Context(state, tagName, tagStart == state.indented); - } - return baseState; - } - setStyle = "error"; - return attrState; - } - function attrEqState(type, stream, state) { - if (type == "equals") return attrValueState; - if (!Kludges.allowMissing) setStyle = "error"; - return attrState(type, stream, state); - } - function attrValueState(type, stream, state) { - if (type == "string") return attrContinuedState; - if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;} - setStyle = "error"; - return attrState(type, stream, state); - } - function attrContinuedState(type, stream, state) { - if (type == "string") return attrContinuedState; - return attrState(type, stream, state); - } - - return { - startState: function() { - return {tokenize: inText, - state: baseState, - indented: 0, - tagName: null, tagStart: null, - context: null}; - }, - - token: function(stream, state) { - if (!state.tagName && stream.sol()) - state.indented = stream.indentation(); - - if (stream.eatSpace()) return null; - type = null; - var style = state.tokenize(stream, state); - if ((style || type) && style != "comment") { - setStyle = null; - state.state = state.state(type || style, stream, state); - if (setStyle) - style = setStyle == "error" ? style + " error" : setStyle; - } - return style; - }, - - indent: function(state, textAfter, fullLine) { - var context = state.context; - // Indent multi-line strings (e.g. css). - if (state.tokenize.isInAttribute) { - if (state.tagStart == state.indented) - return state.stringStartCol + 1; - else - return state.indented + indentUnit; - } - if (context && context.noIndent) return CodeMirror.Pass; - if (state.tokenize != inTag && state.tokenize != inText) - return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; - // Indent the starts of attribute names. - if (state.tagName) { - if (multilineTagIndentPastTag) - return state.tagStart + state.tagName.length + 2; - else - return state.tagStart + indentUnit * multilineTagIndentFactor; - } - if (alignCDATA && /$/, - blockCommentStart: "", - - configuration: parserConfig.htmlMode ? "html" : "xml", - helperType: parserConfig.htmlMode ? "html" : "xml" - }; -}); - -CodeMirror.defineMIME("text/xml", "xml"); -CodeMirror.defineMIME("application/xml", "xml"); -if (!CodeMirror.mimeModes.hasOwnProperty("text/html")) - CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/xquery/index.html b/shared/html/libs/codemirror/5.0.0/mode/xquery/index.html deleted file mode 100644 index 7ac5aae..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/xquery/index.html +++ /dev/null @@ -1,210 +0,0 @@ - - -CodeMirror: XQuery mode - - - - - - - - - - -
    -

    XQuery mode

    - - -
    - -
    - - - -

    MIME types defined: application/xquery.

    - -

    Development of the CodeMirror XQuery mode was sponsored by - MarkLogic and developed by - Mike Brevoort. -

    - -
    diff --git a/shared/html/libs/codemirror/5.0.0/mode/xquery/test.js b/shared/html/libs/codemirror/5.0.0/mode/xquery/test.js deleted file mode 100644 index 1f148cd..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/xquery/test.js +++ /dev/null @@ -1,67 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Don't take these too seriously -- the expected results appear to be -// based on the results of actual runs without any serious manual -// verification. If a change you made causes them to fail, the test is -// as likely to wrong as the code. - -(function() { - var mode = CodeMirror.getMode({tabSize: 4}, "xquery"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("eviltest", - "[keyword xquery] [keyword version] [variable "1][keyword .][atom 0][keyword -][variable ml"][def&variable ;] [comment (: this is : a \"comment\" :)]", - " [keyword let] [variable $let] [keyword :=] [variable <x] [variable attr][keyword =][variable "value">"test"<func>][def&variable ;function]() [variable $var] {[keyword function]()} {[variable $var]}[variable <][keyword /][variable func><][keyword /][variable x>]", - " [keyword let] [variable $joe][keyword :=][atom 1]", - " [keyword return] [keyword element] [variable element] {", - " [keyword attribute] [variable attribute] { [atom 1] },", - " [keyword element] [variable test] { [variable 'a'] }, [keyword attribute] [variable foo] { [variable "bar"] },", - " [def&variable fn:doc]()[[ [variable foo][keyword /][variable @bar] [keyword eq] [variable $let] ]],", - " [keyword //][variable x] } [comment (: a more 'evil' test :)]", - " [comment (: Modified Blakeley example (: with nested comment :) ... :)]", - " [keyword declare] [keyword private] [keyword function] [def&variable local:declare]() {()}[variable ;]", - " [keyword declare] [keyword private] [keyword function] [def&variable local:private]() {()}[variable ;]", - " [keyword declare] [keyword private] [keyword function] [def&variable local:function]() {()}[variable ;]", - " [keyword declare] [keyword private] [keyword function] [def&variable local:local]() {()}[variable ;]", - " [keyword let] [variable $let] [keyword :=] [variable <let>let] [variable $let] [keyword :=] [variable "let"<][keyword /let][variable >]", - " [keyword return] [keyword element] [variable element] {", - " [keyword attribute] [variable attribute] { [keyword try] { [def&variable xdmp:version]() } [keyword catch]([variable $e]) { [def&variable xdmp:log]([variable $e]) } },", - " [keyword attribute] [variable fn:doc] { [variable "bar"] [variable castable] [keyword as] [atom xs:string] },", - " [keyword element] [variable text] { [keyword text] { [variable "text"] } },", - " [def&variable fn:doc]()[[ [qualifier child::][variable eq][keyword /]([variable @bar] [keyword |] [qualifier attribute::][variable attribute]) [keyword eq] [variable $let] ]],", - " [keyword //][variable fn:doc]", - " }"); - - MT("testEmptySequenceKeyword", - "[string \"foo\"] [keyword instance] [keyword of] [keyword empty-sequence]()"); - - MT("testMultiAttr", - "[tag

    ][variable hello] [variable world][tag

    ]"); - - MT("test namespaced variable", - "[keyword declare] [keyword namespace] [variable e] [keyword =] [string \"http://example.com/ANamespace\"][variable ;declare] [keyword variable] [variable $e:exampleComThisVarIsNotRecognized] [keyword as] [keyword element]([keyword *]) [variable external;]"); - - MT("test EQName variable", - "[keyword declare] [keyword variable] [variable $\"http://www.example.com/ns/my\":var] [keyword :=] [atom 12][variable ;]", - "[tag ]{[variable $\"http://www.example.com/ns/my\":var]}[tag ]"); - - MT("test EQName function", - "[keyword declare] [keyword function] [def&variable \"http://www.example.com/ns/my\":fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {", - " [variable $a] [keyword +] [atom 2]", - "}[variable ;]", - "[tag ]{[def&variable \"http://www.example.com/ns/my\":fn]([atom 12])}[tag ]"); - - MT("test EQName function with single quotes", - "[keyword declare] [keyword function] [def&variable 'http://www.example.com/ns/my':fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {", - " [variable $a] [keyword +] [atom 2]", - "}[variable ;]", - "[tag ]{[def&variable 'http://www.example.com/ns/my':fn]([atom 12])}[tag ]"); - - MT("testProcessingInstructions", - "[def&variable data]([comment&meta ]) [keyword instance] [keyword of] [atom xs:string]"); - - MT("testQuoteEscapeDouble", - "[keyword let] [variable $rootfolder] [keyword :=] [string \"c:\\builds\\winnt\\HEAD\\qa\\scripts\\\"]", - "[keyword let] [variable $keysfolder] [keyword :=] [def&variable concat]([variable $rootfolder], [string \"keys\\\"])"); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/mode/xquery/xquery.js b/shared/html/libs/codemirror/5.0.0/mode/xquery/xquery.js deleted file mode 100644 index c8f3d90..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/xquery/xquery.js +++ /dev/null @@ -1,447 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("xquery", function() { - - // The keywords object is set to the result of this self executing - // function. Each keyword is a property of the keywords object whose - // value is {type: atype, style: astyle} - var keywords = function(){ - // conveinence functions used to build keywords object - function kw(type) {return {type: type, style: "keyword"};} - var A = kw("keyword a") - , B = kw("keyword b") - , C = kw("keyword c") - , operator = kw("operator") - , atom = {type: "atom", style: "atom"} - , punctuation = {type: "punctuation", style: null} - , qualifier = {type: "axis_specifier", style: "qualifier"}; - - // kwObj is what is return from this function at the end - var kwObj = { - 'if': A, 'switch': A, 'while': A, 'for': A, - 'else': B, 'then': B, 'try': B, 'finally': B, 'catch': B, - 'element': C, 'attribute': C, 'let': C, 'implements': C, 'import': C, 'module': C, 'namespace': C, - 'return': C, 'super': C, 'this': C, 'throws': C, 'where': C, 'private': C, - ',': punctuation, - 'null': atom, 'fn:false()': atom, 'fn:true()': atom - }; - - // a list of 'basic' keywords. For each add a property to kwObj with the value of - // {type: basic[i], style: "keyword"} e.g. 'after' --> {type: "after", style: "keyword"} - var basic = ['after','ancestor','ancestor-or-self','and','as','ascending','assert','attribute','before', - 'by','case','cast','child','comment','declare','default','define','descendant','descendant-or-self', - 'descending','document','document-node','element','else','eq','every','except','external','following', - 'following-sibling','follows','for','function','if','import','in','instance','intersect','item', - 'let','module','namespace','node','node','of','only','or','order','parent','precedes','preceding', - 'preceding-sibling','processing-instruction','ref','return','returns','satisfies','schema','schema-element', - 'self','some','sortby','stable','text','then','to','treat','typeswitch','union','variable','version','where', - 'xquery', 'empty-sequence']; - for(var i=0, l=basic.length; i < l; i++) { kwObj[basic[i]] = kw(basic[i]);}; - - // a list of types. For each add a property to kwObj with the value of - // {type: "atom", style: "atom"} - var types = ['xs:string', 'xs:float', 'xs:decimal', 'xs:double', 'xs:integer', 'xs:boolean', 'xs:date', 'xs:dateTime', - 'xs:time', 'xs:duration', 'xs:dayTimeDuration', 'xs:time', 'xs:yearMonthDuration', 'numeric', 'xs:hexBinary', - 'xs:base64Binary', 'xs:anyURI', 'xs:QName', 'xs:byte','xs:boolean','xs:anyURI','xf:yearMonthDuration']; - for(var i=0, l=types.length; i < l; i++) { kwObj[types[i]] = atom;}; - - // each operator will add a property to kwObj with value of {type: "operator", style: "keyword"} - var operators = ['eq', 'ne', 'lt', 'le', 'gt', 'ge', ':=', '=', '>', '>=', '<', '<=', '.', '|', '?', 'and', 'or', 'div', 'idiv', 'mod', '*', '/', '+', '-']; - for(var i=0, l=operators.length; i < l; i++) { kwObj[operators[i]] = operator;}; - - // each axis_specifiers will add a property to kwObj with value of {type: "axis_specifier", style: "qualifier"} - var axis_specifiers = ["self::", "attribute::", "child::", "descendant::", "descendant-or-self::", "parent::", - "ancestor::", "ancestor-or-self::", "following::", "preceding::", "following-sibling::", "preceding-sibling::"]; - for(var i=0, l=axis_specifiers.length; i < l; i++) { kwObj[axis_specifiers[i]] = qualifier; }; - - return kwObj; - }(); - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - - function ret(tp, style, cont) { - type = tp; content = cont; - return style; - } - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - // the primary mode tokenizer - function tokenBase(stream, state) { - var ch = stream.next(), - mightBeFunction = false, - isEQName = isEQNameAhead(stream); - - // an XML tag (if not in some sub, chained tokenizer) - if (ch == "<") { - if(stream.match("!--", true)) - return chain(stream, state, tokenXMLComment); - - if(stream.match("![CDATA", false)) { - state.tokenize = tokenCDATA; - return ret("tag", "tag"); - } - - if(stream.match("?", false)) { - return chain(stream, state, tokenPreProcessing); - } - - var isclose = stream.eat("/"); - stream.eatSpace(); - var tagName = "", c; - while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c; - - return chain(stream, state, tokenTag(tagName, isclose)); - } - // start code block - else if(ch == "{") { - pushStateStack(state,{ type: "codeblock"}); - return ret("", null); - } - // end code block - else if(ch == "}") { - popStateStack(state); - return ret("", null); - } - // if we're in an XML block - else if(isInXmlBlock(state)) { - if(ch == ">") - return ret("tag", "tag"); - else if(ch == "/" && stream.eat(">")) { - popStateStack(state); - return ret("tag", "tag"); - } - else - return ret("word", "variable"); - } - // if a number - else if (/\d/.test(ch)) { - stream.match(/^\d*(?:\.\d*)?(?:E[+\-]?\d+)?/); - return ret("number", "atom"); - } - // comment start - else if (ch === "(" && stream.eat(":")) { - pushStateStack(state, { type: "comment"}); - return chain(stream, state, tokenComment); - } - // quoted string - else if ( !isEQName && (ch === '"' || ch === "'")) - return chain(stream, state, tokenString(ch)); - // variable - else if(ch === "$") { - return chain(stream, state, tokenVariable); - } - // assignment - else if(ch ===":" && stream.eat("=")) { - return ret("operator", "keyword"); - } - // open paren - else if(ch === "(") { - pushStateStack(state, { type: "paren"}); - return ret("", null); - } - // close paren - else if(ch === ")") { - popStateStack(state); - return ret("", null); - } - // open paren - else if(ch === "[") { - pushStateStack(state, { type: "bracket"}); - return ret("", null); - } - // close paren - else if(ch === "]") { - popStateStack(state); - return ret("", null); - } - else { - var known = keywords.propertyIsEnumerable(ch) && keywords[ch]; - - // if there's a EQName ahead, consume the rest of the string portion, it's likely a function - if(isEQName && ch === '\"') while(stream.next() !== '"'){} - if(isEQName && ch === '\'') while(stream.next() !== '\''){} - - // gobble up a word if the character is not known - if(!known) stream.eatWhile(/[\w\$_-]/); - - // gobble a colon in the case that is a lib func type call fn:doc - var foundColon = stream.eat(":"); - - // if there's not a second colon, gobble another word. Otherwise, it's probably an axis specifier - // which should get matched as a keyword - if(!stream.eat(":") && foundColon) { - stream.eatWhile(/[\w\$_-]/); - } - // if the next non whitespace character is an open paren, this is probably a function (if not a keyword of other sort) - if(stream.match(/^[ \t]*\(/, false)) { - mightBeFunction = true; - } - // is the word a keyword? - var word = stream.current(); - known = keywords.propertyIsEnumerable(word) && keywords[word]; - - // if we think it's a function call but not yet known, - // set style to variable for now for lack of something better - if(mightBeFunction && !known) known = {type: "function_call", style: "variable def"}; - - // if the previous word was element, attribute, axis specifier, this word should be the name of that - if(isInXmlConstructor(state)) { - popStateStack(state); - return ret("word", "variable", word); - } - // as previously checked, if the word is element,attribute, axis specifier, call it an "xmlconstructor" and - // push the stack so we know to look for it on the next word - if(word == "element" || word == "attribute" || known.type == "axis_specifier") pushStateStack(state, {type: "xmlconstructor"}); - - // if the word is known, return the details of that else just call this a generic 'word' - return known ? ret(known.type, known.style, word) : - ret("word", "variable", word); - } - } - - // handle comments, including nested - function tokenComment(stream, state) { - var maybeEnd = false, maybeNested = false, nestedCount = 0, ch; - while (ch = stream.next()) { - if (ch == ")" && maybeEnd) { - if(nestedCount > 0) - nestedCount--; - else { - popStateStack(state); - break; - } - } - else if(ch == ":" && maybeNested) { - nestedCount++; - } - maybeEnd = (ch == ":"); - maybeNested = (ch == "("); - } - - return ret("comment", "comment"); - } - - // tokenizer for string literals - // optionally pass a tokenizer function to set state.tokenize back to when finished - function tokenString(quote, f) { - return function(stream, state) { - var ch; - - if(isInString(state) && stream.current() == quote) { - popStateStack(state); - if(f) state.tokenize = f; - return ret("string", "string"); - } - - pushStateStack(state, { type: "string", name: quote, tokenize: tokenString(quote, f) }); - - // if we're in a string and in an XML block, allow an embedded code block - if(stream.match("{", false) && isInXmlAttributeBlock(state)) { - state.tokenize = tokenBase; - return ret("string", "string"); - } - - - while (ch = stream.next()) { - if (ch == quote) { - popStateStack(state); - if(f) state.tokenize = f; - break; - } - else { - // if we're in a string and in an XML block, allow an embedded code block in an attribute - if(stream.match("{", false) && isInXmlAttributeBlock(state)) { - state.tokenize = tokenBase; - return ret("string", "string"); - } - - } - } - - return ret("string", "string"); - }; - } - - // tokenizer for variables - function tokenVariable(stream, state) { - var isVariableChar = /[\w\$_-]/; - - // a variable may start with a quoted EQName so if the next character is quote, consume to the next quote - if(stream.eat("\"")) { - while(stream.next() !== '\"'){}; - stream.eat(":"); - } else { - stream.eatWhile(isVariableChar); - if(!stream.match(":=", false)) stream.eat(":"); - } - stream.eatWhile(isVariableChar); - state.tokenize = tokenBase; - return ret("variable", "variable"); - } - - // tokenizer for XML tags - function tokenTag(name, isclose) { - return function(stream, state) { - stream.eatSpace(); - if(isclose && stream.eat(">")) { - popStateStack(state); - state.tokenize = tokenBase; - return ret("tag", "tag"); - } - // self closing tag without attributes? - if(!stream.eat("/")) - pushStateStack(state, { type: "tag", name: name, tokenize: tokenBase}); - if(!stream.eat(">")) { - state.tokenize = tokenAttribute; - return ret("tag", "tag"); - } - else { - state.tokenize = tokenBase; - } - return ret("tag", "tag"); - }; - } - - // tokenizer for XML attributes - function tokenAttribute(stream, state) { - var ch = stream.next(); - - if(ch == "/" && stream.eat(">")) { - if(isInXmlAttributeBlock(state)) popStateStack(state); - if(isInXmlBlock(state)) popStateStack(state); - return ret("tag", "tag"); - } - if(ch == ">") { - if(isInXmlAttributeBlock(state)) popStateStack(state); - return ret("tag", "tag"); - } - if(ch == "=") - return ret("", null); - // quoted string - if (ch == '"' || ch == "'") - return chain(stream, state, tokenString(ch, tokenAttribute)); - - if(!isInXmlAttributeBlock(state)) - pushStateStack(state, { type: "attribute", tokenize: tokenAttribute}); - - stream.eat(/[a-zA-Z_:]/); - stream.eatWhile(/[-a-zA-Z0-9_:.]/); - stream.eatSpace(); - - // the case where the attribute has not value and the tag was closed - if(stream.match(">", false) || stream.match("/", false)) { - popStateStack(state); - state.tokenize = tokenBase; - } - - return ret("attribute", "attribute"); - } - - // handle comments, including nested - function tokenXMLComment(stream, state) { - var ch; - while (ch = stream.next()) { - if (ch == "-" && stream.match("->", true)) { - state.tokenize = tokenBase; - return ret("comment", "comment"); - } - } - } - - - // handle CDATA - function tokenCDATA(stream, state) { - var ch; - while (ch = stream.next()) { - if (ch == "]" && stream.match("]", true)) { - state.tokenize = tokenBase; - return ret("comment", "comment"); - } - } - } - - // handle preprocessing instructions - function tokenPreProcessing(stream, state) { - var ch; - while (ch = stream.next()) { - if (ch == "?" && stream.match(">", true)) { - state.tokenize = tokenBase; - return ret("comment", "comment meta"); - } - } - } - - - // functions to test the current context of the state - function isInXmlBlock(state) { return isIn(state, "tag"); } - function isInXmlAttributeBlock(state) { return isIn(state, "attribute"); } - function isInXmlConstructor(state) { return isIn(state, "xmlconstructor"); } - function isInString(state) { return isIn(state, "string"); } - - function isEQNameAhead(stream) { - // assume we've already eaten a quote (") - if(stream.current() === '"') - return stream.match(/^[^\"]+\"\:/, false); - else if(stream.current() === '\'') - return stream.match(/^[^\"]+\'\:/, false); - else - return false; - } - - function isIn(state, type) { - return (state.stack.length && state.stack[state.stack.length - 1].type == type); - } - - function pushStateStack(state, newState) { - state.stack.push(newState); - } - - function popStateStack(state) { - state.stack.pop(); - var reinstateTokenize = state.stack.length && state.stack[state.stack.length-1].tokenize; - state.tokenize = reinstateTokenize || tokenBase; - } - - // the interface for the mode API - return { - startState: function() { - return { - tokenize: tokenBase, - cc: [], - stack: [] - }; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - return style; - }, - - blockCommentStart: "(:", - blockCommentEnd: ":)" - - }; - -}); - -CodeMirror.defineMIME("application/xquery", "xquery"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/yaml/index.html b/shared/html/libs/codemirror/5.0.0/mode/yaml/index.html deleted file mode 100644 index be9b632..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/yaml/index.html +++ /dev/null @@ -1,80 +0,0 @@ - - -CodeMirror: YAML mode - - - - - - - - - -
    -

    YAML mode

    -
    - - -

    MIME types defined: text/x-yaml.

    - -
    diff --git a/shared/html/libs/codemirror/5.0.0/mode/yaml/yaml.js b/shared/html/libs/codemirror/5.0.0/mode/yaml/yaml.js deleted file mode 100644 index b7015e5..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/yaml/yaml.js +++ /dev/null @@ -1,117 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("yaml", function() { - - var cons = ['true', 'false', 'on', 'off', 'yes', 'no']; - var keywordRegex = new RegExp("\\b(("+cons.join(")|(")+"))$", 'i'); - - return { - token: function(stream, state) { - var ch = stream.peek(); - var esc = state.escaped; - state.escaped = false; - /* comments */ - if (ch == "#" && (stream.pos == 0 || /\s/.test(stream.string.charAt(stream.pos - 1)))) { - stream.skipToEnd(); - return "comment"; - } - - if (stream.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/)) - return "string"; - - if (state.literal && stream.indentation() > state.keyCol) { - stream.skipToEnd(); return "string"; - } else if (state.literal) { state.literal = false; } - if (stream.sol()) { - state.keyCol = 0; - state.pair = false; - state.pairStart = false; - /* document start */ - if(stream.match(/---/)) { return "def"; } - /* document end */ - if (stream.match(/\.\.\./)) { return "def"; } - /* array list item */ - if (stream.match(/\s*-\s+/)) { return 'meta'; } - } - /* inline pairs/lists */ - if (stream.match(/^(\{|\}|\[|\])/)) { - if (ch == '{') - state.inlinePairs++; - else if (ch == '}') - state.inlinePairs--; - else if (ch == '[') - state.inlineList++; - else - state.inlineList--; - return 'meta'; - } - - /* list seperator */ - if (state.inlineList > 0 && !esc && ch == ',') { - stream.next(); - return 'meta'; - } - /* pairs seperator */ - if (state.inlinePairs > 0 && !esc && ch == ',') { - state.keyCol = 0; - state.pair = false; - state.pairStart = false; - stream.next(); - return 'meta'; - } - - /* start of value of a pair */ - if (state.pairStart) { - /* block literals */ - if (stream.match(/^\s*(\||\>)\s*/)) { state.literal = true; return 'meta'; }; - /* references */ - if (stream.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i)) { return 'variable-2'; } - /* numbers */ - if (state.inlinePairs == 0 && stream.match(/^\s*-?[0-9\.\,]+\s?$/)) { return 'number'; } - if (state.inlinePairs > 0 && stream.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/)) { return 'number'; } - /* keywords */ - if (stream.match(keywordRegex)) { return 'keyword'; } - } - - /* pairs (associative arrays) -> key */ - if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)) { - state.pair = true; - state.keyCol = stream.indentation(); - return "atom"; - } - if (state.pair && stream.match(/^:\s*/)) { state.pairStart = true; return 'meta'; } - - /* nothing found, continue */ - state.pairStart = false; - state.escaped = (ch == '\\'); - stream.next(); - return null; - }, - startState: function() { - return { - pair: false, - pairStart: false, - keyCol: 0, - inlinePairs: 0, - inlineList: 0, - literal: false, - escaped: false - }; - } - }; -}); - -CodeMirror.defineMIME("text/x-yaml", "yaml"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/mode/z80/index.html b/shared/html/libs/codemirror/5.0.0/mode/z80/index.html deleted file mode 100644 index 1ad3ace..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/z80/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - -CodeMirror: Z80 assembly mode - - - - - - - - - -
    -

    Z80 assembly mode

    - - -
    - - - -

    MIME type defined: text/x-z80.

    -
    diff --git a/shared/html/libs/codemirror/5.0.0/mode/z80/z80.js b/shared/html/libs/codemirror/5.0.0/mode/z80/z80.js deleted file mode 100644 index ec41d05..0000000 --- a/shared/html/libs/codemirror/5.0.0/mode/z80/z80.js +++ /dev/null @@ -1,100 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('z80', function() { - var keywords1 = /^(exx?|(ld|cp|in)([di]r?)?|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|rst|[de]i|halt|im|ot[di]r|out[di]?)\b/i; - var keywords2 = /^(call|j[pr]|ret[in]?)\b/i; - var keywords3 = /^b_?(call|jump)\b/i; - var variables1 = /^(af?|bc?|c|de?|e|hl?|l|i[xy]?|r|sp)\b/i; - var variables2 = /^(n?[zc]|p[oe]?|m)\b/i; - var errors = /^([hl][xy]|i[xy][hl]|slia|sll)\b/i; - var numbers = /^([\da-f]+h|[0-7]+o|[01]+b|\d+)\b/i; - - return { - startState: function() { - return {context: 0}; - }, - token: function(stream, state) { - if (!stream.column()) - state.context = 0; - - if (stream.eatSpace()) - return null; - - var w; - - if (stream.eatWhile(/\w/)) { - w = stream.current(); - - if (stream.indentation()) { - if (state.context == 1 && variables1.test(w)) - return 'variable-2'; - - if (state.context == 2 && variables2.test(w)) - return 'variable-3'; - - if (keywords1.test(w)) { - state.context = 1; - return 'keyword'; - } else if (keywords2.test(w)) { - state.context = 2; - return 'keyword'; - } else if (keywords3.test(w)) { - state.context = 3; - return 'keyword'; - } - - if (errors.test(w)) - return 'error'; - } else if (numbers.test(w)) { - return 'number'; - } else { - return null; - } - } else if (stream.eat(';')) { - stream.skipToEnd(); - return 'comment'; - } else if (stream.eat('"')) { - while (w = stream.next()) { - if (w == '"') - break; - - if (w == '\\') - stream.next(); - } - return 'string'; - } else if (stream.eat('\'')) { - if (stream.match(/\\?.'/)) - return 'number'; - } else if (stream.eat('.') || stream.sol() && stream.eat('#')) { - state.context = 4; - - if (stream.eatWhile(/\w/)) - return 'def'; - } else if (stream.eat('$')) { - if (stream.eatWhile(/[\da-f]/i)) - return 'number'; - } else if (stream.eat('%')) { - if (stream.eatWhile(/[01]/)) - return 'number'; - } else { - stream.next(); - } - return null; - } - }; -}); - -CodeMirror.defineMIME("text/x-z80", "z80"); - -}); diff --git a/shared/html/libs/codemirror/5.0.0/package.json b/shared/html/libs/codemirror/5.0.0/package.json deleted file mode 100644 index b4a9b53..0000000 --- a/shared/html/libs/codemirror/5.0.0/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "codemirror", - "version":"5.0.0", - "main": "lib/codemirror.js", - "description": "In-browser code editing made bearable", - "licenses": [{"type": "MIT", - "url": "http://codemirror.net/LICENSE"}], - "directories": {"lib": "./lib"}, - "scripts": {"test": "node ./test/run.js"}, - "devDependencies": {"node-static": "0.6.0", - "phantomjs": "1.9.2-5", - "blint": ">=0.1.1"}, - "bugs": "http://github.com/codemirror/CodeMirror/issues", - "keywords": ["JavaScript", "CodeMirror", "Editor"], - "homepage": "http://codemirror.net", - "maintainers":[{"name": "Marijn Haverbeke", - "email": "marijnh@gmail.com", - "web": "http://marijnhaverbeke.nl"}], - "repository": {"type": "git", - "url": "https://github.com/codemirror/CodeMirror.git"} -} diff --git a/shared/html/libs/codemirror/5.0.0/test/comment_test.js b/shared/html/libs/codemirror/5.0.0/test/comment_test.js deleted file mode 100644 index 8bd3959..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/comment_test.js +++ /dev/null @@ -1,100 +0,0 @@ -namespace = "comment_"; - -(function() { - function test(name, mode, run, before, after) { - return testCM(name, function(cm) { - run(cm); - eq(cm.getValue(), after); - }, {value: before, mode: mode}); - } - - var simpleProg = "function foo() {\n return bar;\n}"; - var inlineBlock = "foo(/* bar */ true);"; - var inlineBlocks = "foo(/* bar */ true, /* baz */ false);"; - var multiLineInlineBlock = ["above();", "foo(/* bar */ true);", "below();"]; - - test("block", "javascript", function(cm) { - cm.blockComment(Pos(0, 3), Pos(3, 0), {blockCommentLead: " *"}); - }, simpleProg + "\n", "/* function foo() {\n * return bar;\n * }\n */"); - - test("blockToggle", "javascript", function(cm) { - cm.blockComment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"}); - cm.uncomment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"}); - }, simpleProg, simpleProg); - - test("blockToggle2", "javascript", function(cm) { - cm.setCursor({line: 0, ch: 7 /* inside the block comment */}); - cm.execCommand("toggleComment"); - }, inlineBlock, "foo(bar true);"); - - // This test should work but currently fails. - // test("blockToggle3", "javascript", function(cm) { - // cm.setCursor({line: 0, ch: 7 /* inside the first block comment */}); - // cm.execCommand("toggleComment"); - // }, inlineBlocks, "foo(bar true, /* baz */ false);"); - - test("line", "javascript", function(cm) { - cm.lineComment(Pos(1, 1), Pos(1, 1)); - }, simpleProg, "function foo() {\n// return bar;\n}"); - - test("lineToggle", "javascript", function(cm) { - cm.lineComment(Pos(0, 0), Pos(2, 1)); - cm.uncomment(Pos(0, 0), Pos(2, 1)); - }, simpleProg, simpleProg); - - test("fallbackToBlock", "css", function(cm) { - cm.lineComment(Pos(0, 0), Pos(2, 1)); - }, "html {\n border: none;\n}", "/* html {\n border: none;\n} */"); - - test("fallbackToLine", "ruby", function(cm) { - cm.blockComment(Pos(0, 0), Pos(1)); - }, "def blah()\n return hah\n", "# def blah()\n# return hah\n"); - - test("ignoreExternalBlockComments", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, inlineBlocks, "// " + inlineBlocks); - - test("ignoreExternalBlockComments2", "javascript", function(cm) { - cm.setCursor({line: 0, ch: null /* eol */}); - cm.execCommand("toggleComment"); - }, inlineBlocks, "// " + inlineBlocks); - - test("ignoreExternalBlockCommentsMultiLineAbove", "javascript", function(cm) { - cm.setSelection({line: 0, ch: 0}, {line: 1, ch: 1}); - cm.execCommand("toggleComment"); - }, multiLineInlineBlock.join("\n"), ["// " + multiLineInlineBlock[0], - "// " + multiLineInlineBlock[1], - multiLineInlineBlock[2]].join("\n")); - - test("ignoreExternalBlockCommentsMultiLineBelow", "javascript", function(cm) { - cm.setSelection({line: 1, ch: 13 /* after end of block comment */}, {line: 2, ch: 1}); - cm.execCommand("toggleComment"); - }, multiLineInlineBlock.join("\n"), [multiLineInlineBlock[0], - "// " + multiLineInlineBlock[1], - "// " + multiLineInlineBlock[2]].join("\n")); - - test("commentRange", "javascript", function(cm) { - cm.blockComment(Pos(1, 2), Pos(1, 13), {fullLines: false}); - }, simpleProg, "function foo() {\n /*return bar;*/\n}"); - - test("indented", "javascript", function(cm) { - cm.lineComment(Pos(1, 0), Pos(2), {indent: true}); - }, simpleProg, "function foo() {\n // return bar;\n // }"); - - test("singleEmptyLine", "javascript", function(cm) { - cm.setCursor(1); - cm.execCommand("toggleComment"); - }, "a;\n\nb;", "a;\n// \nb;"); - - test("dontMessWithStrings", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, "console.log(\"/*string*/\");", "// console.log(\"/*string*/\");"); - - test("dontMessWithStrings2", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, "console.log(\"// string\");", "// console.log(\"// string\");"); - - test("dontMessWithStrings3", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, "// console.log(\"// string\");", "console.log(\"// string\");"); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/test/doc_test.js b/shared/html/libs/codemirror/5.0.0/test/doc_test.js deleted file mode 100644 index 5f242f6..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/doc_test.js +++ /dev/null @@ -1,371 +0,0 @@ -(function() { - // A minilanguage for instantiating linked CodeMirror instances and Docs - function instantiateSpec(spec, place, opts) { - var names = {}, pos = 0, l = spec.length, editors = []; - while (spec) { - var m = spec.match(/^(\w+)(\*?)(?:='([^\']*)'|<(~?)(\w+)(?:\/(\d+)-(\d+))?)\s*/); - var name = m[1], isDoc = m[2], cur; - if (m[3]) { - cur = isDoc ? CodeMirror.Doc(m[3]) : CodeMirror(place, clone(opts, {value: m[3]})); - } else { - var other = m[5]; - if (!names.hasOwnProperty(other)) { - names[other] = editors.length; - editors.push(CodeMirror(place, opts)); - } - var doc = editors[names[other]].linkedDoc({ - sharedHist: !m[4], - from: m[6] ? Number(m[6]) : null, - to: m[7] ? Number(m[7]) : null - }); - cur = isDoc ? doc : CodeMirror(place, clone(opts, {value: doc})); - } - names[name] = editors.length; - editors.push(cur); - spec = spec.slice(m[0].length); - } - return editors; - } - - function clone(obj, props) { - if (!obj) return; - clone.prototype = obj; - var inst = new clone(); - if (props) for (var n in props) if (props.hasOwnProperty(n)) - inst[n] = props[n]; - return inst; - } - - function eqAll(val) { - var end = arguments.length, msg = null; - if (typeof arguments[end-1] == "string") - msg = arguments[--end]; - if (i == end) throw new Error("No editors provided to eqAll"); - for (var i = 1; i < end; ++i) - eq(arguments[i].getValue(), val, msg) - } - - function testDoc(name, spec, run, opts, expectFail) { - if (!opts) opts = {}; - - return test("doc_" + name, function() { - var place = document.getElementById("testground"); - var editors = instantiateSpec(spec, place, opts); - var successful = false; - - try { - run.apply(null, editors); - successful = true; - } finally { - if (!successful || verbose) { - place.style.visibility = "visible"; - } else { - for (var i = 0; i < editors.length; ++i) - if (editors[i] instanceof CodeMirror) - place.removeChild(editors[i].getWrapperElement()); - } - } - }, expectFail); - } - - var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent); - - function testBasic(a, b) { - eqAll("x", a, b); - a.setValue("hey"); - eqAll("hey", a, b); - b.setValue("wow"); - eqAll("wow", a, b); - a.replaceRange("u\nv\nw", Pos(0, 3)); - b.replaceRange("i", Pos(0, 4)); - b.replaceRange("j", Pos(2, 1)); - eqAll("wowui\nv\nwj", a, b); - } - - testDoc("basic", "A='x' B 0, "not at left"); - is(pos.top > 0, "not at top"); - }); - - testDoc("copyDoc", "A='u'", function(a) { - var copy = a.getDoc().copy(true); - a.setValue("foo"); - copy.setValue("bar"); - var old = a.swapDoc(copy); - eq(a.getValue(), "bar"); - a.undo(); - eq(a.getValue(), "u"); - a.swapDoc(old); - eq(a.getValue(), "foo"); - eq(old.historySize().undo, 1); - eq(old.copy(false).historySize().undo, 0); - }); - - testDoc("docKeepsMode", "A='1+1'", function(a) { - var other = CodeMirror.Doc("hi", "text/x-markdown"); - a.setOption("mode", "text/javascript"); - var old = a.swapDoc(other); - eq(a.getOption("mode"), "text/x-markdown"); - eq(a.getMode().name, "markdown"); - a.swapDoc(old); - eq(a.getOption("mode"), "text/javascript"); - eq(a.getMode().name, "javascript"); - }); - - testDoc("subview", "A='1\n2\n3\n4\n5' B<~A/1-3", function(a, b) { - eq(b.getValue(), "2\n3"); - eq(b.firstLine(), 1); - b.setCursor(Pos(4)); - eqPos(b.getCursor(), Pos(2, 1)); - a.replaceRange("-1\n0\n", Pos(0, 0)); - eq(b.firstLine(), 3); - eqPos(b.getCursor(), Pos(4, 1)); - a.undo(); - eqPos(b.getCursor(), Pos(2, 1)); - b.replaceRange("oyoy\n", Pos(2, 0)); - eq(a.getValue(), "1\n2\noyoy\n3\n4\n5"); - b.undo(); - eq(a.getValue(), "1\n2\n3\n4\n5"); - }); - - testDoc("subviewEditOnBoundary", "A='11\n22\n33\n44\n55' B<~A/1-4", function(a, b) { - a.replaceRange("x\nyy\nz", Pos(0, 1), Pos(2, 1)); - eq(b.firstLine(), 2); - eq(b.lineCount(), 2); - eq(b.getValue(), "z3\n44"); - a.replaceRange("q\nrr\ns", Pos(3, 1), Pos(4, 1)); - eq(b.firstLine(), 2); - eq(b.getValue(), "z3\n4q"); - eq(a.getValue(), "1x\nyy\nz3\n4q\nrr\ns5"); - a.execCommand("selectAll"); - a.replaceSelection("!"); - eqAll("!", a, b); - }); - - - testDoc("sharedMarker", "A='ab\ncd\nef\ngh' B 500){ - totalTime = 0; - delay = 50; - } - setTimeout(function(){step(i + 1);}, delay); - } else { // Quit tests - running = false; - return null; - } - } - step(0); -} - -function label(str, msg) { - if (msg) return str + " (" + msg + ")"; - return str; -} -function eq(a, b, msg) { - if (a != b) throw new Failure(label(a + " != " + b, msg)); -} -function near(a, b, margin, msg) { - if (Math.abs(a - b) > margin) - throw new Failure(label(a + " is not close to " + b + " (" + margin + ")", msg)); -} -function eqPos(a, b, msg) { - function str(p) { return "{line:" + p.line + ",ch:" + p.ch + "}"; } - if (a == b) return; - if (a == null) throw new Failure(label("comparing null to " + str(b), msg)); - if (b == null) throw new Failure(label("comparing " + str(a) + " to null", msg)); - if (a.line != b.line || a.ch != b.ch) throw new Failure(label(str(a) + " != " + str(b), msg)); -} -function is(a, msg) { - if (!a) throw new Failure(label("assertion failed", msg)); -} - -function countTests() { - if (!filters.length) return tests.length; - var sum = 0; - for (var i = 0; i < tests.length; ++i) { - var name = tests[i].name; - for (var j = 0; j < filters.length; j++) { - if (name.match(filters[j])) { - ++sum; - break; - } - } - } - return sum; -} - -function parseTestFilter(s) { - if (/_\*$/.test(s)) return new RegExp("^" + s.slice(0, s.length - 2), "i"); - else return new RegExp(s, "i"); -} diff --git a/shared/html/libs/codemirror/5.0.0/test/emacs_test.js b/shared/html/libs/codemirror/5.0.0/test/emacs_test.js deleted file mode 100644 index ccbd6ce..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/emacs_test.js +++ /dev/null @@ -1,141 +0,0 @@ -(function() { - "use strict"; - - var Pos = CodeMirror.Pos; - namespace = "emacs_"; - - var eventCache = {}; - function fakeEvent(keyName) { - var event = eventCache[key]; - if (event) return event; - - var ctrl, shift, alt; - var key = keyName.replace(/\w+-/g, function(type) { - if (type == "Ctrl-") ctrl = true; - else if (type == "Alt-") alt = true; - else if (type == "Shift-") shift = true; - return ""; - }); - var code; - for (var c in CodeMirror.keyNames) - if (CodeMirror.keyNames[c] == key) { code = c; break; } - if (c == null) throw new Error("Unknown key: " + key); - - return eventCache[keyName] = { - type: "keydown", keyCode: code, ctrlKey: ctrl, shiftKey: shift, altKey: alt, - preventDefault: function(){}, stopPropagation: function(){} - }; - } - - function sim(name, start /*, actions... */) { - var keys = Array.prototype.slice.call(arguments, 2); - testCM(name, function(cm) { - for (var i = 0; i < keys.length; ++i) { - var cur = keys[i]; - if (cur instanceof Pos) cm.setCursor(cur); - else if (cur.call) cur(cm); - else cm.triggerOnKeyDown(fakeEvent(cur)); - } - }, {keyMap: "emacs", value: start, mode: "javascript"}); - } - - function at(line, ch) { return function(cm) { eqPos(cm.getCursor(), Pos(line, ch)); }; } - function txt(str) { return function(cm) { eq(cm.getValue(), str); }; } - - sim("motionHSimple", "abc", "Ctrl-F", "Ctrl-F", "Ctrl-B", at(0, 1)); - sim("motionHMulti", "abcde", - "Ctrl-4", "Ctrl-F", at(0, 4), "Ctrl--", "Ctrl-2", "Ctrl-F", at(0, 2), - "Ctrl-5", "Ctrl-B", at(0, 0)); - - sim("motionHWord", "abc. def ghi", - "Alt-F", at(0, 3), "Alt-F", at(0, 8), - "Ctrl-B", "Alt-B", at(0, 5), "Alt-B", at(0, 0)); - sim("motionHWordMulti", "abc. def ghi ", - "Ctrl-3", "Alt-F", at(0, 12), "Ctrl-2", "Alt-B", at(0, 5), - "Ctrl--", "Alt-B", at(0, 8)); - - sim("motionVSimple", "a\nb\nc\n", "Ctrl-N", "Ctrl-N", "Ctrl-P", at(1, 0)); - sim("motionVMulti", "a\nb\nc\nd\ne\n", - "Ctrl-2", "Ctrl-N", at(2, 0), "Ctrl-F", "Ctrl--", "Ctrl-N", at(1, 1), - "Ctrl--", "Ctrl-3", "Ctrl-P", at(4, 1)); - - sim("killYank", "abc\ndef\nghi", - "Ctrl-F", "Ctrl-Space", "Ctrl-N", "Ctrl-N", "Ctrl-W", "Ctrl-E", "Ctrl-Y", - txt("ahibc\ndef\ng")); - sim("killRing", "abcdef", - "Ctrl-Space", "Ctrl-F", "Ctrl-W", "Ctrl-Space", "Ctrl-F", "Ctrl-W", - "Ctrl-Y", "Alt-Y", - txt("acdef")); - sim("copyYank", "abcd", - "Ctrl-Space", "Ctrl-E", "Alt-W", "Ctrl-Y", - txt("abcdabcd")); - - sim("killLineSimple", "foo\nbar", "Ctrl-F", "Ctrl-K", txt("f\nbar")); - sim("killLineEmptyLine", "foo\n \nbar", "Ctrl-N", "Ctrl-K", txt("foo\nbar")); - sim("killLineMulti", "foo\nbar\nbaz", - "Ctrl-F", "Ctrl-F", "Ctrl-K", "Ctrl-K", "Ctrl-K", "Ctrl-A", "Ctrl-Y", - txt("o\nbarfo\nbaz")); - - sim("moveByParagraph", "abc\ndef\n\n\nhij\nklm\n\n", - "Ctrl-F", "Ctrl-Down", at(2, 0), "Ctrl-Down", at(6, 0), - "Ctrl-N", "Ctrl-Up", at(3, 0), "Ctrl-Up", at(0, 0), - Pos(1, 2), "Ctrl-Down", at(2, 0), Pos(4, 2), "Ctrl-Up", at(3, 0)); - sim("moveByParagraphMulti", "abc\n\ndef\n\nhij\n\nklm", - "Ctrl-U", "2", "Ctrl-Down", at(3, 0), - "Shift-Alt-.", "Ctrl-3", "Ctrl-Up", at(1, 0)); - - sim("moveBySentence", "sentence one! sentence\ntwo\n\nparagraph two", - "Alt-E", at(0, 13), "Alt-E", at(1, 3), "Ctrl-F", "Alt-A", at(0, 13)); - - sim("moveByExpr", "function foo(a, b) {}", - "Ctrl-Alt-F", at(0, 8), "Ctrl-Alt-F", at(0, 12), "Ctrl-Alt-F", at(0, 18), - "Ctrl-Alt-B", at(0, 12), "Ctrl-Alt-B", at(0, 9)); - sim("moveByExprMulti", "foo bar baz bug", - "Ctrl-2", "Ctrl-Alt-F", at(0, 7), - "Ctrl--", "Ctrl-Alt-F", at(0, 4), - "Ctrl--", "Ctrl-2", "Ctrl-Alt-B", at(0, 11)); - sim("delExpr", "var x = [\n a,\n b\n c\n];", - Pos(0, 8), "Ctrl-Alt-K", txt("var x = ;"), "Ctrl-/", - Pos(4, 1), "Ctrl-Alt-Backspace", txt("var x = ;")); - sim("delExprMulti", "foo bar baz", - "Ctrl-2", "Ctrl-Alt-K", txt(" baz"), - "Ctrl-/", "Ctrl-E", "Ctrl-2", "Ctrl-Alt-Backspace", txt("foo ")); - - sim("justOneSpace", "hi bye ", - Pos(0, 4), "Alt-Space", txt("hi bye "), - Pos(0, 4), "Alt-Space", txt("hi b ye "), - "Ctrl-A", "Alt-Space", "Ctrl-E", "Alt-Space", txt(" hi b ye ")); - - sim("openLine", "foo bar", "Alt-F", "Ctrl-O", txt("foo\n bar")) - - sim("transposeChar", "abcd\ne", - "Ctrl-F", "Ctrl-T", "Ctrl-T", txt("bcad\ne"), at(0, 3), - "Ctrl-F", "Ctrl-T", "Ctrl-T", "Ctrl-T", txt("bcda\ne"), at(0, 4), - "Ctrl-F", "Ctrl-T", txt("bcde\na"), at(1, 0)); - - sim("manipWordCase", "foo BAR bAZ", - "Alt-C", "Alt-L", "Alt-U", txt("Foo bar BAZ"), - "Ctrl-A", "Alt-U", "Alt-L", "Alt-C", txt("FOO bar Baz")); - sim("manipWordCaseMulti", "foo Bar bAz", - "Ctrl-2", "Alt-U", txt("FOO BAR bAz"), - "Ctrl-A", "Ctrl-3", "Alt-C", txt("Foo Bar Baz")); - - sim("upExpr", "foo {\n bar[];\n baz(blah);\n}", - Pos(2, 7), "Ctrl-Alt-U", at(2, 5), "Ctrl-Alt-U", at(0, 4)); - sim("transposeExpr", "do foo[bar] dah", - Pos(0, 6), "Ctrl-Alt-T", txt("do [bar]foo dah")); - - sim("clearMark", "abcde", Pos(0, 2), "Ctrl-Space", "Ctrl-F", "Ctrl-F", - "Ctrl-G", "Ctrl-W", txt("abcde")); - - sim("delRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Delete", txt("cde")); - sim("backspaceRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Backspace", txt("cde")); - - testCM("save", function(cm) { - var saved = false; - CodeMirror.commands.save = function(cm) { saved = cm.getValue(); }; - cm.triggerOnKeyDown(fakeEvent("Ctrl-X")); - cm.triggerOnKeyDown(fakeEvent("Ctrl-S")); - is(saved, "hi"); - }, {value: "hi", keyMap: "emacs"}); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/test/index.html b/shared/html/libs/codemirror/5.0.0/test/index.html deleted file mode 100644 index d7fdede..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/index.html +++ /dev/null @@ -1,240 +0,0 @@ - - - -CodeMirror: Test Suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -

    Test Suite

    - -

    A limited set of programmatic sanity tests for CodeMirror.

    - -
    -
    Ran 0 of 0 tests
    -
    -

    Please enable JavaScript...

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    diff --git a/shared/html/libs/codemirror/5.0.0/test/lint.js b/shared/html/libs/codemirror/5.0.0/test/lint.js deleted file mode 100644 index 3577756..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/lint.js +++ /dev/null @@ -1,11 +0,0 @@ -var blint = require("blint"); - -["mode", "lib", "addon", "keymap"].forEach(function(dir) { - blint.checkDir(dir, { - browser: true, - allowedGlobals: ["CodeMirror", "define", "test", "requirejs"], - blob: "// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http:\/\/codemirror.net\/LICENSE\n\n" - }); -}); - -module.exports = {ok: blint.success()}; diff --git a/shared/html/libs/codemirror/5.0.0/test/mode_test.css b/shared/html/libs/codemirror/5.0.0/test/mode_test.css deleted file mode 100644 index f83271b..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/mode_test.css +++ /dev/null @@ -1,23 +0,0 @@ -.mt-output .mt-token { - border: 1px solid #ddd; - white-space: pre; - font-family: "Consolas", monospace; - text-align: center; -} - -.mt-output .mt-style { - font-size: x-small; -} - -.mt-output .mt-state { - font-size: x-small; - vertical-align: top; -} - -.mt-output .mt-state-row { - display: none; -} - -.mt-state-unhide .mt-output .mt-state-row { - display: table-row; -} diff --git a/shared/html/libs/codemirror/5.0.0/test/mode_test.js b/shared/html/libs/codemirror/5.0.0/test/mode_test.js deleted file mode 100644 index 2e16eba..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/mode_test.js +++ /dev/null @@ -1,192 +0,0 @@ -/** - * Helper to test CodeMirror highlighting modes. It pretty prints output of the - * highlighter and can check against expected styles. - * - * Mode tests are registered by calling test.mode(testName, mode, - * tokens), where mode is a mode object as returned by - * CodeMirror.getMode, and tokens is an array of lines that make up - * the test. - * - * These lines are strings, in which styled stretches of code are - * enclosed in brackets `[]`, and prefixed by their style. For - * example, `[keyword if]`. Brackets in the code itself must be - * duplicated to prevent them from being interpreted as token - * boundaries. For example `a[[i]]` for `a[i]`. If a token has - * multiple styles, the styles must be separated by ampersands, for - * example `[tag&error ]`. - * - * See the test.js files in the css, markdown, gfm, and stex mode - * directories for examples. - */ -(function() { - function findSingle(str, pos, ch) { - for (;;) { - var found = str.indexOf(ch, pos); - if (found == -1) return null; - if (str.charAt(found + 1) != ch) return found; - pos = found + 2; - } - } - - var styleName = /[\w&-_]+/g; - function parseTokens(strs) { - var tokens = [], plain = ""; - for (var i = 0; i < strs.length; ++i) { - if (i) plain += "\n"; - var str = strs[i], pos = 0; - while (pos < str.length) { - var style = null, text; - if (str.charAt(pos) == "[" && str.charAt(pos+1) != "[") { - styleName.lastIndex = pos + 1; - var m = styleName.exec(str); - style = m[0].replace(/&/g, " "); - var textStart = pos + style.length + 2; - var end = findSingle(str, textStart, "]"); - if (end == null) throw new Error("Unterminated token at " + pos + " in '" + str + "'" + style); - text = str.slice(textStart, end); - pos = end + 1; - } else { - var end = findSingle(str, pos, "["); - if (end == null) end = str.length; - text = str.slice(pos, end); - pos = end; - } - text = text.replace(/\[\[|\]\]/g, function(s) {return s.charAt(0);}); - tokens.push({style: style, text: text}); - plain += text; - } - } - return {tokens: tokens, plain: plain}; - } - - test.mode = function(name, mode, tokens, modeName) { - var data = parseTokens(tokens); - return test((modeName || mode.name) + "_" + name, function() { - return compare(data.plain, data.tokens, mode); - }); - }; - - function esc(str) { - return str.replace('&', '&').replace('<', '<').replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); -; - } - - function compare(text, expected, mode) { - - var expectedOutput = []; - for (var i = 0; i < expected.length; ++i) { - var sty = expected[i].style; - if (sty && sty.indexOf(" ")) sty = sty.split(' ').sort().join(' '); - expectedOutput.push({style: sty, text: expected[i].text}); - } - - var observedOutput = highlight(text, mode); - - var s = ""; - var diff = highlightOutputsDifferent(expectedOutput, observedOutput); - if (diff != null) { - s += '
    '; - s += '
    ' + esc(text) + '
    '; - s += '
    '; - s += 'expected:'; - s += prettyPrintOutputTable(expectedOutput, diff); - s += 'observed: [display states]'; - s += prettyPrintOutputTable(observedOutput, diff); - s += '
    '; - s += '
    '; - } - if (observedOutput.indentFailures) { - for (var i = 0; i < observedOutput.indentFailures.length; i++) - s += "
    " + esc(observedOutput.indentFailures[i]) + "
    "; - } - if (s) throw new Failure(s); - } - - function stringify(obj) { - function replacer(key, obj) { - if (typeof obj == "function") { - var m = obj.toString().match(/function\s*[^\s(]*/); - return m ? m[0] : "function"; - } - return obj; - } - if (window.JSON && JSON.stringify) - return JSON.stringify(obj, replacer, 2); - return "[unsupported]"; // Fail safely if no native JSON. - } - - function highlight(string, mode) { - var state = mode.startState(); - - var lines = string.replace(/\r\n/g,'\n').split('\n'); - var st = [], pos = 0; - for (var i = 0; i < lines.length; ++i) { - var line = lines[i], newLine = true; - if (mode.indent) { - var ws = line.match(/^\s*/)[0]; - var indent = mode.indent(state, line.slice(ws.length)); - if (indent != CodeMirror.Pass && indent != ws.length) - (st.indentFailures || (st.indentFailures = [])).push( - "Indentation of line " + (i + 1) + " is " + indent + " (expected " + ws.length + ")"); - } - var stream = new CodeMirror.StringStream(line); - if (line == "" && mode.blankLine) mode.blankLine(state); - /* Start copied code from CodeMirror.highlight */ - while (!stream.eol()) { - for (var j = 0; j < 10 && stream.start >= stream.pos; j++) - var compare = mode.token(stream, state); - if (j == 10) - throw new Failure("Failed to advance the stream." + stream.string + " " + stream.pos); - var substr = stream.current(); - if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' '); - stream.start = stream.pos; - if (pos && st[pos-1].style == compare && !newLine) { - st[pos-1].text += substr; - } else if (substr) { - st[pos++] = {style: compare, text: substr, state: stringify(state)}; - } - // Give up when line is ridiculously long - if (stream.pos > 5000) { - st[pos++] = {style: null, text: this.text.slice(stream.pos)}; - break; - } - newLine = false; - } - } - - return st; - } - - function highlightOutputsDifferent(o1, o2) { - var minLen = Math.min(o1.length, o2.length); - for (var i = 0; i < minLen; ++i) - if (o1[i].style != o2[i].style || o1[i].text != o2[i].text) return i; - if (o1.length > minLen || o2.length > minLen) return minLen; - } - - function prettyPrintOutputTable(output, diffAt) { - var s = ''; - s += ''; - for (var i = 0; i < output.length; ++i) { - var style = output[i].style, val = output[i].text; - s += - ''; - } - s += ''; - for (var i = 0; i < output.length; ++i) { - s += ''; - } - if(output[0].state) { - s += ''; - for (var i = 0; i < output.length; ++i) { - s += ''; - } - } - s += '
    ' + - '' + - esc(val.replace(/ /g,'\xb7')) + // · MIDDLE DOT - '' + - '
    ' + (output[i].style || null) + '
    ' + esc(output[i].state) + '
    '; - return s; - } -})(); diff --git a/shared/html/libs/codemirror/5.0.0/test/multi_test.js b/shared/html/libs/codemirror/5.0.0/test/multi_test.js deleted file mode 100644 index a8e760d..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/multi_test.js +++ /dev/null @@ -1,285 +0,0 @@ -(function() { - namespace = "multi_"; - - function hasSelections(cm) { - var sels = cm.listSelections(); - var given = (arguments.length - 1) / 4; - if (sels.length != given) - throw new Failure("expected " + given + " selections, found " + sels.length); - for (var i = 0, p = 1; i < given; i++, p += 4) { - var anchor = Pos(arguments[p], arguments[p + 1]); - var head = Pos(arguments[p + 2], arguments[p + 3]); - eqPos(sels[i].anchor, anchor, "anchor of selection " + i); - eqPos(sels[i].head, head, "head of selection " + i); - } - } - function hasCursors(cm) { - var sels = cm.listSelections(); - var given = (arguments.length - 1) / 2; - if (sels.length != given) - throw new Failure("expected " + given + " selections, found " + sels.length); - for (var i = 0, p = 1; i < given; i++, p += 2) { - eqPos(sels[i].anchor, sels[i].head, "something selected for " + i); - var head = Pos(arguments[p], arguments[p + 1]); - eqPos(sels[i].head, head, "selection " + i); - } - } - - testCM("getSelection", function(cm) { - select(cm, {anchor: Pos(0, 0), head: Pos(1, 2)}, {anchor: Pos(2, 2), head: Pos(2, 0)}); - eq(cm.getSelection(), "1234\n56\n90"); - eq(cm.getSelection(false).join("|"), "1234|56|90"); - eq(cm.getSelections().join("|"), "1234\n56|90"); - }, {value: "1234\n5678\n90"}); - - testCM("setSelection", function(cm) { - select(cm, Pos(3, 0), Pos(0, 0), {anchor: Pos(2, 5), head: Pos(1, 0)}); - hasSelections(cm, 0, 0, 0, 0, - 2, 5, 1, 0, - 3, 0, 3, 0); - cm.setSelection(Pos(1, 2), Pos(1, 1)); - hasSelections(cm, 1, 2, 1, 1); - select(cm, {anchor: Pos(1, 1), head: Pos(2, 4)}, - {anchor: Pos(0, 0), head: Pos(1, 3)}, - Pos(3, 0), Pos(2, 2)); - hasSelections(cm, 0, 0, 2, 4, - 3, 0, 3, 0); - cm.setSelections([{anchor: Pos(0, 1), head: Pos(0, 2)}, - {anchor: Pos(1, 1), head: Pos(1, 2)}, - {anchor: Pos(2, 1), head: Pos(2, 2)}], 1); - eqPos(cm.getCursor("head"), Pos(1, 2)); - eqPos(cm.getCursor("anchor"), Pos(1, 1)); - eqPos(cm.getCursor("from"), Pos(1, 1)); - eqPos(cm.getCursor("to"), Pos(1, 2)); - cm.setCursor(Pos(1, 1)); - hasCursors(cm, 1, 1); - }, {value: "abcde\nabcde\nabcde\n"}); - - testCM("somethingSelected", function(cm) { - select(cm, Pos(0, 1), {anchor: Pos(0, 3), head: Pos(0, 5)}); - eq(cm.somethingSelected(), true); - select(cm, Pos(0, 1), Pos(0, 3), Pos(0, 5)); - eq(cm.somethingSelected(), false); - }, {value: "123456789"}); - - testCM("extendSelection", function(cm) { - select(cm, Pos(0, 1), Pos(1, 1), Pos(2, 1)); - cm.setExtending(true); - cm.extendSelections([Pos(0, 2), Pos(1, 0), Pos(2, 3)]); - hasSelections(cm, 0, 1, 0, 2, - 1, 1, 1, 0, - 2, 1, 2, 3); - cm.extendSelection(Pos(2, 4), Pos(2, 0)); - hasSelections(cm, 2, 4, 2, 0); - }, {value: "1234\n1234\n1234"}); - - testCM("addSelection", function(cm) { - select(cm, Pos(0, 1), Pos(1, 1)); - cm.addSelection(Pos(0, 0), Pos(0, 4)); - hasSelections(cm, 0, 0, 0, 4, - 1, 1, 1, 1); - cm.addSelection(Pos(2, 2)); - hasSelections(cm, 0, 0, 0, 4, - 1, 1, 1, 1, - 2, 2, 2, 2); - }, {value: "1234\n1234\n1234"}); - - testCM("replaceSelection", function(cm) { - var selections = [{anchor: Pos(0, 0), head: Pos(0, 1)}, - {anchor: Pos(0, 2), head: Pos(0, 3)}, - {anchor: Pos(0, 4), head: Pos(0, 5)}, - {anchor: Pos(2, 1), head: Pos(2, 4)}, - {anchor: Pos(2, 5), head: Pos(2, 6)}]; - var val = "123456\n123456\n123456"; - cm.setValue(val); - cm.setSelections(selections); - cm.replaceSelection("ab", "around"); - eq(cm.getValue(), "ab2ab4ab6\n123456\n1ab5ab"); - hasSelections(cm, 0, 0, 0, 2, - 0, 3, 0, 5, - 0, 6, 0, 8, - 2, 1, 2, 3, - 2, 4, 2, 6); - cm.setValue(val); - cm.setSelections(selections); - cm.replaceSelection("", "around"); - eq(cm.getValue(), "246\n123456\n15"); - hasSelections(cm, 0, 0, 0, 0, - 0, 1, 0, 1, - 0, 2, 0, 2, - 2, 1, 2, 1, - 2, 2, 2, 2); - cm.setValue(val); - cm.setSelections(selections); - cm.replaceSelection("X\nY\nZ", "around"); - hasSelections(cm, 0, 0, 2, 1, - 2, 2, 4, 1, - 4, 2, 6, 1, - 8, 1, 10, 1, - 10, 2, 12, 1); - cm.replaceSelection("a", "around"); - hasSelections(cm, 0, 0, 0, 1, - 0, 2, 0, 3, - 0, 4, 0, 5, - 2, 1, 2, 2, - 2, 3, 2, 4); - cm.replaceSelection("xy", "start"); - hasSelections(cm, 0, 0, 0, 0, - 0, 3, 0, 3, - 0, 6, 0, 6, - 2, 1, 2, 1, - 2, 4, 2, 4); - cm.replaceSelection("z\nf"); - hasSelections(cm, 1, 1, 1, 1, - 2, 1, 2, 1, - 3, 1, 3, 1, - 6, 1, 6, 1, - 7, 1, 7, 1); - eq(cm.getValue(), "z\nfxy2z\nfxy4z\nfxy6\n123456\n1z\nfxy5z\nfxy"); - }); - - function select(cm) { - var sels = []; - for (var i = 1; i < arguments.length; i++) { - var arg = arguments[i]; - if (arg.head) sels.push(arg); - else sels.push({head: arg, anchor: arg}); - } - cm.setSelections(sels, sels.length - 1); - } - - testCM("indentSelection", function(cm) { - select(cm, Pos(0, 1), Pos(1, 1)); - cm.indentSelection(4); - eq(cm.getValue(), " foo\n bar\nbaz"); - - select(cm, Pos(0, 2), Pos(0, 3), Pos(0, 4)); - cm.indentSelection(-2); - eq(cm.getValue(), " foo\n bar\nbaz"); - - select(cm, {anchor: Pos(0, 0), head: Pos(1, 2)}, - {anchor: Pos(1, 3), head: Pos(2, 0)}); - cm.indentSelection(-2); - eq(cm.getValue(), "foo\n bar\nbaz"); - }, {value: "foo\nbar\nbaz"}); - - testCM("killLine", function(cm) { - select(cm, Pos(0, 1), Pos(0, 2), Pos(1, 1)); - cm.execCommand("killLine"); - eq(cm.getValue(), "f\nb\nbaz"); - cm.execCommand("killLine"); - eq(cm.getValue(), "fbbaz"); - cm.setValue("foo\nbar\nbaz"); - select(cm, Pos(0, 1), {anchor: Pos(0, 2), head: Pos(2, 1)}); - cm.execCommand("killLine"); - eq(cm.getValue(), "faz"); - }, {value: "foo\nbar\nbaz"}); - - testCM("deleteLine", function(cm) { - select(cm, Pos(0, 0), - {head: Pos(0, 1), anchor: Pos(2, 0)}, - Pos(4, 0)); - cm.execCommand("deleteLine"); - eq(cm.getValue(), "4\n6\n7"); - select(cm, Pos(2, 1)); - cm.execCommand("deleteLine"); - eq(cm.getValue(), "4\n6\n"); - }, {value: "1\n2\n3\n4\n5\n6\n7"}); - - testCM("deleteH", function(cm) { - select(cm, Pos(0, 4), {anchor: Pos(1, 4), head: Pos(1, 5)}); - cm.execCommand("delWordAfter"); - eq(cm.getValue(), "foo bar baz\nabc ef ghi\n"); - cm.execCommand("delWordAfter"); - eq(cm.getValue(), "foo baz\nabc ghi\n"); - cm.execCommand("delCharBefore"); - cm.execCommand("delCharBefore"); - eq(cm.getValue(), "fo baz\nab ghi\n"); - select(cm, Pos(0, 3), Pos(0, 4), Pos(0, 5)); - cm.execCommand("delWordAfter"); - eq(cm.getValue(), "fo \nab ghi\n"); - }, {value: "foo bar baz\nabc def ghi\n"}); - - testCM("goLineStart", function(cm) { - select(cm, Pos(0, 2), Pos(0, 3), Pos(1, 1)); - cm.execCommand("goLineStart"); - hasCursors(cm, 0, 0, 1, 0); - select(cm, Pos(1, 1), Pos(0, 1)); - cm.setExtending(true); - cm.execCommand("goLineStart"); - hasSelections(cm, 0, 1, 0, 0, - 1, 1, 1, 0); - }, {value: "foo\nbar\nbaz"}); - - testCM("moveV", function(cm) { - select(cm, Pos(0, 2), Pos(1, 2)); - cm.execCommand("goLineDown"); - hasCursors(cm, 1, 2, 2, 2); - cm.execCommand("goLineUp"); - hasCursors(cm, 0, 2, 1, 2); - cm.execCommand("goLineUp"); - hasCursors(cm, 0, 0, 0, 2); - cm.execCommand("goLineUp"); - hasCursors(cm, 0, 0); - select(cm, Pos(0, 2), Pos(1, 2)); - cm.setExtending(true); - cm.execCommand("goLineDown"); - hasSelections(cm, 0, 2, 2, 2); - }, {value: "12345\n12345\n12345"}); - - testCM("moveH", function(cm) { - select(cm, Pos(0, 1), Pos(0, 3), Pos(0, 5), Pos(2, 3)); - cm.execCommand("goCharRight"); - hasCursors(cm, 0, 2, 0, 4, 1, 0, 2, 4); - cm.execCommand("goCharLeft"); - hasCursors(cm, 0, 1, 0, 3, 0, 5, 2, 3); - for (var i = 0; i < 15; i++) - cm.execCommand("goCharRight"); - hasCursors(cm, 2, 4, 2, 5); - }, {value: "12345\n12345\n12345"}); - - testCM("newlineAndIndent", function(cm) { - select(cm, Pos(0, 5), Pos(1, 5)); - cm.execCommand("newlineAndIndent"); - hasCursors(cm, 1, 2, 3, 2); - eq(cm.getValue(), "x = [\n 1];\ny = [\n 2];"); - cm.undo(); - eq(cm.getValue(), "x = [1];\ny = [2];"); - hasCursors(cm, 0, 5, 1, 5); - select(cm, Pos(0, 5), Pos(0, 6)); - cm.execCommand("newlineAndIndent"); - hasCursors(cm, 1, 2, 2, 0); - eq(cm.getValue(), "x = [\n 1\n];\ny = [2];"); - }, {value: "x = [1];\ny = [2];", mode: "javascript"}); - - testCM("goDocStartEnd", function(cm) { - select(cm, Pos(0, 1), Pos(1, 1)); - cm.execCommand("goDocStart"); - hasCursors(cm, 0, 0); - select(cm, Pos(0, 1), Pos(1, 1)); - cm.execCommand("goDocEnd"); - hasCursors(cm, 1, 3); - select(cm, Pos(0, 1), Pos(1, 1)); - cm.setExtending(true); - cm.execCommand("goDocEnd"); - hasSelections(cm, 1, 1, 1, 3); - }, {value: "abc\ndef"}); - - testCM("selectionHistory", function(cm) { - for (var i = 0; i < 3; ++i) - cm.addSelection(Pos(0, i * 2), Pos(0, i * 2 + 1)); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), "1\n2"); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), "1"); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), "1"); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), "1\n2"); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), "1\n2\n3"); - }, {value: "1 2 3"}); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/test/phantom_driver.js b/shared/html/libs/codemirror/5.0.0/test/phantom_driver.js deleted file mode 100644 index dbad08d..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/phantom_driver.js +++ /dev/null @@ -1,31 +0,0 @@ -var page = require('webpage').create(); - -page.open("http://localhost:3000/test/index.html", function (status) { - if (status != "success") { - console.log("page couldn't be loaded successfully"); - phantom.exit(1); - } - waitFor(function () { - return page.evaluate(function () { - var output = document.getElementById('status'); - if (!output) { return false; } - return (/^(\d+ failures?|all passed)/i).test(output.innerText); - }); - }, function () { - var failed = page.evaluate(function () { return window.failed; }); - var output = page.evaluate(function () { - return document.getElementById('output').innerText + "\n" + - document.getElementById('status').innerText; - }); - console.log(output); - phantom.exit(failed > 0 ? 1 : 0); - }); -}); - -function waitFor (test, cb) { - if (test()) { - cb(); - } else { - setTimeout(function () { waitFor(test, cb); }, 250); - } -} diff --git a/shared/html/libs/codemirror/5.0.0/test/run.js b/shared/html/libs/codemirror/5.0.0/test/run.js deleted file mode 100644 index 24b835c..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/run.js +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env node - -var ok = require("./lint").ok; - -var files = new (require('node-static').Server)(); - -var server = require('http').createServer(function (req, res) { - req.addListener('end', function () { - files.serve(req, res, function (err/*, result */) { - if (err) { - console.error(err); - process.exit(1); - } - }); - }).resume(); -}).addListener('error', function (err) { - throw err; -}).listen(3000, function () { - var childProcess = require('child_process'); - var phantomjs = require("phantomjs"); - var childArgs = [ - require("path").join(__dirname, 'phantom_driver.js') - ]; - childProcess.execFile(phantomjs.path, childArgs, function (err, stdout, stderr) { - server.close(); - console.log(stdout); - if (err) console.error(err); - if (stderr) console.error(stderr); - process.exit(err || stderr || !ok ? 1 : 0); - }); -}); diff --git a/shared/html/libs/codemirror/5.0.0/test/scroll_test.js b/shared/html/libs/codemirror/5.0.0/test/scroll_test.js deleted file mode 100644 index 2047002..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/scroll_test.js +++ /dev/null @@ -1,105 +0,0 @@ -(function() { - "use strict"; - - namespace = "scroll_"; - - testCM("bars_hidden", function(cm) { - for (var i = 0;; i++) { - var wrapBox = cm.getWrapperElement().getBoundingClientRect(); - var scrollBox = cm.getScrollerElement().getBoundingClientRect(); - is(wrapBox.bottom < scrollBox.bottom - 10); - is(wrapBox.right < scrollBox.right - 10); - if (i == 1) break; - cm.getWrapperElement().style.height = "auto"; - cm.refresh(); - } - }); - - function barH(cm) { return byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0]; } - function barV(cm) { return byClassName(cm.getWrapperElement(), "CodeMirror-vscrollbar")[0]; } - - function displayBottom(cm, scrollbar) { - if (scrollbar) - return barH(cm).getBoundingClientRect().top; - else - return cm.getWrapperElement().getBoundingClientRect().bottom - 1; - } - - function displayRight(cm, scrollbar) { - if (scrollbar) - return barV(cm).getBoundingClientRect().left; - else - return cm.getWrapperElement().getBoundingClientRect().right - 1; - } - - function testMovedownFixed(cm, hScroll) { - cm.setSize("100px", "100px"); - if (hScroll) cm.setValue(new Array(100).join("x")); - var bottom = displayBottom(cm, hScroll); - for (var i = 0; i < 30; i++) { - cm.replaceSelection("x\n"); - var cursorBottom = cm.cursorCoords(null, "window").bottom; - is(cursorBottom <= bottom); - } - is(cursorBottom >= bottom - 5); - } - - testCM("movedown_fixed", function(cm) {testMovedownFixed(cm, false);}); - testCM("movedown_hscroll_fixed", function(cm) {testMovedownFixed(cm, true);}); - - function testMovedownResize(cm, hScroll) { - cm.getWrapperElement().style.height = "auto"; - if (hScroll) cm.setValue(new Array(100).join("x")); - cm.refresh(); - for (var i = 0; i < 30; i++) { - cm.replaceSelection("x\n"); - var bottom = displayBottom(cm, hScroll); - var cursorBottom = cm.cursorCoords(null, "window").bottom; - is(cursorBottom <= bottom); - is(cursorBottom >= bottom - 5); - } - } - - testCM("movedown_resize", function(cm) {testMovedownResize(cm, false);}); - testCM("movedown_hscroll_resize", function(cm) {testMovedownResize(cm, true);}); - - function testMoveright(cm, wrap, scroll) { - cm.setSize("100px", "100px"); - if (wrap) cm.setOption("lineWrapping", true); - if (scroll) { - cm.setValue("\n" + new Array(100).join("x\n")); - cm.setCursor(Pos(0, 0)); - } - var right = displayRight(cm, scroll); - for (var i = 0; i < 10; i++) { - cm.replaceSelection("xxxxxxxxxx"); - var cursorRight = cm.cursorCoords(null, "window").right; - is(cursorRight < right); - } - if (!wrap) is(cursorRight > right - 20); - } - - testCM("moveright", function(cm) {testMoveright(cm, false, false);}); - testCM("moveright_wrap", function(cm) {testMoveright(cm, true, false);}); - testCM("moveright_scroll", function(cm) {testMoveright(cm, false, true);}); - testCM("moveright_scroll_wrap", function(cm) {testMoveright(cm, true, true);}); - - testCM("suddenly_wide", function(cm) { - addDoc(cm, 100, 100); - cm.replaceSelection(new Array(600).join("l ") + "\n"); - cm.execCommand("goLineUp"); - cm.execCommand("goLineEnd"); - is(barH(cm).scrollLeft > cm.getScrollerElement().scrollLeft - 1); - }); - - testCM("wrap_changes_height", function(cm) { - var line = new Array(20).join("a ") + "\n"; - cm.setValue(new Array(20).join(line)); - var box = cm.getWrapperElement().getBoundingClientRect(); - cm.setSize(cm.cursorCoords(Pos(0), "window").right - box.left + 2, - cm.cursorCoords(Pos(19, 0), "window").bottom - box.top + 2); - cm.setCursor(Pos(19, 0)); - cm.replaceSelection("\n"); - is(cm.cursorCoords(null, "window").bottom < displayBottom(cm, false)); - }, {lineWrapping: true}); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/test/search_test.js b/shared/html/libs/codemirror/5.0.0/test/search_test.js deleted file mode 100644 index 04a1e68..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/search_test.js +++ /dev/null @@ -1,62 +0,0 @@ -(function() { - "use strict"; - - function test(name) { - var text = Array.prototype.slice.call(arguments, 1, arguments.length - 1).join("\n"); - var body = arguments[arguments.length - 1]; - return window.test("search_" + name, function() { - body(new CodeMirror.Doc(text)); - }); - } - - function run(doc, query, insensitive) { - var cursor = doc.getSearchCursor(query, null, insensitive); - for (var i = 3; i < arguments.length; i += 4) { - var found = cursor.findNext(); - is(found, "not enough results (forward)"); - eqPos(Pos(arguments[i], arguments[i + 1]), cursor.from(), "from, forward, " + (i - 3) / 4); - eqPos(Pos(arguments[i + 2], arguments[i + 3]), cursor.to(), "to, forward, " + (i - 3) / 4); - } - is(!cursor.findNext(), "too many matches (forward)"); - for (var i = arguments.length - 4; i >= 3; i -= 4) { - var found = cursor.findPrevious(); - is(found, "not enough results (backwards)"); - eqPos(Pos(arguments[i], arguments[i + 1]), cursor.from(), "from, backwards, " + (i - 3) / 4); - eqPos(Pos(arguments[i + 2], arguments[i + 3]), cursor.to(), "to, backwards, " + (i - 3) / 4); - } - is(!cursor.findPrevious(), "too many matches (backwards)"); - } - - test("simple", "abcdefg", "abcdefg", function(doc) { - run(doc, "cde", false, 0, 2, 0, 5, 1, 2, 1, 5); - }); - - test("multiline", "hallo", "goodbye", function(doc) { - run(doc, "llo\ngoo", false, 0, 2, 1, 3); - run(doc, "blah\nhall", false); - run(doc, "bye\neye", false); - }); - - test("regexp", "abcde", "abcde", function(doc) { - run(doc, /bcd/, false, 0, 1, 0, 4, 1, 1, 1, 4); - run(doc, /BCD/, false); - run(doc, /BCD/i, false, 0, 1, 0, 4, 1, 1, 1, 4); - }); - - test("insensitive", "hallo", "HALLO", "oink", "hAllO", function(doc) { - run(doc, "All", false, 3, 1, 3, 4); - run(doc, "All", true, 0, 1, 0, 4, 1, 1, 1, 4, 3, 1, 3, 4); - }); - - test("multilineInsensitive", "zie ginds komT", "De Stoomboot", "uit Spanje weer aan", function(doc) { - run(doc, "komt\nde stoomboot\nuit", false); - run(doc, "komt\nde stoomboot\nuit", true, 0, 10, 2, 3); - run(doc, "kOMt\ndE stOOmboot\nuiT", true, 0, 10, 2, 3); - }); - - test("expandingCaseFold", "İİ İİ", "uu uu", function(doc) { - if (phantom) return; // A Phantom bug makes this hang - run(doc, "", true, 0, 8, 0, 12, 1, 8, 1, 12); - run(doc, "İİ", true, 0, 3, 0, 5, 0, 6, 0, 8); - }); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/test/sql-hint-test.js b/shared/html/libs/codemirror/5.0.0/test/sql-hint-test.js deleted file mode 100644 index c857920..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/sql-hint-test.js +++ /dev/null @@ -1,170 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var Pos = CodeMirror.Pos; - - var simpleTables = { - "users": ["name", "score", "birthDate"], - "xcountries": ["name", "population", "size"] - }; - - var schemaTables = { - "schema.users": ["name", "score", "birthDate"], - "schema.countries": ["name", "population", "size"] - }; - - var displayTextTables = [{ - text: "mytable", - displayText: "mytable | The main table", - columns: [{text: "id", displayText: "id | Unique ID"}, - {text: "name", displayText: "name | The name"}] - }]; - - namespace = "sql-hint_"; - - function test(name, spec) { - testCM(name, function(cm) { - cm.setValue(spec.value); - cm.setCursor(spec.cursor); - var completion = CodeMirror.hint.sql(cm, {tables: spec.tables}); - if (!deepCompare(completion.list, spec.list)) - throw new Failure("Wrong completion results " + JSON.stringify(completion.list) + " vs " + JSON.stringify(spec.list)); - eqPos(completion.from, spec.from); - eqPos(completion.to, spec.to); - }, { - value: spec.value, - mode: "text/x-mysql" - }); - } - - test("keywords", { - value: "SEL", - cursor: Pos(0, 3), - list: ["SELECT"], - from: Pos(0, 0), - to: Pos(0, 3) - }); - - test("from", { - value: "SELECT * fr", - cursor: Pos(0, 11), - list: ["FROM"], - from: Pos(0, 9), - to: Pos(0, 11) - }); - - test("table", { - value: "SELECT xc", - cursor: Pos(0, 9), - tables: simpleTables, - list: ["xcountries"], - from: Pos(0, 7), - to: Pos(0, 9) - }); - - test("columns", { - value: "SELECT users.", - cursor: Pos(0, 13), - tables: simpleTables, - list: ["users.name", "users.score", "users.birthDate"], - from: Pos(0, 7), - to: Pos(0, 13) - }); - - test("singlecolumn", { - value: "SELECT users.na", - cursor: Pos(0, 15), - tables: simpleTables, - list: ["users.name"], - from: Pos(0, 7), - to: Pos(0, 15) - }); - - test("quoted", { - value: "SELECT `users`.`na", - cursor: Pos(0, 18), - tables: simpleTables, - list: ["`users`.`name`"], - from: Pos(0, 7), - to: Pos(0, 18) - }); - - test("quotedcolumn", { - value: "SELECT users.`na", - cursor: Pos(0, 16), - tables: simpleTables, - list: ["`users`.`name`"], - from: Pos(0, 7), - to: Pos(0, 16) - }); - - test("schema", { - value: "SELECT schem", - cursor: Pos(0, 12), - tables: schemaTables, - list: ["schema.users", "schema.countries", - "SCHEMA", "SCHEMA_NAME", "SCHEMAS"], - from: Pos(0, 7), - to: Pos(0, 12) - }); - - test("schemaquoted", { - value: "SELECT `sch", - cursor: Pos(0, 11), - tables: schemaTables, - list: ["`schema`.`users`", "`schema`.`countries`"], - from: Pos(0, 7), - to: Pos(0, 11) - }); - - test("schemacolumn", { - value: "SELECT schema.users.", - cursor: Pos(0, 20), - tables: schemaTables, - list: ["schema.users.name", - "schema.users.score", - "schema.users.birthDate"], - from: Pos(0, 7), - to: Pos(0, 20) - }); - - test("schemacolumnquoted", { - value: "SELECT `schema`.`users`.", - cursor: Pos(0, 24), - tables: schemaTables, - list: ["`schema`.`users`.`name`", - "`schema`.`users`.`score`", - "`schema`.`users`.`birthDate`"], - from: Pos(0, 7), - to: Pos(0, 24) - }); - - test("displayText_table", { - value: "SELECT myt", - cursor: Pos(0, 10), - tables: displayTextTables, - list: displayTextTables, - from: Pos(0, 7), - to: Pos(0, 10) - }); - - test("displayText_column", { - value: "SELECT mytable.", - cursor: Pos(0, 15), - tables: displayTextTables, - list: [{text: "mytable.id", displayText: "id | Unique ID"}, - {text: "mytable.name", displayText: "name | The name"}], - from: Pos(0, 7), - to: Pos(0, 15) - }); - - function deepCompare(a, b) { - if (!a || typeof a != "object") - return a === b; - if (!b || typeof b != "object") - return false; - for (var prop in a) if (!deepCompare(a[prop], b[prop])) return false; - return true; - } -})(); diff --git a/shared/html/libs/codemirror/5.0.0/test/sublime_test.js b/shared/html/libs/codemirror/5.0.0/test/sublime_test.js deleted file mode 100644 index c93e041..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/sublime_test.js +++ /dev/null @@ -1,303 +0,0 @@ -(function() { - "use strict"; - - var Pos = CodeMirror.Pos; - namespace = "sublime_"; - - function stTest(name) { - var actions = Array.prototype.slice.call(arguments, 1); - testCM(name, function(cm) { - for (var i = 0; i < actions.length; i++) { - var action = actions[i]; - if (typeof action == "string" && i == 0) - cm.setValue(action); - else if (typeof action == "string") - cm.execCommand(action); - else if (action instanceof Pos) - cm.setCursor(action); - else - action(cm); - } - }); - } - - function at(line, ch, msg) { - return function(cm) { - eq(cm.listSelections().length, 1); - eqPos(cm.getCursor("head"), Pos(line, ch), msg); - eqPos(cm.getCursor("anchor"), Pos(line, ch), msg); - }; - } - - function val(content, msg) { - return function(cm) { eq(cm.getValue(), content, msg); }; - } - - function argsToRanges(args) { - if (args.length % 4) throw new Error("Wrong number of arguments for ranges."); - var ranges = []; - for (var i = 0; i < args.length; i += 4) - ranges.push({anchor: Pos(args[i], args[i + 1]), - head: Pos(args[i + 2], args[i + 3])}); - return ranges; - } - - function setSel() { - var ranges = argsToRanges(arguments); - return function(cm) { cm.setSelections(ranges, 0); }; - } - - function hasSel() { - var ranges = argsToRanges(arguments); - return function(cm) { - var sels = cm.listSelections(); - if (sels.length != ranges.length) - throw new Failure("Expected " + ranges.length + " selections, but found " + sels.length); - for (var i = 0; i < sels.length; i++) { - eqPos(sels[i].anchor, ranges[i].anchor, "anchor " + i); - eqPos(sels[i].head, ranges[i].head, "head " + i); - } - }; - } - - stTest("bySubword", "the foo_bar DooDahBah \n a", - "goSubwordLeft", at(0, 0), - "goSubwordRight", at(0, 3), - "goSubwordRight", at(0, 7), - "goSubwordRight", at(0, 11), - "goSubwordRight", at(0, 15), - "goSubwordRight", at(0, 18), - "goSubwordRight", at(0, 21), - "goSubwordRight", at(0, 22), - "goSubwordRight", at(1, 0), - "goSubwordRight", at(1, 2), - "goSubwordRight", at(1, 2), - "goSubwordLeft", at(1, 1), - "goSubwordLeft", at(1, 0), - "goSubwordLeft", at(0, 22), - "goSubwordLeft", at(0, 18), - "goSubwordLeft", at(0, 15), - "goSubwordLeft", at(0, 12), - "goSubwordLeft", at(0, 8), - "goSubwordLeft", at(0, 4), - "goSubwordLeft", at(0, 0)); - - stTest("splitSelectionByLine", "abc\ndef\nghi", - setSel(0, 1, 2, 2), - "splitSelectionByLine", - hasSel(0, 1, 0, 3, - 1, 0, 1, 3, - 2, 0, 2, 2)); - - stTest("splitSelectionByLineMulti", "abc\ndef\nghi\njkl", - setSel(0, 1, 1, 1, - 1, 2, 3, 2, - 3, 3, 3, 3), - "splitSelectionByLine", - hasSel(0, 1, 0, 3, - 1, 0, 1, 1, - 1, 2, 1, 3, - 2, 0, 2, 3, - 3, 0, 3, 2, - 3, 3, 3, 3)); - - stTest("selectLine", "abc\ndef\nghi", - setSel(0, 1, 0, 1, - 2, 0, 2, 1), - "selectLine", - hasSel(0, 0, 1, 0, - 2, 0, 2, 3), - setSel(0, 1, 1, 0), - "selectLine", - hasSel(0, 0, 2, 0)); - - stTest("insertLineAfter", "abcde\nfghijkl\nmn", - setSel(0, 1, 0, 1, - 0, 3, 0, 3, - 1, 2, 1, 2, - 1, 3, 1, 5), "insertLineAfter", - hasSel(1, 0, 1, 0, - 3, 0, 3, 0), val("abcde\n\nfghijkl\n\nmn")); - - stTest("insertLineBefore", "abcde\nfghijkl\nmn", - setSel(0, 1, 0, 1, - 0, 3, 0, 3, - 1, 2, 1, 2, - 1, 3, 1, 5), "insertLineBefore", - hasSel(0, 0, 0, 0, - 2, 0, 2, 0), val("\nabcde\n\nfghijkl\nmn")); - - stTest("selectNextOccurrence", "a foo bar\nfoobar foo", - setSel(0, 2, 0, 5), - "selectNextOccurrence", hasSel(0, 2, 0, 5, - 1, 0, 1, 3), - "selectNextOccurrence", hasSel(0, 2, 0, 5, - 1, 0, 1, 3, - 1, 7, 1, 10), - "selectNextOccurrence", hasSel(0, 2, 0, 5, - 1, 0, 1, 3, - 1, 7, 1, 10), - Pos(0, 3), "selectNextOccurrence", hasSel(0, 2, 0, 5), - "selectNextOccurrence", hasSel(0, 2, 0, 5, - 1, 7, 1, 10), - setSel(0, 6, 0, 9), - "selectNextOccurrence", hasSel(0, 6, 0, 9, - 1, 3, 1, 6)); - - stTest("selectScope", "foo(a) {\n bar[1, 2];\n}", - "selectScope", hasSel(0, 0, 2, 1), - Pos(0, 4), "selectScope", hasSel(0, 4, 0, 5), - Pos(0, 5), "selectScope", hasSel(0, 4, 0, 5), - Pos(0, 6), "selectScope", hasSel(0, 0, 2, 1), - Pos(0, 8), "selectScope", hasSel(0, 8, 2, 0), - Pos(1, 2), "selectScope", hasSel(0, 8, 2, 0), - Pos(1, 6), "selectScope", hasSel(1, 6, 1, 10), - Pos(1, 9), "selectScope", hasSel(1, 6, 1, 10)); - - stTest("goToBracket", "foo(a) {\n bar[1, 2];\n}", - Pos(0, 0), "goToBracket", at(0, 0), - Pos(0, 4), "goToBracket", at(0, 5), "goToBracket", at(0, 4), - Pos(0, 8), "goToBracket", at(2, 0), "goToBracket", at(0, 8), - Pos(1, 2), "goToBracket", at(2, 0), - Pos(1, 7), "goToBracket", at(1, 10), "goToBracket", at(1, 6)); - - stTest("swapLine", "1\n2\n3---\n4\n5", - "swapLineDown", val("2\n1\n3---\n4\n5"), - "swapLineUp", val("1\n2\n3---\n4\n5"), - "swapLineUp", val("1\n2\n3---\n4\n5"), - Pos(4, 1), "swapLineDown", val("1\n2\n3---\n4\n5"), - setSel(0, 1, 0, 1, - 1, 0, 2, 0, - 2, 2, 2, 2), - "swapLineDown", val("4\n1\n2\n3---\n5"), - hasSel(1, 1, 1, 1, - 2, 0, 3, 0, - 3, 2, 3, 2), - "swapLineUp", val("1\n2\n3---\n4\n5"), - hasSel(0, 1, 0, 1, - 1, 0, 2, 0, - 2, 2, 2, 2)); - - stTest("swapLineEmptyBottomSel", "1\n2\n3", - setSel(0, 1, 1, 0), - "swapLineDown", val("2\n1\n3"), hasSel(1, 1, 2, 0), - "swapLineUp", val("1\n2\n3"), hasSel(0, 1, 1, 0), - "swapLineUp", val("1\n2\n3"), hasSel(0, 0, 0, 0)); - - stTest("swapLineUpFromEnd", "a\nb\nc", - Pos(2, 1), "swapLineUp", - hasSel(1, 1, 1, 1), val("a\nc\nb")); - - stTest("joinLines", "abc\ndef\nghi\njkl", - "joinLines", val("abc def\nghi\njkl"), at(0, 4), - "undo", - setSel(0, 2, 1, 1), "joinLines", - val("abc def ghi\njkl"), hasSel(0, 2, 0, 8), - "undo", - setSel(0, 1, 0, 1, - 1, 1, 1, 1, - 3, 1, 3, 1), "joinLines", - val("abc def ghi\njkl"), hasSel(0, 4, 0, 4, - 0, 8, 0, 8, - 1, 3, 1, 3)); - - stTest("duplicateLine", "abc\ndef\nghi", - Pos(1, 0), "duplicateLine", val("abc\ndef\ndef\nghi"), at(2, 0), - "undo", - setSel(0, 1, 0, 1, - 1, 1, 1, 1, - 2, 1, 2, 1), "duplicateLine", - val("abc\nabc\ndef\ndef\nghi\nghi"), hasSel(1, 1, 1, 1, - 3, 1, 3, 1, - 5, 1, 5, 1)); - stTest("duplicateLineSelection", "abcdef", - setSel(0, 1, 0, 1, - 0, 2, 0, 4, - 0, 5, 0, 5), - "duplicateLine", - val("abcdef\nabcdcdef\nabcdcdef"), hasSel(2, 1, 2, 1, - 2, 4, 2, 6, - 2, 7, 2, 7)); - - stTest("selectLinesUpward", "123\n345\n789\n012", - setSel(0, 1, 0, 1, - 1, 1, 1, 3, - 2, 0, 2, 0, - 3, 0, 3, 0), - "selectLinesUpward", - hasSel(0, 1, 0, 1, - 0, 3, 0, 3, - 1, 0, 1, 0, - 1, 1, 1, 3, - 2, 0, 2, 0, - 3, 0, 3, 0)); - - stTest("selectLinesDownward", "123\n345\n789\n012", - setSel(0, 1, 0, 1, - 1, 1, 1, 3, - 2, 0, 2, 0, - 3, 0, 3, 0), - "selectLinesDownward", - hasSel(0, 1, 0, 1, - 1, 1, 1, 3, - 2, 0, 2, 0, - 2, 3, 2, 3, - 3, 0, 3, 0)); - - stTest("sortLines", "c\nb\na\nC\nB\nA", - "sortLines", val("A\nB\nC\na\nb\nc"), - "undo", - setSel(0, 0, 2, 0, - 3, 0, 5, 0), - "sortLines", val("a\nb\nc\nA\nB\nC"), - hasSel(0, 0, 2, 1, - 3, 0, 5, 1), - "undo", - setSel(1, 0, 4, 0), "sortLinesInsensitive", val("c\na\nB\nb\nC\nA")); - - stTest("bookmarks", "abc\ndef\nghi\njkl", - Pos(0, 1), "toggleBookmark", - setSel(1, 1, 1, 2), "toggleBookmark", - setSel(2, 1, 2, 2), "toggleBookmark", - "nextBookmark", hasSel(0, 1, 0, 1), - "nextBookmark", hasSel(1, 1, 1, 2), - "nextBookmark", hasSel(2, 1, 2, 2), - "prevBookmark", hasSel(1, 1, 1, 2), - "prevBookmark", hasSel(0, 1, 0, 1), - "prevBookmark", hasSel(2, 1, 2, 2), - "prevBookmark", hasSel(1, 1, 1, 2), - "toggleBookmark", - "prevBookmark", hasSel(2, 1, 2, 2), - "prevBookmark", hasSel(0, 1, 0, 1), - "selectBookmarks", hasSel(0, 1, 0, 1, - 2, 1, 2, 2), - "clearBookmarks", - Pos(0, 0), "selectBookmarks", at(0, 0)); - - stTest("upAndDowncaseAtCursor", "abc\ndef x\nghI", - setSel(0, 1, 0, 3, - 1, 1, 1, 1, - 1, 4, 1, 4), "upcaseAtCursor", - val("aBC\nDEF x\nghI"), hasSel(0, 1, 0, 3, - 1, 3, 1, 3, - 1, 4, 1, 4), - "downcaseAtCursor", - val("abc\ndef x\nghI"), hasSel(0, 1, 0, 3, - 1, 3, 1, 3, - 1, 4, 1, 4)); - - stTest("mark", "abc\ndef\nghi", - Pos(1, 1), "setSublimeMark", - Pos(2, 1), "selectToSublimeMark", hasSel(2, 1, 1, 1), - Pos(0, 1), "swapWithSublimeMark", at(1, 1), "swapWithSublimeMark", at(0, 1), - "deleteToSublimeMark", val("aef\nghi"), - "sublimeYank", val("abc\ndef\nghi"), at(1, 1)); - - stTest("findUnder", "foo foobar a", - "findUnder", hasSel(0, 4, 0, 7), - "findUnder", hasSel(0, 0, 0, 3), - "findUnderPrevious", hasSel(0, 4, 0, 7), - "findUnderPrevious", hasSel(0, 0, 0, 3), - Pos(0, 4), "findUnder", hasSel(0, 4, 0, 10), - Pos(0, 11), "findUnder", hasSel(0, 11, 0, 11)); -})(); diff --git a/shared/html/libs/codemirror/5.0.0/test/test.js b/shared/html/libs/codemirror/5.0.0/test/test.js deleted file mode 100644 index 83d09ca..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/test.js +++ /dev/null @@ -1,2112 +0,0 @@ -var Pos = CodeMirror.Pos; - -CodeMirror.defaults.rtlMoveVisually = true; - -function forEach(arr, f) { - for (var i = 0, e = arr.length; i < e; ++i) f(arr[i], i); -} - -function addDoc(cm, width, height) { - var content = [], line = ""; - for (var i = 0; i < width; ++i) line += "x"; - for (var i = 0; i < height; ++i) content.push(line); - cm.setValue(content.join("\n")); -} - -function byClassName(elt, cls) { - if (elt.getElementsByClassName) return elt.getElementsByClassName(cls); - var found = [], re = new RegExp("\\b" + cls + "\\b"); - function search(elt) { - if (elt.nodeType == 3) return; - if (re.test(elt.className)) found.push(elt); - for (var i = 0, e = elt.childNodes.length; i < e; ++i) - search(elt.childNodes[i]); - } - search(elt); - return found; -} - -var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent); -var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent); -var mac = /Mac/.test(navigator.platform); -var phantom = /PhantomJS/.test(navigator.userAgent); -var opera = /Opera\/\./.test(navigator.userAgent); -var opera_version = opera && navigator.userAgent.match(/Version\/(\d+\.\d+)/); -if (opera_version) opera_version = Number(opera_version); -var opera_lt10 = opera && (!opera_version || opera_version < 10); - -namespace = "core_"; - -test("core_fromTextArea", function() { - var te = document.getElementById("code"); - te.value = "CONTENT"; - var cm = CodeMirror.fromTextArea(te); - is(!te.offsetHeight); - eq(cm.getValue(), "CONTENT"); - cm.setValue("foo\nbar"); - eq(cm.getValue(), "foo\nbar"); - cm.save(); - is(/^foo\r?\nbar$/.test(te.value)); - cm.setValue("xxx"); - cm.toTextArea(); - is(te.offsetHeight); - eq(te.value, "xxx"); -}); - -testCM("getRange", function(cm) { - eq(cm.getLine(0), "1234"); - eq(cm.getLine(1), "5678"); - eq(cm.getLine(2), null); - eq(cm.getLine(-1), null); - eq(cm.getRange(Pos(0, 0), Pos(0, 3)), "123"); - eq(cm.getRange(Pos(0, -1), Pos(0, 200)), "1234"); - eq(cm.getRange(Pos(0, 2), Pos(1, 2)), "34\n56"); - eq(cm.getRange(Pos(1, 2), Pos(100, 0)), "78"); -}, {value: "1234\n5678"}); - -testCM("replaceRange", function(cm) { - eq(cm.getValue(), ""); - cm.replaceRange("foo\n", Pos(0, 0)); - eq(cm.getValue(), "foo\n"); - cm.replaceRange("a\nb", Pos(0, 1)); - eq(cm.getValue(), "fa\nboo\n"); - eq(cm.lineCount(), 3); - cm.replaceRange("xyzzy", Pos(0, 0), Pos(1, 1)); - eq(cm.getValue(), "xyzzyoo\n"); - cm.replaceRange("abc", Pos(0, 0), Pos(10, 0)); - eq(cm.getValue(), "abc"); - eq(cm.lineCount(), 1); -}); - -testCM("selection", function(cm) { - cm.setSelection(Pos(0, 4), Pos(2, 2)); - is(cm.somethingSelected()); - eq(cm.getSelection(), "11\n222222\n33"); - eqPos(cm.getCursor(false), Pos(2, 2)); - eqPos(cm.getCursor(true), Pos(0, 4)); - cm.setSelection(Pos(1, 0)); - is(!cm.somethingSelected()); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(true), Pos(1, 0)); - cm.replaceSelection("abc", "around"); - eq(cm.getSelection(), "abc"); - eq(cm.getValue(), "111111\nabc222222\n333333"); - cm.replaceSelection("def", "end"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(true), Pos(1, 3)); - cm.setCursor(Pos(2, 1)); - eqPos(cm.getCursor(true), Pos(2, 1)); - cm.setCursor(1, 2); - eqPos(cm.getCursor(true), Pos(1, 2)); -}, {value: "111111\n222222\n333333"}); - -testCM("extendSelection", function(cm) { - cm.setExtending(true); - addDoc(cm, 10, 10); - cm.setSelection(Pos(3, 5)); - eqPos(cm.getCursor("head"), Pos(3, 5)); - eqPos(cm.getCursor("anchor"), Pos(3, 5)); - cm.setSelection(Pos(2, 5), Pos(5, 5)); - eqPos(cm.getCursor("head"), Pos(5, 5)); - eqPos(cm.getCursor("anchor"), Pos(2, 5)); - eqPos(cm.getCursor("start"), Pos(2, 5)); - eqPos(cm.getCursor("end"), Pos(5, 5)); - cm.setSelection(Pos(5, 5), Pos(2, 5)); - eqPos(cm.getCursor("head"), Pos(2, 5)); - eqPos(cm.getCursor("anchor"), Pos(5, 5)); - eqPos(cm.getCursor("start"), Pos(2, 5)); - eqPos(cm.getCursor("end"), Pos(5, 5)); - cm.extendSelection(Pos(3, 2)); - eqPos(cm.getCursor("head"), Pos(3, 2)); - eqPos(cm.getCursor("anchor"), Pos(5, 5)); - cm.extendSelection(Pos(6, 2)); - eqPos(cm.getCursor("head"), Pos(6, 2)); - eqPos(cm.getCursor("anchor"), Pos(5, 5)); - cm.extendSelection(Pos(6, 3), Pos(6, 4)); - eqPos(cm.getCursor("head"), Pos(6, 4)); - eqPos(cm.getCursor("anchor"), Pos(5, 5)); - cm.extendSelection(Pos(0, 3), Pos(0, 4)); - eqPos(cm.getCursor("head"), Pos(0, 3)); - eqPos(cm.getCursor("anchor"), Pos(5, 5)); - cm.extendSelection(Pos(4, 5), Pos(6, 5)); - eqPos(cm.getCursor("head"), Pos(6, 5)); - eqPos(cm.getCursor("anchor"), Pos(4, 5)); - cm.setExtending(false); - cm.extendSelection(Pos(0, 3), Pos(0, 4)); - eqPos(cm.getCursor("head"), Pos(0, 3)); - eqPos(cm.getCursor("anchor"), Pos(0, 4)); -}); - -testCM("lines", function(cm) { - eq(cm.getLine(0), "111111"); - eq(cm.getLine(1), "222222"); - eq(cm.getLine(-1), null); - cm.replaceRange("", Pos(1, 0), Pos(2, 0)) - cm.replaceRange("abc", Pos(1, 0), Pos(1)); - eq(cm.getValue(), "111111\nabc"); -}, {value: "111111\n222222\n333333"}); - -testCM("indent", function(cm) { - cm.indentLine(1); - eq(cm.getLine(1), " blah();"); - cm.setOption("indentUnit", 8); - cm.indentLine(1); - eq(cm.getLine(1), "\tblah();"); - cm.setOption("indentUnit", 10); - cm.setOption("tabSize", 4); - cm.indentLine(1); - eq(cm.getLine(1), "\t\t blah();"); -}, {value: "if (x) {\nblah();\n}", indentUnit: 3, indentWithTabs: true, tabSize: 8}); - -testCM("indentByNumber", function(cm) { - cm.indentLine(0, 2); - eq(cm.getLine(0), " foo"); - cm.indentLine(0, -200); - eq(cm.getLine(0), "foo"); - cm.setSelection(Pos(0, 0), Pos(1, 2)); - cm.indentSelection(3); - eq(cm.getValue(), " foo\n bar\nbaz"); -}, {value: "foo\nbar\nbaz"}); - -test("core_defaults", function() { - var defsCopy = {}, defs = CodeMirror.defaults; - for (var opt in defs) defsCopy[opt] = defs[opt]; - defs.indentUnit = 5; - defs.value = "uu"; - defs.indentWithTabs = true; - defs.tabindex = 55; - var place = document.getElementById("testground"), cm = CodeMirror(place); - try { - eq(cm.getOption("indentUnit"), 5); - cm.setOption("indentUnit", 10); - eq(defs.indentUnit, 5); - eq(cm.getValue(), "uu"); - eq(cm.getOption("indentWithTabs"), true); - eq(cm.getInputField().tabIndex, 55); - } - finally { - for (var opt in defsCopy) defs[opt] = defsCopy[opt]; - place.removeChild(cm.getWrapperElement()); - } -}); - -testCM("lineInfo", function(cm) { - eq(cm.lineInfo(-1), null); - var mark = document.createElement("span"); - var lh = cm.setGutterMarker(1, "FOO", mark); - var info = cm.lineInfo(1); - eq(info.text, "222222"); - eq(info.gutterMarkers.FOO, mark); - eq(info.line, 1); - eq(cm.lineInfo(2).gutterMarkers, null); - cm.setGutterMarker(lh, "FOO", null); - eq(cm.lineInfo(1).gutterMarkers, null); - cm.setGutterMarker(1, "FOO", mark); - cm.setGutterMarker(0, "FOO", mark); - cm.clearGutter("FOO"); - eq(cm.lineInfo(0).gutterMarkers, null); - eq(cm.lineInfo(1).gutterMarkers, null); -}, {value: "111111\n222222\n333333"}); - -testCM("coords", function(cm) { - cm.setSize(null, 100); - addDoc(cm, 32, 200); - var top = cm.charCoords(Pos(0, 0)); - var bot = cm.charCoords(Pos(200, 30)); - is(top.left < bot.left); - is(top.top < bot.top); - is(top.top < top.bottom); - cm.scrollTo(null, 100); - var top2 = cm.charCoords(Pos(0, 0)); - is(top.top > top2.top); - eq(top.left, top2.left); -}); - -testCM("coordsChar", function(cm) { - addDoc(cm, 35, 70); - for (var i = 0; i < 2; ++i) { - var sys = i ? "local" : "page"; - for (var ch = 0; ch <= 35; ch += 5) { - for (var line = 0; line < 70; line += 5) { - cm.setCursor(line, ch); - var coords = cm.charCoords(Pos(line, ch), sys); - var pos = cm.coordsChar({left: coords.left + 1, top: coords.top + 1}, sys); - eqPos(pos, Pos(line, ch)); - } - } - } -}, {lineNumbers: true}); - -testCM("posFromIndex", function(cm) { - cm.setValue( - "This function should\n" + - "convert a zero based index\n" + - "to line and ch." - ); - - var examples = [ - { index: -1, line: 0, ch: 0 }, // <- Tests clipping - { index: 0, line: 0, ch: 0 }, - { index: 10, line: 0, ch: 10 }, - { index: 39, line: 1, ch: 18 }, - { index: 55, line: 2, ch: 7 }, - { index: 63, line: 2, ch: 15 }, - { index: 64, line: 2, ch: 15 } // <- Tests clipping - ]; - - for (var i = 0; i < examples.length; i++) { - var example = examples[i]; - var pos = cm.posFromIndex(example.index); - eq(pos.line, example.line); - eq(pos.ch, example.ch); - if (example.index >= 0 && example.index < 64) - eq(cm.indexFromPos(pos), example.index); - } -}); - -testCM("undo", function(cm) { - cm.replaceRange("def", Pos(0, 0), Pos(0)); - eq(cm.historySize().undo, 1); - cm.undo(); - eq(cm.getValue(), "abc"); - eq(cm.historySize().undo, 0); - eq(cm.historySize().redo, 1); - cm.redo(); - eq(cm.getValue(), "def"); - eq(cm.historySize().undo, 1); - eq(cm.historySize().redo, 0); - cm.setValue("1\n\n\n2"); - cm.clearHistory(); - eq(cm.historySize().undo, 0); - for (var i = 0; i < 20; ++i) { - cm.replaceRange("a", Pos(0, 0)); - cm.replaceRange("b", Pos(3, 0)); - } - eq(cm.historySize().undo, 40); - for (var i = 0; i < 40; ++i) - cm.undo(); - eq(cm.historySize().redo, 40); - eq(cm.getValue(), "1\n\n\n2"); -}, {value: "abc"}); - -testCM("undoDepth", function(cm) { - cm.replaceRange("d", Pos(0)); - cm.replaceRange("e", Pos(0)); - cm.replaceRange("f", Pos(0)); - cm.undo(); cm.undo(); cm.undo(); - eq(cm.getValue(), "abcd"); -}, {value: "abc", undoDepth: 4}); - -testCM("undoDoesntClearValue", function(cm) { - cm.undo(); - eq(cm.getValue(), "x"); -}, {value: "x"}); - -testCM("undoMultiLine", function(cm) { - cm.operation(function() { - cm.replaceRange("x", Pos(0, 0)); - cm.replaceRange("y", Pos(1, 0)); - }); - cm.undo(); - eq(cm.getValue(), "abc\ndef\nghi"); - cm.operation(function() { - cm.replaceRange("y", Pos(1, 0)); - cm.replaceRange("x", Pos(0, 0)); - }); - cm.undo(); - eq(cm.getValue(), "abc\ndef\nghi"); - cm.operation(function() { - cm.replaceRange("y", Pos(2, 0)); - cm.replaceRange("x", Pos(1, 0)); - cm.replaceRange("z", Pos(2, 0)); - }); - cm.undo(); - eq(cm.getValue(), "abc\ndef\nghi", 3); -}, {value: "abc\ndef\nghi"}); - -testCM("undoComposite", function(cm) { - cm.replaceRange("y", Pos(1)); - cm.operation(function() { - cm.replaceRange("x", Pos(0)); - cm.replaceRange("z", Pos(2)); - }); - eq(cm.getValue(), "ax\nby\ncz\n"); - cm.undo(); - eq(cm.getValue(), "a\nby\nc\n"); - cm.undo(); - eq(cm.getValue(), "a\nb\nc\n"); - cm.redo(); cm.redo(); - eq(cm.getValue(), "ax\nby\ncz\n"); -}, {value: "a\nb\nc\n"}); - -testCM("undoSelection", function(cm) { - cm.setSelection(Pos(0, 2), Pos(0, 4)); - cm.replaceSelection(""); - cm.setCursor(Pos(1, 0)); - cm.undo(); - eqPos(cm.getCursor(true), Pos(0, 2)); - eqPos(cm.getCursor(false), Pos(0, 4)); - cm.setCursor(Pos(1, 0)); - cm.redo(); - eqPos(cm.getCursor(true), Pos(0, 2)); - eqPos(cm.getCursor(false), Pos(0, 2)); -}, {value: "abcdefgh\n"}); - -testCM("undoSelectionAsBefore", function(cm) { - cm.replaceSelection("abc", "around"); - cm.undo(); - cm.redo(); - eq(cm.getSelection(), "abc"); -}); - -testCM("selectionChangeConfusesHistory", function(cm) { - cm.replaceSelection("abc", null, "dontmerge"); - cm.operation(function() { - cm.setCursor(Pos(0, 0)); - cm.replaceSelection("abc", null, "dontmerge"); - }); - eq(cm.historySize().undo, 2); -}); - -testCM("markTextSingleLine", function(cm) { - forEach([{a: 0, b: 1, c: "", f: 2, t: 5}, - {a: 0, b: 4, c: "", f: 0, t: 2}, - {a: 1, b: 2, c: "x", f: 3, t: 6}, - {a: 4, b: 5, c: "", f: 3, t: 5}, - {a: 4, b: 5, c: "xx", f: 3, t: 7}, - {a: 2, b: 5, c: "", f: 2, t: 3}, - {a: 2, b: 5, c: "abcd", f: 6, t: 7}, - {a: 2, b: 6, c: "x", f: null, t: null}, - {a: 3, b: 6, c: "", f: null, t: null}, - {a: 0, b: 9, c: "hallo", f: null, t: null}, - {a: 4, b: 6, c: "x", f: 3, t: 4}, - {a: 4, b: 8, c: "", f: 3, t: 4}, - {a: 6, b: 6, c: "a", f: 3, t: 6}, - {a: 8, b: 9, c: "", f: 3, t: 6}], function(test) { - cm.setValue("1234567890"); - var r = cm.markText(Pos(0, 3), Pos(0, 6), {className: "foo"}); - cm.replaceRange(test.c, Pos(0, test.a), Pos(0, test.b)); - var f = r.find(); - eq(f && f.from.ch, test.f); eq(f && f.to.ch, test.t); - }); -}); - -testCM("markTextMultiLine", function(cm) { - function p(v) { return v && Pos(v[0], v[1]); } - forEach([{a: [0, 0], b: [0, 5], c: "", f: [0, 0], t: [2, 5]}, - {a: [0, 0], b: [0, 5], c: "foo\n", f: [1, 0], t: [3, 5]}, - {a: [0, 1], b: [0, 10], c: "", f: [0, 1], t: [2, 5]}, - {a: [0, 5], b: [0, 6], c: "x", f: [0, 6], t: [2, 5]}, - {a: [0, 0], b: [1, 0], c: "", f: [0, 0], t: [1, 5]}, - {a: [0, 6], b: [2, 4], c: "", f: [0, 5], t: [0, 7]}, - {a: [0, 6], b: [2, 4], c: "aa", f: [0, 5], t: [0, 9]}, - {a: [1, 2], b: [1, 8], c: "", f: [0, 5], t: [2, 5]}, - {a: [0, 5], b: [2, 5], c: "xx", f: null, t: null}, - {a: [0, 0], b: [2, 10], c: "x", f: null, t: null}, - {a: [1, 5], b: [2, 5], c: "", f: [0, 5], t: [1, 5]}, - {a: [2, 0], b: [2, 3], c: "", f: [0, 5], t: [2, 2]}, - {a: [2, 5], b: [3, 0], c: "a\nb", f: [0, 5], t: [2, 5]}, - {a: [2, 3], b: [3, 0], c: "x", f: [0, 5], t: [2, 3]}, - {a: [1, 1], b: [1, 9], c: "1\n2\n3", f: [0, 5], t: [4, 5]}], function(test) { - cm.setValue("aaaaaaaaaa\nbbbbbbbbbb\ncccccccccc\ndddddddd\n"); - var r = cm.markText(Pos(0, 5), Pos(2, 5), - {className: "CodeMirror-matchingbracket"}); - cm.replaceRange(test.c, p(test.a), p(test.b)); - var f = r.find(); - eqPos(f && f.from, p(test.f)); eqPos(f && f.to, p(test.t)); - }); -}); - -testCM("markTextUndo", function(cm) { - var marker1, marker2, bookmark; - marker1 = cm.markText(Pos(0, 1), Pos(0, 3), - {className: "CodeMirror-matchingbracket"}); - marker2 = cm.markText(Pos(0, 0), Pos(2, 1), - {className: "CodeMirror-matchingbracket"}); - bookmark = cm.setBookmark(Pos(1, 5)); - cm.operation(function(){ - cm.replaceRange("foo", Pos(0, 2)); - cm.replaceRange("bar\nbaz\nbug\n", Pos(2, 0), Pos(3, 0)); - }); - var v1 = cm.getValue(); - cm.setValue(""); - eq(marker1.find(), null); eq(marker2.find(), null); eq(bookmark.find(), null); - cm.undo(); - eqPos(bookmark.find(), Pos(1, 5), "still there"); - cm.undo(); - var m1Pos = marker1.find(), m2Pos = marker2.find(); - eqPos(m1Pos.from, Pos(0, 1)); eqPos(m1Pos.to, Pos(0, 3)); - eqPos(m2Pos.from, Pos(0, 0)); eqPos(m2Pos.to, Pos(2, 1)); - eqPos(bookmark.find(), Pos(1, 5)); - cm.redo(); cm.redo(); - eq(bookmark.find(), null); - cm.undo(); - eqPos(bookmark.find(), Pos(1, 5)); - eq(cm.getValue(), v1); -}, {value: "1234\n56789\n00\n"}); - -testCM("markTextStayGone", function(cm) { - var m1 = cm.markText(Pos(0, 0), Pos(0, 1)); - cm.replaceRange("hi", Pos(0, 2)); - m1.clear(); - cm.undo(); - eq(m1.find(), null); -}, {value: "hello"}); - -testCM("markTextAllowEmpty", function(cm) { - var m1 = cm.markText(Pos(0, 1), Pos(0, 2), {clearWhenEmpty: false}); - is(m1.find()); - cm.replaceRange("x", Pos(0, 0)); - is(m1.find()); - cm.replaceRange("y", Pos(0, 2)); - is(m1.find()); - cm.replaceRange("z", Pos(0, 3), Pos(0, 4)); - is(!m1.find()); - var m2 = cm.markText(Pos(0, 1), Pos(0, 2), {clearWhenEmpty: false, - inclusiveLeft: true, - inclusiveRight: true}); - cm.replaceRange("q", Pos(0, 1), Pos(0, 2)); - is(m2.find()); - cm.replaceRange("", Pos(0, 0), Pos(0, 3)); - is(!m2.find()); - var m3 = cm.markText(Pos(0, 1), Pos(0, 1), {clearWhenEmpty: false}); - cm.replaceRange("a", Pos(0, 3)); - is(m3.find()); - cm.replaceRange("b", Pos(0, 1)); - is(!m3.find()); -}, {value: "abcde"}); - -testCM("markTextStacked", function(cm) { - var m1 = cm.markText(Pos(0, 0), Pos(0, 0), {clearWhenEmpty: false}); - var m2 = cm.markText(Pos(0, 0), Pos(0, 0), {clearWhenEmpty: false}); - cm.replaceRange("B", Pos(0, 1)); - is(m1.find() && m2.find()); -}, {value: "A"}); - -testCM("undoPreservesNewMarks", function(cm) { - cm.markText(Pos(0, 3), Pos(0, 4)); - cm.markText(Pos(1, 1), Pos(1, 3)); - cm.replaceRange("", Pos(0, 3), Pos(3, 1)); - var mBefore = cm.markText(Pos(0, 0), Pos(0, 1)); - var mAfter = cm.markText(Pos(0, 5), Pos(0, 6)); - var mAround = cm.markText(Pos(0, 2), Pos(0, 4)); - cm.undo(); - eqPos(mBefore.find().from, Pos(0, 0)); - eqPos(mBefore.find().to, Pos(0, 1)); - eqPos(mAfter.find().from, Pos(3, 3)); - eqPos(mAfter.find().to, Pos(3, 4)); - eqPos(mAround.find().from, Pos(0, 2)); - eqPos(mAround.find().to, Pos(3, 2)); - var found = cm.findMarksAt(Pos(2, 2)); - eq(found.length, 1); - eq(found[0], mAround); -}, {value: "aaaa\nbbbb\ncccc\ndddd"}); - -testCM("markClearBetween", function(cm) { - cm.setValue("aaa\nbbb\nccc\nddd\n"); - cm.markText(Pos(0, 0), Pos(2)); - cm.replaceRange("aaa\nbbb\nccc", Pos(0, 0), Pos(2)); - eq(cm.findMarksAt(Pos(1, 1)).length, 0); -}); - -testCM("deleteSpanCollapsedInclusiveLeft", function(cm) { - var from = Pos(1, 0), to = Pos(1, 1); - var m = cm.markText(from, to, {collapsed: true, inclusiveLeft: true}); - // Delete collapsed span. - cm.replaceRange("", from, to); -}, {value: "abc\nX\ndef"}); - -testCM("markTextCSS", function(cm) { - function present() { - var spans = cm.display.lineDiv.getElementsByTagName("span"); - for (var i = 0; i < spans.length; i++) - if (spans[i].style.color == "cyan" && span[i].textContent == "cdefg") return true; - } - var m = cm.markText(Pos(0, 2), Pos(0, 6), {css: "color: cyan"}); - m.clear(); - is(!present()); -}, {value: "abcdefgh"}); - -testCM("bookmark", function(cm) { - function p(v) { return v && Pos(v[0], v[1]); } - forEach([{a: [1, 0], b: [1, 1], c: "", d: [1, 4]}, - {a: [1, 1], b: [1, 1], c: "xx", d: [1, 7]}, - {a: [1, 4], b: [1, 5], c: "ab", d: [1, 6]}, - {a: [1, 4], b: [1, 6], c: "", d: null}, - {a: [1, 5], b: [1, 6], c: "abc", d: [1, 5]}, - {a: [1, 6], b: [1, 8], c: "", d: [1, 5]}, - {a: [1, 4], b: [1, 4], c: "\n\n", d: [3, 1]}, - {bm: [1, 9], a: [1, 1], b: [1, 1], c: "\n", d: [2, 8]}], function(test) { - cm.setValue("1234567890\n1234567890\n1234567890"); - var b = cm.setBookmark(p(test.bm) || Pos(1, 5)); - cm.replaceRange(test.c, p(test.a), p(test.b)); - eqPos(b.find(), p(test.d)); - }); -}); - -testCM("bookmarkInsertLeft", function(cm) { - var br = cm.setBookmark(Pos(0, 2), {insertLeft: false}); - var bl = cm.setBookmark(Pos(0, 2), {insertLeft: true}); - cm.setCursor(Pos(0, 2)); - cm.replaceSelection("hi"); - eqPos(br.find(), Pos(0, 2)); - eqPos(bl.find(), Pos(0, 4)); - cm.replaceRange("", Pos(0, 4), Pos(0, 5)); - cm.replaceRange("", Pos(0, 2), Pos(0, 4)); - cm.replaceRange("", Pos(0, 1), Pos(0, 2)); - // Verify that deleting next to bookmarks doesn't kill them - eqPos(br.find(), Pos(0, 1)); - eqPos(bl.find(), Pos(0, 1)); -}, {value: "abcdef"}); - -testCM("bookmarkCursor", function(cm) { - var pos01 = cm.cursorCoords(Pos(0, 1)), pos11 = cm.cursorCoords(Pos(1, 1)), - pos20 = cm.cursorCoords(Pos(2, 0)), pos30 = cm.cursorCoords(Pos(3, 0)), - pos41 = cm.cursorCoords(Pos(4, 1)); - cm.setBookmark(Pos(0, 1), {widget: document.createTextNode("←"), insertLeft: true}); - cm.setBookmark(Pos(2, 0), {widget: document.createTextNode("←"), insertLeft: true}); - cm.setBookmark(Pos(1, 1), {widget: document.createTextNode("→")}); - cm.setBookmark(Pos(3, 0), {widget: document.createTextNode("→")}); - var new01 = cm.cursorCoords(Pos(0, 1)), new11 = cm.cursorCoords(Pos(1, 1)), - new20 = cm.cursorCoords(Pos(2, 0)), new30 = cm.cursorCoords(Pos(3, 0)); - near(new01.left, pos01.left, 1); - near(new01.top, pos01.top, 1); - is(new11.left > pos11.left, "at right, middle of line"); - near(new11.top == pos11.top, 1); - near(new20.left, pos20.left, 1); - near(new20.top, pos20.top, 1); - is(new30.left > pos30.left, "at right, empty line"); - near(new30.top, pos30, 1); - cm.setBookmark(Pos(4, 0), {widget: document.createTextNode("→")}); - is(cm.cursorCoords(Pos(4, 1)).left > pos41.left, "single-char bug"); -}, {value: "foo\nbar\n\n\nx\ny"}); - -testCM("multiBookmarkCursor", function(cm) { - if (phantom) return; - var ms = [], m; - function add(insertLeft) { - for (var i = 0; i < 3; ++i) { - var node = document.createElement("span"); - node.innerHTML = "X"; - ms.push(cm.setBookmark(Pos(0, 1), {widget: node, insertLeft: insertLeft})); - } - } - var base1 = cm.cursorCoords(Pos(0, 1)).left, base4 = cm.cursorCoords(Pos(0, 4)).left; - add(true); - near(base1, cm.cursorCoords(Pos(0, 1)).left, 1); - while (m = ms.pop()) m.clear(); - add(false); - near(base4, cm.cursorCoords(Pos(0, 1)).left, 1); -}, {value: "abcdefg"}); - -testCM("getAllMarks", function(cm) { - addDoc(cm, 10, 10); - var m1 = cm.setBookmark(Pos(0, 2)); - var m2 = cm.markText(Pos(0, 2), Pos(3, 2)); - var m3 = cm.markText(Pos(1, 2), Pos(1, 8)); - var m4 = cm.markText(Pos(8, 0), Pos(9, 0)); - eq(cm.getAllMarks().length, 4); - m1.clear(); - m3.clear(); - eq(cm.getAllMarks().length, 2); -}); - -testCM("setValueClears", function(cm) { - cm.addLineClass(0, "wrap", "foo"); - var mark = cm.markText(Pos(0, 0), Pos(1, 1), {inclusiveLeft: true, inclusiveRight: true}); - cm.setValue("foo"); - is(!cm.lineInfo(0).wrapClass); - is(!mark.find()); -}, {value: "a\nb"}); - -testCM("bug577", function(cm) { - cm.setValue("a\nb"); - cm.clearHistory(); - cm.setValue("fooooo"); - cm.undo(); -}); - -testCM("scrollSnap", function(cm) { - cm.setSize(100, 100); - addDoc(cm, 200, 200); - cm.setCursor(Pos(100, 180)); - var info = cm.getScrollInfo(); - is(info.left > 0 && info.top > 0); - cm.setCursor(Pos(0, 0)); - info = cm.getScrollInfo(); - is(info.left == 0 && info.top == 0, "scrolled clean to top"); - cm.setCursor(Pos(100, 180)); - cm.setCursor(Pos(199, 0)); - info = cm.getScrollInfo(); - is(info.left == 0 && info.top + 2 > info.height - cm.getScrollerElement().clientHeight, "scrolled clean to bottom"); -}); - -testCM("scrollIntoView", function(cm) { - if (phantom) return; - var outer = cm.getWrapperElement().getBoundingClientRect(); - function test(line, ch, msg) { - var pos = Pos(line, ch); - cm.scrollIntoView(pos); - var box = cm.charCoords(pos, "window"); - is(box.left >= outer.left, msg + " (left)"); - is(box.right <= outer.right, msg + " (right)"); - is(box.top >= outer.top, msg + " (top)"); - is(box.bottom <= outer.bottom, msg + " (bottom)"); - } - addDoc(cm, 200, 200); - test(199, 199, "bottom right"); - test(0, 0, "top left"); - test(100, 100, "center"); - test(199, 0, "bottom left"); - test(0, 199, "top right"); - test(100, 100, "center again"); -}); - -testCM("scrollBackAndForth", function(cm) { - addDoc(cm, 1, 200); - cm.operation(function() { - cm.scrollIntoView(Pos(199, 0)); - cm.scrollIntoView(Pos(4, 0)); - }); - is(cm.getScrollInfo().top > 0); -}); - -testCM("selectAllNoScroll", function(cm) { - addDoc(cm, 1, 200); - cm.execCommand("selectAll"); - eq(cm.getScrollInfo().top, 0); - cm.setCursor(199); - cm.execCommand("selectAll"); - is(cm.getScrollInfo().top > 0); -}); - -testCM("selectionPos", function(cm) { - if (phantom || cm.getOption("inputStyle") != "textarea") return; - cm.setSize(100, 100); - addDoc(cm, 200, 100); - cm.setSelection(Pos(1, 100), Pos(98, 100)); - var lineWidth = cm.charCoords(Pos(0, 200), "local").left; - var lineHeight = (cm.charCoords(Pos(99)).top - cm.charCoords(Pos(0)).top) / 100; - cm.scrollTo(0, 0); - var selElt = byClassName(cm.getWrapperElement(), "CodeMirror-selected"); - var outer = cm.getWrapperElement().getBoundingClientRect(); - var sawMiddle, sawTop, sawBottom; - for (var i = 0, e = selElt.length; i < e; ++i) { - var box = selElt[i].getBoundingClientRect(); - var atLeft = box.left - outer.left < 30; - var width = box.right - box.left; - var atRight = box.right - outer.left > .8 * lineWidth; - if (atLeft && atRight) { - sawMiddle = true; - is(box.bottom - box.top > 90 * lineHeight, "middle high"); - is(width > .9 * lineWidth, "middle wide"); - } else { - is(width > .4 * lineWidth, "top/bot wide enough"); - is(width < .6 * lineWidth, "top/bot slim enough"); - if (atLeft) { - sawBottom = true; - is(box.top - outer.top > 96 * lineHeight, "bot below"); - } else if (atRight) { - sawTop = true; - is(box.top - outer.top < 2.1 * lineHeight, "top above"); - } - } - } - is(sawTop && sawBottom && sawMiddle, "all parts"); -}, null); - -testCM("restoreHistory", function(cm) { - cm.setValue("abc\ndef"); - cm.replaceRange("hello", Pos(1, 0), Pos(1)); - cm.replaceRange("goop", Pos(0, 0), Pos(0)); - cm.undo(); - var storedVal = cm.getValue(), storedHist = cm.getHistory(); - if (window.JSON) storedHist = JSON.parse(JSON.stringify(storedHist)); - eq(storedVal, "abc\nhello"); - cm.setValue(""); - cm.clearHistory(); - eq(cm.historySize().undo, 0); - cm.setValue(storedVal); - cm.setHistory(storedHist); - cm.redo(); - eq(cm.getValue(), "goop\nhello"); - cm.undo(); cm.undo(); - eq(cm.getValue(), "abc\ndef"); -}); - -testCM("doubleScrollbar", function(cm) { - var dummy = document.body.appendChild(document.createElement("p")); - dummy.style.cssText = "height: 50px; overflow: scroll; width: 50px"; - var scrollbarWidth = dummy.offsetWidth + 1 - dummy.clientWidth; - document.body.removeChild(dummy); - if (scrollbarWidth < 2) return; - cm.setSize(null, 100); - addDoc(cm, 1, 300); - var wrap = cm.getWrapperElement(); - is(wrap.offsetWidth - byClassName(wrap, "CodeMirror-lines")[0].offsetWidth <= scrollbarWidth * 1.5); -}); - -testCM("weirdLinebreaks", function(cm) { - cm.setValue("foo\nbar\rbaz\r\nquux\n\rplop"); - is(cm.getValue(), "foo\nbar\nbaz\nquux\n\nplop"); - is(cm.lineCount(), 6); - cm.setValue("\n\n"); - is(cm.lineCount(), 3); -}); - -testCM("setSize", function(cm) { - cm.setSize(100, 100); - var wrap = cm.getWrapperElement(); - is(wrap.offsetWidth, 100); - is(wrap.offsetHeight, 100); - cm.setSize("100%", "3em"); - is(wrap.style.width, "100%"); - is(wrap.style.height, "3em"); - cm.setSize(null, 40); - is(wrap.style.width, "100%"); - is(wrap.style.height, "40px"); -}); - -function foldLines(cm, start, end, autoClear) { - return cm.markText(Pos(start, 0), Pos(end - 1), { - inclusiveLeft: true, - inclusiveRight: true, - collapsed: true, - clearOnEnter: autoClear - }); -} - -testCM("collapsedLines", function(cm) { - addDoc(cm, 4, 10); - var range = foldLines(cm, 4, 5), cleared = 0; - CodeMirror.on(range, "clear", function() {cleared++;}); - cm.setCursor(Pos(3, 0)); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(5, 0)); - cm.replaceRange("abcdefg", Pos(3, 0), Pos(3)); - cm.setCursor(Pos(3, 6)); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(5, 4)); - cm.replaceRange("ab", Pos(3, 0), Pos(3)); - cm.setCursor(Pos(3, 2)); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(5, 2)); - cm.operation(function() {range.clear(); range.clear();}); - eq(cleared, 1); -}); - -testCM("collapsedRangeCoordsChar", function(cm) { - var pos_1_3 = cm.charCoords(Pos(1, 3)); - pos_1_3.left += 2; pos_1_3.top += 2; - var opts = {collapsed: true, inclusiveLeft: true, inclusiveRight: true}; - var m1 = cm.markText(Pos(0, 0), Pos(2, 0), opts); - eqPos(cm.coordsChar(pos_1_3), Pos(3, 3)); - m1.clear(); - var m1 = cm.markText(Pos(0, 0), Pos(1, 1), {collapsed: true, inclusiveLeft: true}); - var m2 = cm.markText(Pos(1, 1), Pos(2, 0), {collapsed: true, inclusiveRight: true}); - eqPos(cm.coordsChar(pos_1_3), Pos(3, 3)); - m1.clear(); m2.clear(); - var m1 = cm.markText(Pos(0, 0), Pos(1, 6), opts); - eqPos(cm.coordsChar(pos_1_3), Pos(3, 3)); -}, {value: "123456\nabcdef\nghijkl\nmnopqr\n"}); - -testCM("collapsedRangeBetweenLinesSelected", function(cm) { - if (cm.getOption("inputStyle") != "textarea") return; - var widget = document.createElement("span"); - widget.textContent = "\u2194"; - cm.markText(Pos(0, 3), Pos(1, 0), {replacedWith: widget}); - cm.setSelection(Pos(0, 3), Pos(1, 0)); - var selElts = byClassName(cm.getWrapperElement(), "CodeMirror-selected"); - for (var i = 0, w = 0; i < selElts.length; i++) - w += selElts[i].offsetWidth; - is(w > 0); -}, {value: "one\ntwo"}); - -testCM("randomCollapsedRanges", function(cm) { - addDoc(cm, 20, 500); - cm.operation(function() { - for (var i = 0; i < 200; i++) { - var start = Pos(Math.floor(Math.random() * 500), Math.floor(Math.random() * 20)); - if (i % 4) - try { cm.markText(start, Pos(start.line + 2, 1), {collapsed: true}); } - catch(e) { if (!/overlapping/.test(String(e))) throw e; } - else - cm.markText(start, Pos(start.line, start.ch + 4), {"className": "foo"}); - } - }); -}); - -testCM("hiddenLinesAutoUnfold", function(cm) { - var range = foldLines(cm, 1, 3, true), cleared = 0; - CodeMirror.on(range, "clear", function() {cleared++;}); - cm.setCursor(Pos(3, 0)); - eq(cleared, 0); - cm.execCommand("goCharLeft"); - eq(cleared, 1); - range = foldLines(cm, 1, 3, true); - CodeMirror.on(range, "clear", function() {cleared++;}); - eqPos(cm.getCursor(), Pos(3, 0)); - cm.setCursor(Pos(0, 3)); - cm.execCommand("goCharRight"); - eq(cleared, 2); -}, {value: "abc\ndef\nghi\njkl"}); - -testCM("hiddenLinesSelectAll", function(cm) { // Issue #484 - addDoc(cm, 4, 20); - foldLines(cm, 0, 10); - foldLines(cm, 11, 20); - CodeMirror.commands.selectAll(cm); - eqPos(cm.getCursor(true), Pos(10, 0)); - eqPos(cm.getCursor(false), Pos(10, 4)); -}); - - -testCM("everythingFolded", function(cm) { - addDoc(cm, 2, 2); - function enterPress() { - cm.triggerOnKeyDown({type: "keydown", keyCode: 13, preventDefault: function(){}, stopPropagation: function(){}}); - } - var fold = foldLines(cm, 0, 2); - enterPress(); - eq(cm.getValue(), "xx\nxx"); - fold.clear(); - fold = foldLines(cm, 0, 2, true); - eq(fold.find(), null); - enterPress(); - eq(cm.getValue(), "\nxx\nxx"); -}); - -testCM("structuredFold", function(cm) { - if (phantom) return; - addDoc(cm, 4, 8); - var range = cm.markText(Pos(1, 2), Pos(6, 2), { - replacedWith: document.createTextNode("Q") - }); - cm.setCursor(0, 3); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(6, 2)); - CodeMirror.commands.goCharLeft(cm); - eqPos(cm.getCursor(), Pos(1, 2)); - CodeMirror.commands.delCharAfter(cm); - eq(cm.getValue(), "xxxx\nxxxx\nxxxx"); - addDoc(cm, 4, 8); - range = cm.markText(Pos(1, 2), Pos(6, 2), { - replacedWith: document.createTextNode("M"), - clearOnEnter: true - }); - var cleared = 0; - CodeMirror.on(range, "clear", function(){++cleared;}); - cm.setCursor(0, 3); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(6, 2)); - CodeMirror.commands.goCharLeft(cm); - eqPos(cm.getCursor(), Pos(6, 1)); - eq(cleared, 1); - range.clear(); - eq(cleared, 1); - range = cm.markText(Pos(1, 2), Pos(6, 2), { - replacedWith: document.createTextNode("Q"), - clearOnEnter: true - }); - range.clear(); - cm.setCursor(1, 2); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(1, 3)); - range = cm.markText(Pos(2, 0), Pos(4, 4), { - replacedWith: document.createTextNode("M") - }); - cm.setCursor(1, 0); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(2, 0)); -}, null); - -testCM("nestedFold", function(cm) { - addDoc(cm, 10, 3); - function fold(ll, cl, lr, cr) { - return cm.markText(Pos(ll, cl), Pos(lr, cr), {collapsed: true}); - } - var inner1 = fold(0, 6, 1, 3), inner2 = fold(0, 2, 1, 8), outer = fold(0, 1, 2, 3), inner0 = fold(0, 5, 0, 6); - cm.setCursor(0, 1); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(2, 3)); - inner0.clear(); - CodeMirror.commands.goCharLeft(cm); - eqPos(cm.getCursor(), Pos(0, 1)); - outer.clear(); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(0, 2)); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(1, 8)); - inner2.clear(); - CodeMirror.commands.goCharLeft(cm); - eqPos(cm.getCursor(), Pos(1, 7)); - cm.setCursor(0, 5); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(0, 6)); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(1, 3)); -}); - -testCM("badNestedFold", function(cm) { - addDoc(cm, 4, 4); - cm.markText(Pos(0, 2), Pos(3, 2), {collapsed: true}); - var caught; - try {cm.markText(Pos(0, 1), Pos(0, 3), {collapsed: true});} - catch(e) {caught = e;} - is(caught instanceof Error, "no error"); - is(/overlap/i.test(caught.message), "wrong error"); -}); - -testCM("nestedFoldOnSide", function(cm) { - var m1 = cm.markText(Pos(0, 1), Pos(2, 1), {collapsed: true, inclusiveRight: true}); - var m2 = cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true}); - cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true}).clear(); - try { cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true, inclusiveLeft: true}); } - catch(e) { var caught = e; } - is(caught && /overlap/i.test(caught.message)); - var m3 = cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true}); - var m4 = cm.markText(Pos(2, 0), Pos(2, 1), {collapse: true, inclusiveRight: true}); - m1.clear(); m4.clear(); - m1 = cm.markText(Pos(0, 1), Pos(2, 1), {collapsed: true}); - cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true}).clear(); - try { cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true, inclusiveRight: true}); } - catch(e) { var caught = e; } - is(caught && /overlap/i.test(caught.message)); -}, {value: "ab\ncd\ef"}); - -testCM("editInFold", function(cm) { - addDoc(cm, 4, 6); - var m = cm.markText(Pos(1, 2), Pos(3, 2), {collapsed: true}); - cm.replaceRange("", Pos(0, 0), Pos(1, 3)); - cm.replaceRange("", Pos(2, 1), Pos(3, 3)); - cm.replaceRange("a\nb\nc\nd", Pos(0, 1), Pos(1, 0)); - cm.cursorCoords(Pos(0, 0)); -}); - -testCM("wrappingInlineWidget", function(cm) { - cm.setSize("11em"); - var w = document.createElement("span"); - w.style.color = "red"; - w.innerHTML = "one two three four"; - cm.markText(Pos(0, 6), Pos(0, 9), {replacedWith: w}); - var cur0 = cm.cursorCoords(Pos(0, 0)), cur1 = cm.cursorCoords(Pos(0, 10)); - is(cur0.top < cur1.top); - is(cur0.bottom < cur1.bottom); - var curL = cm.cursorCoords(Pos(0, 6)), curR = cm.cursorCoords(Pos(0, 9)); - eq(curL.top, cur0.top); - eq(curL.bottom, cur0.bottom); - eq(curR.top, cur1.top); - eq(curR.bottom, cur1.bottom); - cm.replaceRange("", Pos(0, 9), Pos(0)); - curR = cm.cursorCoords(Pos(0, 9)); - if (phantom) return; - eq(curR.top, cur1.top); - eq(curR.bottom, cur1.bottom); -}, {value: "1 2 3 xxx 4", lineWrapping: true}); - -testCM("changedInlineWidget", function(cm) { - cm.setSize("10em"); - var w = document.createElement("span"); - w.innerHTML = "x"; - var m = cm.markText(Pos(0, 4), Pos(0, 5), {replacedWith: w}); - w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed"; - m.changed(); - var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0]; - is(hScroll.scrollWidth > hScroll.clientWidth); -}, {value: "hello there"}); - -testCM("changedBookmark", function(cm) { - cm.setSize("10em"); - var w = document.createElement("span"); - w.innerHTML = "x"; - var m = cm.setBookmark(Pos(0, 4), {widget: w}); - w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed"; - m.changed(); - var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0]; - is(hScroll.scrollWidth > hScroll.clientWidth); -}, {value: "abcdefg"}); - -testCM("inlineWidget", function(cm) { - var w = cm.setBookmark(Pos(0, 2), {widget: document.createTextNode("uu")}); - cm.setCursor(0, 2); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(1, 4)); - cm.setCursor(0, 2); - cm.replaceSelection("hi"); - eqPos(w.find(), Pos(0, 2)); - cm.setCursor(0, 1); - cm.replaceSelection("ay"); - eqPos(w.find(), Pos(0, 4)); - eq(cm.getLine(0), "uayuhiuu"); -}, {value: "uuuu\nuuuuuu"}); - -testCM("wrappingAndResizing", function(cm) { - cm.setSize(null, "auto"); - cm.setOption("lineWrapping", true); - var wrap = cm.getWrapperElement(), h0 = wrap.offsetHeight; - var doc = "xxx xxx xxx xxx xxx"; - cm.setValue(doc); - for (var step = 10, w = cm.charCoords(Pos(0, 18), "div").right;; w += step) { - cm.setSize(w); - if (wrap.offsetHeight <= h0 * (opera_lt10 ? 1.2 : 1.5)) { - if (step == 10) { w -= 10; step = 1; } - else break; - } - } - // Ensure that putting the cursor at the end of the maximally long - // line doesn't cause wrapping to happen. - cm.setCursor(Pos(0, doc.length)); - eq(wrap.offsetHeight, h0); - cm.replaceSelection("x"); - is(wrap.offsetHeight > h0, "wrapping happens"); - // Now add a max-height and, in a document consisting of - // almost-wrapped lines, go over it so that a scrollbar appears. - cm.setValue(doc + "\n" + doc + "\n"); - cm.getScrollerElement().style.maxHeight = "100px"; - cm.replaceRange("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n!\n", Pos(2, 0)); - forEach([Pos(0, doc.length), Pos(0, doc.length - 1), - Pos(0, 0), Pos(1, doc.length), Pos(1, doc.length - 1)], - function(pos) { - var coords = cm.charCoords(pos); - eqPos(pos, cm.coordsChar({left: coords.left + 2, top: coords.top + 5})); - }); -}, null, ie_lt8); - -testCM("measureEndOfLine", function(cm) { - cm.setSize(null, "auto"); - var inner = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild; - var lh = inner.offsetHeight; - for (var step = 10, w = cm.charCoords(Pos(0, 7), "div").right;; w += step) { - cm.setSize(w); - if (inner.offsetHeight < 2.5 * lh) { - if (step == 10) { w -= 10; step = 1; } - else break; - } - } - cm.setValue(cm.getValue() + "\n\n"); - var endPos = cm.charCoords(Pos(0, 18), "local"); - is(endPos.top > lh * .8, "not at top"); - is(endPos.left > w - 20, "not at right"); - endPos = cm.charCoords(Pos(0, 18)); - eqPos(cm.coordsChar({left: endPos.left, top: endPos.top + 5}), Pos(0, 18)); -}, {mode: "text/html", value: "", lineWrapping: true}, ie_lt8 || opera_lt10); - -testCM("scrollVerticallyAndHorizontally", function(cm) { - if (cm.getOption("inputStyle") != "textarea") return; - cm.setSize(100, 100); - addDoc(cm, 40, 40); - cm.setCursor(39); - var wrap = cm.getWrapperElement(), bar = byClassName(wrap, "CodeMirror-vscrollbar")[0]; - is(bar.offsetHeight < wrap.offsetHeight, "vertical scrollbar limited by horizontal one"); - var cursorBox = byClassName(wrap, "CodeMirror-cursor")[0].getBoundingClientRect(); - var editorBox = wrap.getBoundingClientRect(); - is(cursorBox.bottom < editorBox.top + cm.getScrollerElement().clientHeight, - "bottom line visible"); -}, {lineNumbers: true}); - -testCM("moveVstuck", function(cm) { - var lines = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild, h0 = lines.offsetHeight; - var val = "fooooooooooooooooooooooooo baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar\n"; - cm.setValue(val); - for (var w = cm.charCoords(Pos(0, 26), "div").right * 2.8;; w += 5) { - cm.setSize(w); - if (lines.offsetHeight <= 3.5 * h0) break; - } - cm.setCursor(Pos(0, val.length - 1)); - cm.moveV(-1, "line"); - eqPos(cm.getCursor(), Pos(0, 26)); -}, {lineWrapping: true}, ie_lt8 || opera_lt10); - -testCM("collapseOnMove", function(cm) { - cm.setSelection(Pos(0, 1), Pos(2, 4)); - cm.execCommand("goLineUp"); - is(!cm.somethingSelected()); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.setSelection(Pos(0, 1), Pos(2, 4)); - cm.execCommand("goPageDown"); - is(!cm.somethingSelected()); - eqPos(cm.getCursor(), Pos(2, 4)); - cm.execCommand("goLineUp"); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.setSelection(Pos(0, 1), Pos(2, 4)); - cm.execCommand("goCharLeft"); - is(!cm.somethingSelected()); - eqPos(cm.getCursor(), Pos(0, 1)); -}, {value: "aaaaa\nb\nccccc"}); - -testCM("clickTab", function(cm) { - var p0 = cm.charCoords(Pos(0, 0)); - eqPos(cm.coordsChar({left: p0.left + 5, top: p0.top + 5}), Pos(0, 0)); - eqPos(cm.coordsChar({left: p0.right - 5, top: p0.top + 5}), Pos(0, 1)); -}, {value: "\t\n\n", lineWrapping: true, tabSize: 8}); - -testCM("verticalScroll", function(cm) { - cm.setSize(100, 200); - cm.setValue("foo\nbar\nbaz\n"); - var sc = cm.getScrollerElement(), baseWidth = sc.scrollWidth; - cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0)); - is(sc.scrollWidth > baseWidth, "scrollbar present"); - cm.replaceRange("foo", Pos(0, 0), Pos(0)); - if (!phantom) eq(sc.scrollWidth, baseWidth, "scrollbar gone"); - cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0)); - cm.replaceRange("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbh", Pos(1, 0), Pos(1)); - is(sc.scrollWidth > baseWidth, "present again"); - var curWidth = sc.scrollWidth; - cm.replaceRange("foo", Pos(0, 0), Pos(0)); - is(sc.scrollWidth < curWidth, "scrollbar smaller"); - is(sc.scrollWidth > baseWidth, "but still present"); -}); - -testCM("extraKeys", function(cm) { - var outcome; - function fakeKey(expected, code, props) { - if (typeof code == "string") code = code.charCodeAt(0); - var e = {type: "keydown", keyCode: code, preventDefault: function(){}, stopPropagation: function(){}}; - if (props) for (var n in props) e[n] = props[n]; - outcome = null; - cm.triggerOnKeyDown(e); - eq(outcome, expected); - } - CodeMirror.commands.testCommand = function() {outcome = "tc";}; - CodeMirror.commands.goTestCommand = function() {outcome = "gtc";}; - cm.setOption("extraKeys", {"Shift-X": function() {outcome = "sx";}, - "X": function() {outcome = "x";}, - "Ctrl-Alt-U": function() {outcome = "cau";}, - "End": "testCommand", - "Home": "goTestCommand", - "Tab": false}); - fakeKey(null, "U"); - fakeKey("cau", "U", {ctrlKey: true, altKey: true}); - fakeKey(null, "U", {shiftKey: true, ctrlKey: true, altKey: true}); - fakeKey("x", "X"); - fakeKey("sx", "X", {shiftKey: true}); - fakeKey("tc", 35); - fakeKey(null, 35, {shiftKey: true}); - fakeKey("gtc", 36); - fakeKey("gtc", 36, {shiftKey: true}); - fakeKey(null, 9); -}, null, window.opera && mac); - -testCM("wordMovementCommands", function(cm) { - cm.execCommand("goWordLeft"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(0, 7)); - cm.execCommand("goWordLeft"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(0, 12)); - cm.execCommand("goWordLeft"); - eqPos(cm.getCursor(), Pos(0, 9)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(0, 24)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(1, 9)); - cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(1, 13)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(2, 0)); -}, {value: "this is (the) firstline.\na foo12\u00e9\u00f8\u00d7bar\n"}); - -testCM("groupMovementCommands", function(cm) { - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 7)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 10)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 7)); - cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 15)); - cm.setCursor(Pos(0, 17)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 16)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 14)); - cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 20)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(1, 2)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(1, 5)); - cm.execCommand("goGroupLeft"); cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 20)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 16)); -}, {value: "booo ba---quux. ffff\n abc d"}); - -testCM("groupsAndWhitespace", function(cm) { - var positions = [Pos(0, 0), Pos(0, 2), Pos(0, 5), Pos(0, 9), Pos(0, 11), - Pos(1, 0), Pos(1, 2), Pos(1, 5)]; - for (var i = 1; i < positions.length; i++) { - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), positions[i]); - } - for (var i = positions.length - 2; i >= 0; i--) { - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), i == 2 ? Pos(0, 6) : positions[i]); - } -}, {value: " foo +++ \n bar"}); - -testCM("charMovementCommands", function(cm) { - cm.execCommand("goCharLeft"); cm.execCommand("goColumnLeft"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goCharRight"); cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.setCursor(Pos(1, 0)); - cm.execCommand("goColumnLeft"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goColumnRight"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goLineEnd"); - eqPos(cm.getCursor(), Pos(1, 5)); - cm.execCommand("goLineStartSmart"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineStartSmart"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.setCursor(Pos(2, 0)); - cm.execCommand("goCharRight"); cm.execCommand("goColumnRight"); - eqPos(cm.getCursor(), Pos(2, 0)); -}, {value: "line1\n ine2\n"}); - -testCM("verticalMovementCommands", function(cm) { - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goLineDown"); - if (!phantom) // This fails in PhantomJS, though not in a real Webkit - eqPos(cm.getCursor(), Pos(1, 0)); - cm.setCursor(Pos(1, 12)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(2, 5)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(3, 0)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(2, 5)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 12)); - cm.execCommand("goPageDown"); - eqPos(cm.getCursor(), Pos(5, 0)); - cm.execCommand("goPageDown"); cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(5, 0)); - cm.execCommand("goPageUp"); - eqPos(cm.getCursor(), Pos(0, 0)); -}, {value: "line1\nlong long line2\nline3\n\nline5\n"}); - -testCM("verticalMovementCommandsWrapping", function(cm) { - cm.setSize(120); - cm.setCursor(Pos(0, 5)); - cm.execCommand("goLineDown"); - eq(cm.getCursor().line, 0); - is(cm.getCursor().ch > 5, "moved beyond wrap"); - for (var i = 0; ; ++i) { - is(i < 20, "no endless loop"); - cm.execCommand("goLineDown"); - var cur = cm.getCursor(); - if (cur.line == 1) eq(cur.ch, 5); - if (cur.line == 2) { eq(cur.ch, 1); break; } - } -}, {value: "a very long line that wraps around somehow so that we can test cursor movement\nshortone\nk", - lineWrapping: true}); - -testCM("rtlMovement", function(cm) { - if (cm.getOption("inputStyle") != "textarea") return; - forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج", - "خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر", "خ ة ق", - ""], function(line) { - var inv = line.charAt(0) == "خ"; - cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart"); - var cursors = byClassName(cm.getWrapperElement(), "CodeMirror-cursors")[0]; - var cursor = cursors.firstChild; - var prevX = cursor.offsetLeft, prevY = cursor.offsetTop; - for (var i = 0; i <= line.length; ++i) { - cm.execCommand("goCharRight"); - cursor = cursors.firstChild; - if (i == line.length) is(cursor.offsetTop > prevY, "next line"); - else is(cursor.offsetLeft > prevX, "moved right"); - prevX = cursor.offsetLeft; prevY = cursor.offsetTop; - } - cm.setCursor(0, 0); cm.execCommand(inv ? "goLineStart" : "goLineEnd"); - prevX = cursors.firstChild.offsetLeft; - for (var i = 0; i < line.length; ++i) { - cm.execCommand("goCharLeft"); - cursor = cursors.firstChild; - is(cursor.offsetLeft < prevX, "moved left"); - prevX = cursor.offsetLeft; - } - }); -}, null, ie_lt9); - -// Verify that updating a line clears its bidi ordering -testCM("bidiUpdate", function(cm) { - cm.setCursor(Pos(0, 2)); - cm.replaceSelection("خحج", "start"); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 4)); -}, {value: "abcd\n"}); - -testCM("movebyTextUnit", function(cm) { - cm.setValue("בְּרֵאשִ\nééé́\n"); - cm.execCommand("goLineEnd"); - for (var i = 0; i < 4; ++i) cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goCharRight"); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 4)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 7)); -}); - -testCM("lineChangeEvents", function(cm) { - addDoc(cm, 3, 5); - var log = [], want = ["ch 0", "ch 1", "del 2", "ch 0", "ch 0", "del 1", "del 3", "del 4"]; - for (var i = 0; i < 5; ++i) { - CodeMirror.on(cm.getLineHandle(i), "delete", function(i) { - return function() {log.push("del " + i);}; - }(i)); - CodeMirror.on(cm.getLineHandle(i), "change", function(i) { - return function() {log.push("ch " + i);}; - }(i)); - } - cm.replaceRange("x", Pos(0, 1)); - cm.replaceRange("xy", Pos(1, 1), Pos(2)); - cm.replaceRange("foo\nbar", Pos(0, 1)); - cm.replaceRange("", Pos(0, 0), Pos(cm.lineCount())); - eq(log.length, want.length, "same length"); - for (var i = 0; i < log.length; ++i) - eq(log[i], want[i]); -}); - -testCM("scrollEntirelyToRight", function(cm) { - if (phantom || cm.getOption("inputStyle") != "textarea") return; - addDoc(cm, 500, 2); - cm.setCursor(Pos(0, 500)); - var wrap = cm.getWrapperElement(), cur = byClassName(wrap, "CodeMirror-cursor")[0]; - is(wrap.getBoundingClientRect().right > cur.getBoundingClientRect().left); -}); - -testCM("lineWidgets", function(cm) { - addDoc(cm, 500, 3); - var last = cm.charCoords(Pos(2, 0)); - var node = document.createElement("div"); - node.innerHTML = "hi"; - var widget = cm.addLineWidget(1, node); - is(last.top < cm.charCoords(Pos(2, 0)).top, "took up space"); - cm.setCursor(Pos(1, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(2, 1)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 1)); -}); - -testCM("lineWidgetFocus", function(cm) { - var place = document.getElementById("testground"); - place.className = "offscreen"; - try { - addDoc(cm, 500, 10); - var node = document.createElement("input"); - var widget = cm.addLineWidget(1, node); - node.focus(); - eq(document.activeElement, node); - cm.replaceRange("new stuff", Pos(1, 0)); - eq(document.activeElement, node); - } finally { - place.className = ""; - } -}); - -testCM("lineWidgetCautiousRedraw", function(cm) { - var node = document.createElement("div"); - node.innerHTML = "hahah"; - var w = cm.addLineWidget(0, node); - var redrawn = false; - w.on("redraw", function() { redrawn = true; }); - cm.replaceSelection("0"); - is(!redrawn); -}, {value: "123\n456"}); - - -var knownScrollbarWidth; -function scrollbarWidth(measure) { - if (knownScrollbarWidth != null) return knownScrollbarWidth; - var div = document.createElement('div'); - div.style.cssText = "width: 50px; height: 50px; overflow-x: scroll"; - document.body.appendChild(div); - knownScrollbarWidth = div.offsetHeight - div.clientHeight; - document.body.removeChild(div); - return knownScrollbarWidth || 0; -} - -testCM("lineWidgetChanged", function(cm) { - addDoc(cm, 2, 300); - var halfScrollbarWidth = scrollbarWidth(cm.display.measure)/2; - cm.setOption('lineNumbers', true); - cm.setSize(600, cm.defaultTextHeight() * 50); - cm.scrollTo(null, cm.heightAtLine(125, "local")); - - var expectedWidgetHeight = 60; - var expectedLinesInWidget = 3; - function w() { - var node = document.createElement("div"); - // we use these children with just under half width of the line to check measurements are made with correct width - // when placed in the measure div. - // If the widget is measured at a width much narrower than it is displayed at, the underHalf children will span two lines and break the test. - // If the widget is measured at a width much wider than it is displayed at, the overHalf children will combine and break the test. - // Note that this test only checks widgets where coverGutter is true, because these require extra styling to get the width right. - // It may also be worthwhile to check this for non-coverGutter widgets. - // Visually: - // Good: - // | ------------- display width ------------- | - // | ------- widget-width when measured ------ | - // | | -- under-half -- | | -- under-half -- | | - // | | --- over-half --- | | - // | | --- over-half --- | | - // Height: measured as 3 lines, same as it will be when actually displayed - - // Bad (too narrow): - // | ------------- display width ------------- | - // | ------ widget-width when measured ----- | < -- uh oh - // | | -- under-half -- | | - // | | -- under-half -- | | < -- when measured, shoved to next line - // | | --- over-half --- | | - // | | --- over-half --- | | - // Height: measured as 4 lines, more than expected . Will be displayed as 3 lines! - - // Bad (too wide): - // | ------------- display width ------------- | - // | -------- widget-width when measured ------- | < -- uh oh - // | | -- under-half -- | | -- under-half -- | | - // | | --- over-half --- | | --- over-half --- | | < -- when measured, combined on one line - // Height: measured as 2 lines, less than expected. Will be displayed as 3 lines! - - var barelyUnderHalfWidthHtml = '
    '; - var barelyOverHalfWidthHtml = '
    '; - node.innerHTML = new Array(3).join(barelyUnderHalfWidthHtml) + new Array(3).join(barelyOverHalfWidthHtml); - node.style.cssText = "background: yellow;font-size:0;line-height: " + (expectedWidgetHeight/expectedLinesInWidget) + "px;"; - return node; - } - var info0 = cm.getScrollInfo(); - var w0 = cm.addLineWidget(0, w(), { coverGutter: true }); - var w150 = cm.addLineWidget(150, w(), { coverGutter: true }); - var w300 = cm.addLineWidget(300, w(), { coverGutter: true }); - var info1 = cm.getScrollInfo(); - eq(info0.height + (3 * expectedWidgetHeight), info1.height); - eq(info0.top + expectedWidgetHeight, info1.top); - expectedWidgetHeight = 12; - w0.node.style.lineHeight = w150.node.style.lineHeight = w300.node.style.lineHeight = (expectedWidgetHeight/expectedLinesInWidget) + "px"; - w0.changed(); w150.changed(); w300.changed(); - var info2 = cm.getScrollInfo(); - eq(info0.height + (3 * expectedWidgetHeight), info2.height); - eq(info0.top + expectedWidgetHeight, info2.top); -}); - -testCM("getLineNumber", function(cm) { - addDoc(cm, 2, 20); - var h1 = cm.getLineHandle(1); - eq(cm.getLineNumber(h1), 1); - cm.replaceRange("hi\nbye\n", Pos(0, 0)); - eq(cm.getLineNumber(h1), 3); - cm.setValue(""); - eq(cm.getLineNumber(h1), null); -}); - -testCM("jumpTheGap", function(cm) { - if (phantom) return; - var longLine = "abcdef ghiklmnop qrstuvw xyz "; - longLine += longLine; longLine += longLine; longLine += longLine; - cm.replaceRange(longLine, Pos(2, 0), Pos(2)); - cm.setSize("200px", null); - cm.getWrapperElement().style.lineHeight = 2; - cm.refresh(); - cm.setCursor(Pos(0, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(2, 1)); - cm.execCommand("goLineDown"); - eq(cm.getCursor().line, 2); - is(cm.getCursor().ch > 1); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(2, 1)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 1)); - var node = document.createElement("div"); - node.innerHTML = "hi"; node.style.height = "30px"; - cm.addLineWidget(0, node); - cm.addLineWidget(1, node.cloneNode(true), {above: true}); - cm.setCursor(Pos(0, 2)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(1, 2)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 2)); -}, {lineWrapping: true, value: "abc\ndef\nghi\njkl\n"}); - -testCM("addLineClass", function(cm) { - function cls(line, text, bg, wrap, gutter) { - var i = cm.lineInfo(line); - eq(i.textClass, text); - eq(i.bgClass, bg); - eq(i.wrapClass, wrap); - if (typeof i.handle.gutterClass !== 'undefined') { - eq(i.handle.gutterClass, gutter); - } - } - cm.addLineClass(0, "text", "foo"); - cm.addLineClass(0, "text", "bar"); - cm.addLineClass(1, "background", "baz"); - cm.addLineClass(1, "wrap", "foo"); - cm.addLineClass(1, "gutter", "gutter-class"); - cls(0, "foo bar", null, null, null); - cls(1, null, "baz", "foo", "gutter-class"); - var lines = cm.display.lineDiv; - eq(byClassName(lines, "foo").length, 2); - eq(byClassName(lines, "bar").length, 1); - eq(byClassName(lines, "baz").length, 1); - eq(byClassName(lines, "gutter-class").length, 1); - cm.removeLineClass(0, "text", "foo"); - cls(0, "bar", null, null, null); - cm.removeLineClass(0, "text", "foo"); - cls(0, "bar", null, null, null); - cm.removeLineClass(0, "text", "bar"); - cls(0, null, null, null); - - cm.addLineClass(1, "wrap", "quux"); - cls(1, null, "baz", "foo quux", "gutter-class"); - cm.removeLineClass(1, "wrap"); - cls(1, null, "baz", null, "gutter-class"); - cm.removeLineClass(1, "gutter", "gutter-class"); - eq(byClassName(lines, "gutter-class").length, 0); - cls(1, null, "baz", null, null); - - cm.addLineClass(1, "gutter", "gutter-class"); - cls(1, null, "baz", null, "gutter-class"); - cm.removeLineClass(1, "gutter", "gutter-class"); - cls(1, null, "baz", null, null); - -}, {value: "hohoho\n", lineNumbers: true}); - -testCM("atomicMarker", function(cm) { - addDoc(cm, 10, 10); - function atom(ll, cl, lr, cr, li, ri) { - return cm.markText(Pos(ll, cl), Pos(lr, cr), - {atomic: true, inclusiveLeft: li, inclusiveRight: ri}); - } - var m = atom(0, 1, 0, 5); - cm.setCursor(Pos(0, 1)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 1)); - m.clear(); - m = atom(0, 0, 0, 5, true); - eqPos(cm.getCursor(), Pos(0, 5), "pushed out"); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 5)); - m.clear(); - m = atom(8, 4, 9, 10, false, true); - cm.setCursor(Pos(9, 8)); - eqPos(cm.getCursor(), Pos(8, 4), "set"); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(8, 4), "char right"); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(8, 4), "line down"); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(8, 3)); - m.clear(); - m = atom(1, 1, 3, 8); - cm.setCursor(Pos(0, 0)); - cm.setCursor(Pos(2, 0)); - eqPos(cm.getCursor(), Pos(3, 8)); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(3, 8)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(3, 8)); - cm.execCommand("delCharBefore"); - eq(cm.getValue().length, 80, "del chunk"); - m = atom(3, 0, 5, 5); - cm.setCursor(Pos(3, 0)); - cm.execCommand("delWordAfter"); - eq(cm.getValue().length, 53, "del chunk"); -}); - -testCM("selectionBias", function(cm) { - cm.markText(Pos(0, 1), Pos(0, 3), {atomic: true}); - cm.setCursor(Pos(0, 2)); - eqPos(cm.getCursor(), Pos(0, 3)); - cm.setCursor(Pos(0, 2)); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.setCursor(Pos(0, 2), null, {bias: -1}); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.setCursor(Pos(0, 4)); - cm.setCursor(Pos(0, 2), null, {bias: 1}); - eqPos(cm.getCursor(), Pos(0, 3)); -}, {value: "12345"}); - -testCM("selectionHomeEnd", function(cm) { - cm.markText(Pos(1, 0), Pos(1, 1), {atomic: true, inclusiveLeft: true}); - cm.markText(Pos(1, 3), Pos(1, 4), {atomic: true, inclusiveRight: true}); - cm.setCursor(Pos(1, 2)); - cm.execCommand("goLineStart"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineEnd"); - eqPos(cm.getCursor(), Pos(1, 3)); -}, {value: "ab\ncdef\ngh"}); - -testCM("readOnlyMarker", function(cm) { - function mark(ll, cl, lr, cr, at) { - return cm.markText(Pos(ll, cl), Pos(lr, cr), - {readOnly: true, atomic: at}); - } - var m = mark(0, 1, 0, 4); - cm.setCursor(Pos(0, 2)); - cm.replaceSelection("hi", "end"); - eqPos(cm.getCursor(), Pos(0, 2)); - eq(cm.getLine(0), "abcde"); - cm.execCommand("selectAll"); - cm.replaceSelection("oops", "around"); - eq(cm.getValue(), "oopsbcd"); - cm.undo(); - eqPos(m.find().from, Pos(0, 1)); - eqPos(m.find().to, Pos(0, 4)); - m.clear(); - cm.setCursor(Pos(0, 2)); - cm.replaceSelection("hi", "around"); - eq(cm.getLine(0), "abhicde"); - eqPos(cm.getCursor(), Pos(0, 4)); - m = mark(0, 2, 2, 2, true); - cm.setSelection(Pos(1, 1), Pos(2, 4)); - cm.replaceSelection("t", "end"); - eqPos(cm.getCursor(), Pos(2, 3)); - eq(cm.getLine(2), "klto"); - cm.execCommand("goCharLeft"); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.setSelection(Pos(0, 1), Pos(0, 3)); - cm.replaceSelection("xx", "around"); - eqPos(cm.getCursor(), Pos(0, 3)); - eq(cm.getLine(0), "axxhicde"); -}, {value: "abcde\nfghij\nklmno\n"}); - -testCM("dirtyBit", function(cm) { - eq(cm.isClean(), true); - cm.replaceSelection("boo", null, "test"); - eq(cm.isClean(), false); - cm.undo(); - eq(cm.isClean(), true); - cm.replaceSelection("boo", null, "test"); - cm.replaceSelection("baz", null, "test"); - cm.undo(); - eq(cm.isClean(), false); - cm.markClean(); - eq(cm.isClean(), true); - cm.undo(); - eq(cm.isClean(), false); - cm.redo(); - eq(cm.isClean(), true); -}); - -testCM("changeGeneration", function(cm) { - cm.replaceSelection("x"); - var softGen = cm.changeGeneration(); - cm.replaceSelection("x"); - cm.undo(); - eq(cm.getValue(), ""); - is(!cm.isClean(softGen)); - cm.replaceSelection("x"); - var hardGen = cm.changeGeneration(true); - cm.replaceSelection("x"); - cm.undo(); - eq(cm.getValue(), "x"); - is(cm.isClean(hardGen)); -}); - -testCM("addKeyMap", function(cm) { - function sendKey(code) { - cm.triggerOnKeyDown({type: "keydown", keyCode: code, - preventDefault: function(){}, stopPropagation: function(){}}); - } - - sendKey(39); - eqPos(cm.getCursor(), Pos(0, 1)); - var test = 0; - var map1 = {Right: function() { ++test; }}, map2 = {Right: function() { test += 10; }} - cm.addKeyMap(map1); - sendKey(39); - eqPos(cm.getCursor(), Pos(0, 1)); - eq(test, 1); - cm.addKeyMap(map2, true); - sendKey(39); - eq(test, 2); - cm.removeKeyMap(map1); - sendKey(39); - eq(test, 12); - cm.removeKeyMap(map2); - sendKey(39); - eq(test, 12); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.addKeyMap({Right: function() { test = 55; }, name: "mymap"}); - sendKey(39); - eq(test, 55); - cm.removeKeyMap("mymap"); - sendKey(39); - eqPos(cm.getCursor(), Pos(0, 3)); -}, {value: "abc"}); - -testCM("findPosH", function(cm) { - forEach([{from: Pos(0, 0), to: Pos(0, 1), by: 1}, - {from: Pos(0, 0), to: Pos(0, 0), by: -1, hitSide: true}, - {from: Pos(0, 0), to: Pos(0, 4), by: 1, unit: "word"}, - {from: Pos(0, 0), to: Pos(0, 8), by: 2, unit: "word"}, - {from: Pos(0, 0), to: Pos(2, 0), by: 20, unit: "word", hitSide: true}, - {from: Pos(0, 7), to: Pos(0, 5), by: -1, unit: "word"}, - {from: Pos(0, 4), to: Pos(0, 8), by: 1, unit: "word"}, - {from: Pos(1, 0), to: Pos(1, 18), by: 3, unit: "word"}, - {from: Pos(1, 22), to: Pos(1, 5), by: -3, unit: "word"}, - {from: Pos(1, 15), to: Pos(1, 10), by: -5}, - {from: Pos(1, 15), to: Pos(1, 10), by: -5, unit: "column"}, - {from: Pos(1, 15), to: Pos(1, 0), by: -50, unit: "column", hitSide: true}, - {from: Pos(1, 15), to: Pos(1, 24), by: 50, unit: "column", hitSide: true}, - {from: Pos(1, 15), to: Pos(2, 0), by: 50, hitSide: true}], function(t) { - var r = cm.findPosH(t.from, t.by, t.unit || "char"); - eqPos(r, t.to); - eq(!!r.hitSide, !!t.hitSide); - }); -}, {value: "line one\nline two.something.other\n"}); - -testCM("beforeChange", function(cm) { - cm.on("beforeChange", function(cm, change) { - var text = []; - for (var i = 0; i < change.text.length; ++i) - text.push(change.text[i].replace(/\s/g, "_")); - change.update(null, null, text); - }); - cm.setValue("hello, i am a\nnew document\n"); - eq(cm.getValue(), "hello,_i_am_a\nnew_document\n"); - CodeMirror.on(cm.getDoc(), "beforeChange", function(doc, change) { - if (change.from.line == 0) change.cancel(); - }); - cm.setValue("oops"); // Canceled - eq(cm.getValue(), "hello,_i_am_a\nnew_document\n"); - cm.replaceRange("hey hey hey", Pos(1, 0), Pos(2, 0)); - eq(cm.getValue(), "hello,_i_am_a\nhey_hey_hey"); -}, {value: "abcdefghijk"}); - -testCM("beforeChangeUndo", function(cm) { - cm.replaceRange("hi", Pos(0, 0), Pos(0)); - cm.replaceRange("bye", Pos(0, 0), Pos(0)); - eq(cm.historySize().undo, 2); - cm.on("beforeChange", function(cm, change) { - is(!change.update); - change.cancel(); - }); - cm.undo(); - eq(cm.historySize().undo, 0); - eq(cm.getValue(), "bye\ntwo"); -}, {value: "one\ntwo"}); - -testCM("beforeSelectionChange", function(cm) { - function notAtEnd(cm, pos) { - var len = cm.getLine(pos.line).length; - if (!len || pos.ch == len) return Pos(pos.line, pos.ch - 1); - return pos; - } - cm.on("beforeSelectionChange", function(cm, obj) { - obj.update([{anchor: notAtEnd(cm, obj.ranges[0].anchor), - head: notAtEnd(cm, obj.ranges[0].head)}]); - }); - - addDoc(cm, 10, 10); - cm.execCommand("goLineEnd"); - eqPos(cm.getCursor(), Pos(0, 9)); - cm.execCommand("selectAll"); - eqPos(cm.getCursor("start"), Pos(0, 0)); - eqPos(cm.getCursor("end"), Pos(9, 9)); -}); - -testCM("change_removedText", function(cm) { - cm.setValue("abc\ndef"); - - var removedText = []; - cm.on("change", function(cm, change) { - removedText.push(change.removed); - }); - - cm.operation(function() { - cm.replaceRange("xyz", Pos(0, 0), Pos(1,1)); - cm.replaceRange("123", Pos(0,0)); - }); - - eq(removedText.length, 2); - eq(removedText[0].join("\n"), "abc\nd"); - eq(removedText[1].join("\n"), ""); - - var removedText = []; - cm.undo(); - eq(removedText.length, 2); - eq(removedText[0].join("\n"), "123"); - eq(removedText[1].join("\n"), "xyz"); - - var removedText = []; - cm.redo(); - eq(removedText.length, 2); - eq(removedText[0].join("\n"), "abc\nd"); - eq(removedText[1].join("\n"), ""); -}); - -testCM("lineStyleFromMode", function(cm) { - CodeMirror.defineMode("test_mode", function() { - return {token: function(stream) { - if (stream.match(/^\[[^\]]*\]/)) return " line-brackets "; - if (stream.match(/^\([^\)]*\)/)) return " line-background-parens "; - if (stream.match(/^<[^>]*>/)) return " span line-line line-background-bg "; - stream.match(/^\s+|^\S+/); - }}; - }); - cm.setOption("mode", "test_mode"); - var bracketElts = byClassName(cm.getWrapperElement(), "brackets"); - eq(bracketElts.length, 1, "brackets count"); - eq(bracketElts[0].nodeName, "PRE"); - is(!/brackets.*brackets/.test(bracketElts[0].className)); - var parenElts = byClassName(cm.getWrapperElement(), "parens"); - eq(parenElts.length, 1, "parens count"); - eq(parenElts[0].nodeName, "DIV"); - is(!/parens.*parens/.test(parenElts[0].className)); - eq(parenElts[0].parentElement.nodeName, "DIV"); - - eq(byClassName(cm.getWrapperElement(), "bg").length, 1); - eq(byClassName(cm.getWrapperElement(), "line").length, 1); - var spanElts = byClassName(cm.getWrapperElement(), "cm-span"); - eq(spanElts.length, 2); - is(/^\s*cm-span\s*$/.test(spanElts[0].className)); -}, {value: "line1: [br] [br]\nline2: (par) (par)\nline3: "}); - -testCM("lineStyleFromBlankLine", function(cm) { - CodeMirror.defineMode("lineStyleFromBlankLine_mode", function() { - return {token: function(stream) { stream.skipToEnd(); return "comment"; }, - blankLine: function() { return "line-blank"; }}; - }); - cm.setOption("mode", "lineStyleFromBlankLine_mode"); - var blankElts = byClassName(cm.getWrapperElement(), "blank"); - eq(blankElts.length, 1); - eq(blankElts[0].nodeName, "PRE"); - cm.replaceRange("x", Pos(1, 0)); - blankElts = byClassName(cm.getWrapperElement(), "blank"); - eq(blankElts.length, 0); -}, {value: "foo\n\nbar"}); - -CodeMirror.registerHelper("xxx", "a", "A"); -CodeMirror.registerHelper("xxx", "b", "B"); -CodeMirror.defineMode("yyy", function() { - return { - token: function(stream) { stream.skipToEnd(); }, - xxx: ["a", "b", "q"] - }; -}); -CodeMirror.registerGlobalHelper("xxx", "c", function(m) { return m.enableC; }, "C"); - -testCM("helpers", function(cm) { - cm.setOption("mode", "yyy"); - eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "A/B"); - cm.setOption("mode", {name: "yyy", modeProps: {xxx: "b", enableC: true}}); - eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "B/C"); - cm.setOption("mode", "javascript"); - eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), ""); -}); - -testCM("selectionHistory", function(cm) { - for (var i = 0; i < 3; i++) { - cm.setExtending(true); - cm.execCommand("goCharRight"); - cm.setExtending(false); - cm.execCommand("goCharRight"); - cm.execCommand("goCharRight"); - } - cm.execCommand("undoSelection"); - eq(cm.getSelection(), "c"); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), "b"); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), "c"); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(), Pos(0, 6)); -}, {value: "a b c d"}); - -testCM("selectionChangeReducesRedo", function(cm) { - cm.replaceSelection("X"); - cm.execCommand("goCharRight"); - cm.undoSelection(); - cm.execCommand("selectAll"); - cm.undoSelection(); - eq(cm.getValue(), "Xabc"); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.undoSelection(); - eq(cm.getValue(), "abc"); -}, {value: "abc"}); - -testCM("selectionHistoryNonOverlapping", function(cm) { - cm.setSelection(Pos(0, 0), Pos(0, 1)); - cm.setSelection(Pos(0, 2), Pos(0, 3)); - cm.execCommand("undoSelection"); - eqPos(cm.getCursor("anchor"), Pos(0, 0)); - eqPos(cm.getCursor("head"), Pos(0, 1)); -}, {value: "1234"}); - -testCM("cursorMotionSplitsHistory", function(cm) { - cm.replaceSelection("a"); - cm.execCommand("goCharRight"); - cm.replaceSelection("b"); - cm.replaceSelection("c"); - cm.undo(); - eq(cm.getValue(), "a1234"); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.undo(); - eq(cm.getValue(), "1234"); - eqPos(cm.getCursor(), Pos(0, 0)); -}, {value: "1234"}); - -testCM("selChangeInOperationDoesNotSplit", function(cm) { - for (var i = 0; i < 4; i++) { - cm.operation(function() { - cm.replaceSelection("x"); - cm.setCursor(Pos(0, cm.getCursor().ch - 1)); - }); - } - eqPos(cm.getCursor(), Pos(0, 0)); - eq(cm.getValue(), "xxxxa"); - cm.undo(); - eq(cm.getValue(), "a"); -}, {value: "a"}); - -testCM("alwaysMergeSelEventWithChangeOrigin", function(cm) { - cm.replaceSelection("U", null, "foo"); - cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "foo"}); - cm.undoSelection(); - eq(cm.getValue(), "a"); - cm.replaceSelection("V", null, "foo"); - cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "bar"}); - cm.undoSelection(); - eq(cm.getValue(), "Va"); -}, {value: "a"}); - -testCM("getTokenAt", function(cm) { - var tokPlus = cm.getTokenAt(Pos(0, 2)); - eq(tokPlus.type, "operator"); - eq(tokPlus.string, "+"); - var toks = cm.getLineTokens(0); - eq(toks.length, 3); - forEach([["number", "1"], ["operator", "+"], ["number", "2"]], function(expect, i) { - eq(toks[i].type, expect[0]); - eq(toks[i].string, expect[1]); - }); -}, {value: "1+2", mode: "javascript"}); - -testCM("getTokenTypeAt", function(cm) { - eq(cm.getTokenTypeAt(Pos(0, 0)), "number"); - eq(cm.getTokenTypeAt(Pos(0, 6)), "string"); - cm.addOverlay({ - token: function(stream) { - if (stream.match("foo")) return "foo"; - else stream.next(); - } - }); - eq(byClassName(cm.getWrapperElement(), "cm-foo").length, 1); - eq(cm.getTokenTypeAt(Pos(0, 6)), "string"); -}, {value: "1 + 'foo'", mode: "javascript"}); - -testCM("resizeLineWidget", function(cm) { - addDoc(cm, 200, 3); - var widget = document.createElement("pre"); - widget.innerHTML = "imwidget"; - widget.style.background = "yellow"; - cm.addLineWidget(1, widget, {noHScroll: true}); - cm.setSize(40); - is(widget.parentNode.offsetWidth < 42); -}); - -testCM("combinedOperations", function(cm) { - var place = document.getElementById("testground"); - var other = CodeMirror(place, {value: "123"}); - try { - cm.operation(function() { - cm.addLineClass(0, "wrap", "foo"); - other.addLineClass(0, "wrap", "foo"); - }); - eq(byClassName(cm.getWrapperElement(), "foo").length, 1); - eq(byClassName(other.getWrapperElement(), "foo").length, 1); - cm.operation(function() { - cm.removeLineClass(0, "wrap", "foo"); - other.removeLineClass(0, "wrap", "foo"); - }); - eq(byClassName(cm.getWrapperElement(), "foo").length, 0); - eq(byClassName(other.getWrapperElement(), "foo").length, 0); - } finally { - place.removeChild(other.getWrapperElement()); - } -}, {value: "abc"}); - -testCM("eventOrder", function(cm) { - var seen = []; - cm.on("change", function() { - if (!seen.length) cm.replaceSelection("."); - seen.push("change"); - }); - cm.on("cursorActivity", function() { - cm.replaceSelection("!"); - seen.push("activity"); - }); - cm.replaceSelection("/"); - eq(seen.join(","), "change,change,activity,change"); -}); - -test("core_rmClass", function() { - var node = document.createElement("div"); - node.className = "foo-bar baz-quux yadda"; - CodeMirror.rmClass(node, "quux"); - eq(node.className, "foo-bar baz-quux yadda"); - CodeMirror.rmClass(node, "baz-quux"); - eq(node.className, "foo-bar yadda"); - CodeMirror.rmClass(node, "yadda"); - eq(node.className, "foo-bar"); - CodeMirror.rmClass(node, "foo-bar"); - eq(node.className, ""); - node.className = " foo "; - CodeMirror.rmClass(node, "foo"); - eq(node.className, ""); -}); - -test("core_addClass", function() { - var node = document.createElement("div"); - CodeMirror.addClass(node, "a"); - eq(node.className, "a"); - CodeMirror.addClass(node, "a"); - eq(node.className, "a"); - CodeMirror.addClass(node, "b"); - eq(node.className, "a b"); - CodeMirror.addClass(node, "a"); - CodeMirror.addClass(node, "b"); - eq(node.className, "a b"); -}); diff --git a/shared/html/libs/codemirror/5.0.0/test/vim_test.js b/shared/html/libs/codemirror/5.0.0/test/vim_test.js deleted file mode 100644 index 74013cb..0000000 --- a/shared/html/libs/codemirror/5.0.0/test/vim_test.js +++ /dev/null @@ -1,3773 +0,0 @@ -CodeMirror.Vim.suppressErrorLogging = true; - -var code = '' + -' wOrd1 (#%\n' + -' word3] \n' + -'aopop pop 0 1 2 3 4\n' + -' (a) [b] {c} \n' + -'int getchar(void) {\n' + -' static char buf[BUFSIZ];\n' + -' static char *bufp = buf;\n' + -' if (n == 0) { /* buffer is empty */\n' + -' n = read(0, buf, sizeof buf);\n' + -' bufp = buf;\n' + -' }\n' + -'\n' + -' return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' + -' \n' + -'}\n'; - -var lines = (function() { - lineText = code.split('\n'); - var ret = []; - for (var i = 0; i < lineText.length; i++) { - ret[i] = { - line: i, - length: lineText[i].length, - lineText: lineText[i], - textStart: /^\s*/.exec(lineText[i])[0].length - }; - } - return ret; -})(); -var endOfDocument = makeCursor(lines.length - 1, - lines[lines.length - 1].length); -var wordLine = lines[0]; -var bigWordLine = lines[1]; -var charLine = lines[2]; -var bracesLine = lines[3]; -var seekBraceLine = lines[4]; - -var word1 = { - start: { line: wordLine.line, ch: 1 }, - end: { line: wordLine.line, ch: 5 } -}; -var word2 = { - start: { line: wordLine.line, ch: word1.end.ch + 2 }, - end: { line: wordLine.line, ch: word1.end.ch + 4 } -}; -var word3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 5 } -}; -var bigWord1 = word1; -var bigWord2 = word2; -var bigWord3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 7 } -}; -var bigWord4 = { - start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 }, - end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 } -}; - -var oChars = [ { line: charLine.line, ch: 1 }, - { line: charLine.line, ch: 3 }, - { line: charLine.line, ch: 7 } ]; -var pChars = [ { line: charLine.line, ch: 2 }, - { line: charLine.line, ch: 4 }, - { line: charLine.line, ch: 6 }, - { line: charLine.line, ch: 8 } ]; -var numChars = [ { line: charLine.line, ch: 10 }, - { line: charLine.line, ch: 12 }, - { line: charLine.line, ch: 14 }, - { line: charLine.line, ch: 16 }, - { line: charLine.line, ch: 18 }]; -var parens1 = { - start: { line: bracesLine.line, ch: 1 }, - end: { line: bracesLine.line, ch: 3 } -}; -var squares1 = { - start: { line: bracesLine.line, ch: 5 }, - end: { line: bracesLine.line, ch: 7 } -}; -var curlys1 = { - start: { line: bracesLine.line, ch: 9 }, - end: { line: bracesLine.line, ch: 11 } -}; -var seekOutside = { - start: { line: seekBraceLine.line, ch: 1 }, - end: { line: seekBraceLine.line, ch: 16 } -}; -var seekInside = { - start: { line: seekBraceLine.line, ch: 14 }, - end: { line: seekBraceLine.line, ch: 11 } -}; - -function copyCursor(cur) { - return { ch: cur.ch, line: cur.line }; -} - -function forEach(arr, func) { - for (var i = 0; i < arr.length; i++) { - func(arr[i], i, arr); - } -} - -function testVim(name, run, opts, expectedFail) { - var vimOpts = { - lineNumbers: true, - vimMode: true, - showCursorWhenSelecting: true, - value: code - }; - for (var prop in opts) { - if (opts.hasOwnProperty(prop)) { - vimOpts[prop] = opts[prop]; - } - } - return test('vim_' + name, function() { - var place = document.getElementById("testground"); - var cm = CodeMirror(place, vimOpts); - var vim = CodeMirror.Vim.maybeInitVimState_(cm); - - function doKeysFn(cm) { - return function(args) { - if (args instanceof Array) { - arguments = args; - } - for (var i = 0; i < arguments.length; i++) { - CodeMirror.Vim.handleKey(cm, arguments[i]); - } - } - } - function doInsertModeKeysFn(cm) { - return function(args) { - if (args instanceof Array) { arguments = args; } - function executeHandler(handler) { - if (typeof handler == 'string') { - CodeMirror.commands[handler](cm); - } else { - handler(cm); - } - return true; - } - for (var i = 0; i < arguments.length; i++) { - var key = arguments[i]; - // Find key in keymap and handle. - var handled = CodeMirror.lookupKey(key, 'vim-insert', executeHandler); - // Record for insert mode. - if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') { - var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges; - if (lastChange) { - lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key)); - } - } - } - } - } - function doExFn(cm) { - return function(command) { - cm.openDialog = helpers.fakeOpenDialog(command); - helpers.doKeys(':'); - } - } - function assertCursorAtFn(cm) { - return function(line, ch) { - var pos; - if (ch == null && typeof line.line == 'number') { - pos = line; - } else { - pos = makeCursor(line, ch); - } - eqPos(pos, cm.getCursor()); - } - } - function fakeOpenDialog(result) { - return function(text, callback) { - return callback(result); - } - } - function fakeOpenNotification(matcher) { - return function(text) { - matcher(text); - } - } - var helpers = { - doKeys: doKeysFn(cm), - // Warning: Only emulates keymap events, not character insertions. Use - // replaceRange to simulate character insertions. - // Keys are in CodeMirror format, NOT vim format. - doInsertModeKeys: doInsertModeKeysFn(cm), - doEx: doExFn(cm), - assertCursorAt: assertCursorAtFn(cm), - fakeOpenDialog: fakeOpenDialog, - fakeOpenNotification: fakeOpenNotification, - getRegisterController: function() { - return CodeMirror.Vim.getRegisterController(); - } - } - CodeMirror.Vim.resetVimGlobalState_(); - var successful = false; - var savedOpenNotification = cm.openNotification; - try { - run(cm, vim, helpers); - successful = true; - } finally { - cm.openNotification = savedOpenNotification; - if (!successful || verbose) { - place.style.visibility = "visible"; - } else { - place.removeChild(cm.getWrapperElement()); - } - } - }, expectedFail); -}; -testVim('qq@q', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'q', 'l', 'l', 'q'); - helpers.assertCursorAt(0,2); - helpers.doKeys('@', 'q'); - helpers.assertCursorAt(0,4); -}, { value: ' '}); -testVim('@@', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'q', 'l', 'l', 'q'); - helpers.assertCursorAt(0,2); - helpers.doKeys('@', 'q'); - helpers.assertCursorAt(0,4); - helpers.doKeys('@', '@'); - helpers.assertCursorAt(0,6); -}, { value: ' '}); -var jumplistScene = ''+ - 'word\n'+ - '(word)\n'+ - '{word\n'+ - 'word.\n'+ - '\n'+ - 'word search\n'+ - '}word\n'+ - 'word\n'+ - 'word\n'; -function testJumplist(name, keys, endPos, startPos, dialog) { - endPos = makeCursor(endPos[0], endPos[1]); - startPos = makeCursor(startPos[0], startPos[1]); - testVim(name, function(cm, vim, helpers) { - CodeMirror.Vim.resetVimGlobalState_(); - if(dialog)cm.openDialog = helpers.fakeOpenDialog('word'); - cm.setCursor(startPos); - helpers.doKeys.apply(null, keys); - helpers.assertCursorAt(endPos); - }, {value: jumplistScene}); -}; -testJumplist('jumplist_H', ['H', ''], [5,2], [5,2]); -testJumplist('jumplist_M', ['M', ''], [2,2], [2,2]); -testJumplist('jumplist_L', ['L', ''], [2,2], [2,2]); -testJumplist('jumplist_[[', ['[', '[', ''], [5,2], [5,2]); -testJumplist('jumplist_]]', [']', ']', ''], [2,2], [2,2]); -testJumplist('jumplist_G', ['G', ''], [5,2], [5,2]); -testJumplist('jumplist_gg', ['g', 'g', ''], [5,2], [5,2]); -testJumplist('jumplist_%', ['%', ''], [1,5], [1,5]); -testJumplist('jumplist_{', ['{', ''], [1,5], [1,5]); -testJumplist('jumplist_}', ['}', ''], [1,5], [1,5]); -testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', ''], [1,0], [1,5]); -testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', ''], [1,5], [1,5]); -testJumplist('jumplist_*_cachedCursor', ['*', ''], [1,3], [1,3]); -testJumplist('jumplist_#_cachedCursor', ['#', ''], [1,3], [1,3]); -testJumplist('jumplist_n', ['#', 'n', ''], [1,1], [2,3]); -testJumplist('jumplist_N', ['#', 'N', ''], [1,1], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', ''], [2,3], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', '', '2', ''], [5,0], [2,3]); -testJumplist('jumplist_repeated_motion', ['3', '*', ''], [2,3], [2,3]); -testJumplist('jumplist_/', ['/', ''], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_?', ['?', ''], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_skip_delted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], - [0,2], [0,2]); -testJumplist('jumplist_skip_delted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], - [1,0], [0,2]); - -/** - * @param name Name of the test - * @param keys An array of keys or a string with a single key to simulate. - * @param endPos The expected end position of the cursor. - * @param startPos The position the cursor should start at, defaults to 0, 0. - */ -function testMotion(name, keys, endPos, startPos) { - testVim(name, function(cm, vim, helpers) { - if (!startPos) { - startPos = { line: 0, ch: 0 }; - } - cm.setCursor(startPos); - helpers.doKeys(keys); - helpers.assertCursorAt(endPos); - }); -}; - -function makeCursor(line, ch) { - return { line: line, ch: ch }; -}; - -function offsetCursor(cur, offsetLine, offsetCh) { - return { line: cur.line + offsetLine, ch: cur.ch + offsetCh }; -}; - -// Motion tests -testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4)); -testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4)); -testMotion('h', 'h', makeCursor(0, 0), word1.start); -testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end); -testMotion('l', 'l', makeCursor(0, 1)); -testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2)); -testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end); -testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end); -testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument); -testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end); -testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4)); -testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4)); -testMotion('w', 'w', word1.start); -testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2)); -testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51)); -testMotion('w_repeat', ['2', 'w'], word2.start); -testMotion('w_wrap', ['w'], word3.start, word2.start); -testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument); -testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0)); -testMotion('W', 'W', bigWord1.start); -testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start); -testMotion('e', 'e', word1.end); -testMotion('e_repeat', ['2', 'e'], word2.end); -testMotion('e_wrap', 'e', word3.end, word2.end); -testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument); -testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0)); -testMotion('b', 'b', word3.start, word3.end); -testMotion('b_repeat', ['2', 'b'], word2.start, word3.end); -testMotion('b_wrap', 'b', word2.start, word3.start); -testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0)); -testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument); -testMotion('ge', ['g', 'e'], word2.end, word3.end); -testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start); -testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start); -testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0), - makeCursor(0, 0)); -testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument); -testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart), - makeCursor(3, 1)); -testMotion('gg_repeat', ['3', 'g', 'g'], - makeCursor(lines[2].line, lines[2].textStart)); -testMotion('G', 'G', - makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart), - makeCursor(3, 1)); -testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line, - lines[2].textStart)); -// TODO: Make the test code long enough to test Ctrl-F and Ctrl-B. -testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8)); -testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8)); -testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8)); -testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4)); -testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8)); -testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1)); -testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1), - makeCursor(0, 3)); -testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0)); -testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]); -testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0)); -testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1), - makeCursor(charLine.line, 0)); -testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1), - pChars[0]); -testMotion('F', ['F', 'p'], pChars[0], pChars[1]); -testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]); -testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]); -testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]); -testMotion('%_parens', ['%'], parens1.end, parens1.start); -testMotion('%_squares', ['%'], squares1.end, squares1.start); -testMotion('%_braces', ['%'], curlys1.end, curlys1.start); -testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start); -testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start); -testVim('%_seek_skip', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,9); -}, {value:'01234"("()'}); -testVim('%_skip_string', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,4); - cm.setCursor(0,2); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,0); -}, {value:'(")")'}); -(')') -testVim('%_skip_comment', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,6); - cm.setCursor(0,3); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,0); -}, {value:'(/*)*/)'}); -// Make sure that moving down after going to the end of a line always leaves you -// at the end of a line, but preserves the offset in other cases -testVim('Changing lines after Eol operation', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['$']); - helpers.doKeys(['j']); - // After moving to Eol and then down, we should be at Eol of line 2 - helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 }); - helpers.doKeys(['j']); - // After moving down, we should be at Eol of line 3 - helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 }); - helpers.doKeys(['h']); - helpers.doKeys(['j']); - // After moving back one space and then down, since line 4 is shorter than line 2, we should - // be at Eol of line 2 - 1 - helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 }); - helpers.doKeys(['j']); - helpers.doKeys(['j']); - // After moving down again, since line 3 has enough characters, we should be back to the - // same place we were at on line 1 - helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 }); -}); -//making sure gj and gk recover from clipping -testVim('gj_gk_clipping', function(cm,vim,helpers){ - cm.setCursor(0, 1); - helpers.doKeys('g','j','g','j'); - helpers.assertCursorAt(2, 1); - helpers.doKeys('g','k','g','k'); - helpers.assertCursorAt(0, 1); -},{value: 'line 1\n\nline 2'}); -//testing a mix of j/k and gj/gk -testVim('j_k_and_gj_gk', function(cm,vim,helpers){ - cm.setSize(120); - cm.setCursor(0, 0); - //go to the last character on the first line - helpers.doKeys('$'); - //move up/down on the column within the wrapped line - //side-effect: cursor is not locked to eol anymore - helpers.doKeys('g','k'); - var cur=cm.getCursor(); - eq(cur.line,0); - is((cur.ch<176),'gk didn\'t move cursor back (1)'); - helpers.doKeys('g','j'); - helpers.assertCursorAt(0, 176); - //should move to character 177 on line 2 (j/k preserve character index within line) - helpers.doKeys('j'); - //due to different line wrapping, the cursor can be on a different screen-x now - //gj and gk preserve screen-x on movement, much like moveV - helpers.doKeys('3','g','k'); - cur=cm.getCursor(); - eq(cur.line,1); - is((cur.ch<176),'gk didn\'t move cursor back (2)'); - helpers.doKeys('g','j','2','g','j'); - //should return to the same character-index - helpers.doKeys('k'); - helpers.assertCursorAt(0, 176); -},{ lineWrapping:true, value: 'This line is intentially long to test movement of gj and gk over wrapped lines. I will start on the end of this line, then make a step up and back to set the origin for j and k.\nThis line is supposed to be even longer than the previous. I will jump here and make another wiggle with gj and gk, before I jump back to the line above. Both wiggles should not change my cursor\'s target character but both j/k and gj/gk change each other\'s reference position.'}); -testVim('gj_gk', function(cm, vim, helpers) { - if (phantom) return; - cm.setSize(120); - // Test top of document edge case. - cm.setCursor(0, 4); - helpers.doKeys('g', 'j'); - helpers.doKeys('10', 'g', 'k'); - helpers.assertCursorAt(0, 4); - - // Test moving down preserves column position. - helpers.doKeys('g', 'j'); - var pos1 = cm.getCursor(); - var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4}; - helpers.doKeys('g', 'j'); - helpers.assertCursorAt(expectedPos2); - - // Move to the last character - cm.setCursor(0, 0); - // Move left to reset HSPos - helpers.doKeys('h'); - // Test bottom of document edge case. - helpers.doKeys('100', 'g', 'j'); - var endingPos = cm.getCursor(); - is(endingPos != 0, 'gj should not be on wrapped line 0'); - var topLeftCharCoords = cm.charCoords(makeCursor(0, 0)); - var endingCharCoords = cm.charCoords(endingPos); - is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0'); -},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' }); -testVim('}', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(1, 0); - cm.setCursor(0, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(4, 0); - cm.setCursor(0, 0); - helpers.doKeys('6', '}'); - helpers.assertCursorAt(5, 0); -}, { value: 'a\n\nb\nc\n\nd' }); -testVim('{', function(cm, vim, helpers) { - cm.setCursor(5, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(4, 0); - cm.setCursor(5, 0); - helpers.doKeys('2', '{'); - helpers.assertCursorAt(1, 0); - cm.setCursor(5, 0); - helpers.doKeys('6', '{'); - helpers.assertCursorAt(0, 0); -}, { value: 'a\n\nb\nc\n\nd' }); -testVim('paragraph motions', function(cm, vim, helpers) { - cm.setCursor(10, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(4, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(7, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(16, 0); - - cm.setCursor(9, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(14, 0); - - cm.setCursor(6, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(7, 0); - - // ip inside empty space - cm.setCursor(10, 0); - helpers.doKeys('v', 'i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(12, 0), cm.getCursor('head')); - helpers.doKeys('i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(13, 1), cm.getCursor('head')); - helpers.doKeys('2', 'i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - // should switch to visualLine mode - cm.setCursor(14, 0); - helpers.doKeys('', 'v', 'i', 'p'); - helpers.assertCursorAt(14, 0); - - cm.setCursor(14, 0); - helpers.doKeys('', 'V', 'i', 'p'); - eqPos(Pos(16, 1), cm.getCursor('head')); - - // ap inside empty space - cm.setCursor(10, 0); - helpers.doKeys('', 'v', 'a', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(13, 1), cm.getCursor('head')); - helpers.doKeys('a', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - cm.setCursor(13, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(13, 0), cm.getCursor('anchor')); - eqPos(Pos(14, 0), cm.getCursor('head')); - - cm.setCursor(16, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(14, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - cm.setCursor(0, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(0, 0), cm.getCursor('anchor')); - eqPos(Pos(4, 0), cm.getCursor('head')); - - cm.setCursor(0, 0); - helpers.doKeys('d', 'i', 'p'); - var register = helpers.getRegisterController().getRegister(); - eq('a\na\n', register.toString()); - is(register.linewise); - helpers.doKeys('3', 'j', 'p'); - helpers.doKeys('y', 'i', 'p'); - is(register.linewise); - eq('b\na\na\nc\n', register.toString()); -}, { value: 'a\na\n\n\n\nb\nc\n\n\n\n\n\n\nd\n\ne\nf' }); - -// Operator tests -testVim('dl', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('d', 'l'); - eq('word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dl_eol', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('d', 'l'); - eq(' word1', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 5); -}, { value: ' word1 ' }); -testVim('dl_repeat', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('2', 'd', 'l'); - eq('ord1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' w', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dh', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'h'); - eq(' wrd1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('o', register.toString()); - is(!register.linewise); - eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dj', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'j'); - eq(' word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1\nword2\n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2\n word3' }); -testVim('dj_end_of_document', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'j'); - eq(' word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1 ' }); -testVim('dk', function(cm, vim, helpers) { - var curStart = makeCursor(1, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'k'); - eq(' word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1\nword2\n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2\n word3' }); -testVim('dk_start_of_document', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'k'); - eq(' word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1 ' }); -testVim('dw_space', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('d', 'w'); - eq('word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dw_word', function(cm, vim, helpers) { - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('d', 'w'); - eq(' word2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1 ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 word2' }); -testVim('dw_only_word', function(cm, vim, helpers) { - // Test that if there is only 1 word left, dw deletes till the end of the - // line. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1 ', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1 ' }); -testVim('dw_eol', function(cm, vim, helpers) { - // Assert that dw does not delete the newline if last word to delete is at end - // of line. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' \nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1\nword2' }); -testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) { - // Assert that dw does not delete the newline if last word to delete is at end - // of line and it is followed by multiple newlines. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' \n\nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1\n\nword2' }); -testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq(' \nword', cm.getValue()); -}, { value: '\n \nword' }); -testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('word', cm.getValue()); -}, { value: '\nword' }); -testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n', cm.getValue()); -}, { value: '\n\n' }); -testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n \n', cm.getValue()); -}, { value: ' \n \n' }); -testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n\n', cm.getValue()); -}, { value: ' \n\n' }); -testVim('dw_word_whitespace_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n \nword2', cm.getValue()); -}, { value: 'word1\n \nword2'}) -testVim('dw_end_of_document', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('d', 'w'); - eq('\nab', cm.getValue()); -}, { value: '\nabc' }); -testVim('dw_repeat', function(cm, vim, helpers) { - // Assert that dw does delete newline if it should go to the next line, and - // that repeat works properly. - cm.setCursor(0, 1); - helpers.doKeys('d', '2', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1\nword2' }); -testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'e'); - eq('\n\n', cm.getValue()); -}, { value: 'word\n\n' }); -testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('d', 'e'); - eq('wor', cm.getValue()); -}, { value: 'word\n\n\n' }); -testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'e'); - eq('', cm.getValue()); -}, { value: ' \n\n\n' }); -testVim('de_end_of_document', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('d', 'e'); - eq('\nab', cm.getValue()); -}, { value: '\nabc' }); -testVim('db_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('\n\n', cm.getValue()); -}, { value: '\n\n\n' }); -testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('\nword', cm.getValue()); -}, { value: '\n\nword' }); -testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 3); - helpers.doKeys('d', 'b'); - eq('\n\nd', cm.getValue()); -}, { value: '\n\nword' }); -testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('', cm.getValue()); -}, { value: '\n \n' }); -testVim('db_start_of_document', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'b'); - eq('abc\n', cm.getValue()); -}, { value: 'abc\n' }); -testVim('dge_empty_lines', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doKeys('d', 'g', 'e'); - // Note: In real VIM the result should be '', but it's not quite consistent, - // since 2 newlines are deleted. But in the similar case of word\n\n, only - // 1 newline is deleted. We'll diverge from VIM's behavior since it's much - // easier this way. - eq('\n', cm.getValue()); -}, { value: '\n\n' }); -testVim('dge_word_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doKeys('d', 'g', 'e'); - eq('wor\n', cm.getValue()); -}, { value: 'word\n\n'}); -testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'g', 'e'); - eq('', cm.getValue()); -}, { value: '\n \n' }); -testVim('dge_start_of_document', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'g', 'e'); - eq('bc\n', cm.getValue()); -}, { value: 'abc\n' }); -testVim('d_inclusive', function(cm, vim, helpers) { - // Assert that when inclusive is set, the character the cursor is on gets - // deleted too. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('d', 'e'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('d_reverse', function(cm, vim, helpers) { - // Test that deleting in reverse works. - cm.setCursor(1, 0); - helpers.doKeys('d', 'b'); - eq(' word2 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\n', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2 ' }); -testVim('dd', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 1, ch: 0 }); - var expectedLineCount = cm.lineCount() - 1; - helpers.doKeys('d', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[1].textStart); -}); -testVim('dd_prefix_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); - var expectedLineCount = cm.lineCount() - 2; - helpers.doKeys('2', 'd', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[2].textStart); -}); -testVim('dd_motion_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); - var expectedLineCount = cm.lineCount() - 2; - helpers.doKeys('d', '2', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[2].textStart); -}); -testVim('dd_multiply_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount() - 6; - helpers.doKeys('2', 'd', '3', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[6].textStart); -}); -testVim('dd_lastline', function(cm, vim, helpers) { - cm.setCursor(cm.lineCount(), 0); - var expectedLineCount = cm.lineCount() - 1; - helpers.doKeys('d', 'd'); - eq(expectedLineCount, cm.lineCount()); - helpers.assertCursorAt(cm.lineCount() - 1, 0); -}); -testVim('dd_only_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - var expectedRegister = cm.getValue() + "\n"; - helpers.doKeys('d','d'); - eq(1, cm.lineCount()); - eq('', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedRegister, register.toString()); -}, { value: "thisistheonlyline" }); -// Yank commands should behave the exact same as d commands, expect that nothing -// gets deleted. -testVim('yw_repeat', function(cm, vim, helpers) { - // Assert that yw does yank newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('y', '2', 'w'); - eq(' word1\nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2' }); -testVim('yy_multiply_repeat', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount(); - helpers.doKeys('2', 'y', '3', 'y'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - eqPos(curStart, cm.getCursor()); -}); -// Change commands behave like d commands except that it also enters insert -// mode. In addition, when the change is linewise, an additional newline is -// inserted so that insert mode starts on that line. -testVim('cw', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('c', '2', 'w'); - eq(' word3', cm.getValue()); - helpers.assertCursorAt(0, 0); -}, { value: 'word1 word2 word3'}); -testVim('cw_repeat', function(cm, vim, helpers) { - // Assert that cw does delete newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('c', '2', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: ' word1\nword2' }); -testVim('cc_multiply_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount() - 5; - helpers.doKeys('2', 'c', '3', 'c'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('cc_should_not_append_to_document', function(cm, vim, helpers) { - var expectedLineCount = cm.lineCount(); - cm.setCursor(cm.lastLine(), 0); - helpers.doKeys('c', 'c'); - eq(expectedLineCount, cm.lineCount()); -}); -function fillArray(val, times) { - var arr = []; - for (var i = 0; i < times; i++) { - arr.push(val); - } - return arr; -} -testVim('c_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'c'); - var replacement = fillArray('hello', 3); - cm.replaceSelections(replacement); - eq('1hello\n5hello\nahellofg', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(2, 3); - helpers.doKeys('', '2', 'k', 'h', 'C'); - replacement = fillArray('world', 3); - cm.replaceSelections(replacement); - eq('1hworld\n5hworld\nahworld', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('c_visual_block_replay', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'c'); - var replacement = fillArray('fo', 3); - cm.replaceSelections(replacement); - eq('1fo4\n5fo8\nafodefg', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(0, 0); - helpers.doKeys('.'); - eq('foo4\nfoo8\nfoodefg', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); - -testVim('d_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'd'); - eq('1\n5\nafg', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('D_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'D'); - eq('1\n5\na', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); - -// Swapcase commands edit in place and do not modify registers. -testVim('g~w_repeat', function(cm, vim, helpers) { - // Assert that dw does delete newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('g', '~', '2', 'w'); - eq(' WORD1\nWORD2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2' }); -testVim('g~g~', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - var expectedLineCount = cm.lineCount(); - var expectedValue = cm.getValue().toUpperCase(); - helpers.doKeys('2', 'g', '~', '3', 'g', '~'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2\nword3\nword4\nword5\nword6' }); -testVim('gu_and_gU', function(cm, vim, helpers) { - var curStart = makeCursor(0, 7); - var value = cm.getValue(); - cm.setCursor(curStart); - helpers.doKeys('2', 'g', 'U', 'w'); - eq(cm.getValue(), 'wa wb xX WC wd'); - eqPos(curStart, cm.getCursor()); - helpers.doKeys('2', 'g', 'u', 'w'); - eq(cm.getValue(), value); - - helpers.doKeys('2', 'g', 'U', 'B'); - eq(cm.getValue(), 'wa WB Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); - - cm.setCursor(makeCursor(0, 4)); - helpers.doKeys('g', 'u', 'i', 'w'); - eq(cm.getValue(), 'wa wb Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); - - // TODO: support gUgU guu - // eqPos(makeCursor(0, 0), cm.getCursor()); - - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); -}, { value: 'wa wb xx wc wd' }); -testVim('visual_block_~', function(cm, vim, helpers) { - cm.setCursor(1, 1); - helpers.doKeys('', 'l', 'l', 'j', '~'); - helpers.assertCursorAt(1, 1); - eq('hello\nwoRLd\naBCDe', cm.getValue()); - cm.setCursor(2, 0); - helpers.doKeys('v', 'l', 'l', '~'); - helpers.assertCursorAt(2, 0); - eq('hello\nwoRLd\nAbcDe', cm.getValue()); -},{value: 'hello\nwOrld\nabcde' }); -testVim('._swapCase_visualBlock', function(cm, vim, helpers) { - helpers.doKeys('', 'j', 'j', 'l', '~'); - cm.setCursor(0, 3); - helpers.doKeys('.'); - eq('HelLO\nWorLd\nAbcdE', cm.getValue()); -},{value: 'hEllo\nwOrlD\naBcDe' }); -testVim('._delete_visualBlock', function(cm, vim, helpers) { - helpers.doKeys('', 'j', 'x'); - eq('ive\ne\nsome\nsugar', cm.getValue()); - helpers.doKeys('.'); - eq('ve\n\nsome\nsugar', cm.getValue()); - helpers.doKeys('j', 'j', '.'); - eq('ve\n\nome\nugar', cm.getValue()); - helpers.doKeys('u', '', '.'); - eq('ve\n\nme\ngar', cm.getValue()); -},{value: 'give\nme\nsome\nsugar' }); -testVim('>{motion}', function(cm, vim, helpers) { - cm.setCursor(1, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\n word2\nword3 '; - helpers.doKeys('>', 'k'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); -testVim('>>', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\n word2\nword3 '; - helpers.doKeys('2', '>', '>'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); -testVim('<{motion}', function(cm, vim, helpers) { - cm.setCursor(1, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('<', 'k'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); -testVim('<<', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('2', '<', '<'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); - -// Edit tests -function testEdit(name, before, pos, edit, after) { - return testVim(name, function(cm, vim, helpers) { - var ch = before.search(pos) - var line = before.substring(0, ch).split('\n').length - 1; - if (line) { - ch = before.substring(0, ch).split('\n').pop().length; - } - cm.setCursor(line, ch); - helpers.doKeys.apply(this, edit.split('')); - eq(after, cm.getValue()); - }, {value: before}); -} - -// These Delete tests effectively cover word-wise Change, Visual & Yank. -// Tabs are used as differentiated whitespace to catch edge cases. -// Normal word: -testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz'); -testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz'); -testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz'); -testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz'); -testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz'); -testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz'); -testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz'); -testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz'); -testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz'); -testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz'); -testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t'); -testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo'); -testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.'); -testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.'); -// Big word: -testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz'); -testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz'); -testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz'); -testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz'); -testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t'); -testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo'); -testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t'); -testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo'); -// Deleting text objects -// Open and close on same line -testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz'); -testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz'); -testEdit('dib_open_spc', 'foo (bAr) baz', /\(/, 'dib', 'foo () baz'); -testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo baz'); -testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo baz'); - -testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz'); -testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz'); -testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo baz'); -testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo baz'); - -testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz'); -testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz'); -testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo baz'); -testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo baz'); - -// delete around and inner b. -testEdit('dab_on_(_should_delete_around_()block', 'o( in(abc) )', /\(a/, 'dab', 'o( in )'); - -// delete around and inner B. -testEdit('daB_on_{_should_delete_around_{}block', 'o{ in{abc} }', /{a/, 'daB', 'o{ in }'); -testEdit('diB_on_{_should_delete_inner_{}block', 'o{ in{abc} }', /{a/, 'diB', 'o{ in{} }'); - -testEdit('da{_on_{_should_delete_inner_block', 'o{ in{abc} }', /{a/, 'da{', 'o{ in }'); -testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) baz'); -testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz'); -testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz'); -testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz'); -testMotion('di(_outside_should_stay', ['d', 'i', '('], { line: 0, ch: 0}, { line: 0, ch: 0}); - -// Open and close on different lines, equally indented -testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b'); -testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b'); -testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab'); -testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab'); -testEdit('daB_middle_spc', 'a{\n\tbar\n}b', /r/, 'daB', 'ab'); - -// open and close on diff lines, open indented less than close -testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b'); -testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b'); -testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab'); -testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab'); - -// open and close on diff lines, open indented more than close -testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b'); -testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b'); -testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb'); -testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb'); - -function testSelection(name, before, pos, keys, sel) { - return testVim(name, function(cm, vim, helpers) { - var ch = before.search(pos) - var line = before.substring(0, ch).split('\n').length - 1; - if (line) { - ch = before.substring(0, ch).split('\n').pop().length; - } - cm.setCursor(line, ch); - helpers.doKeys.apply(this, keys.split('')); - eq(sel, cm.getSelection()); - }, {value: before}); -} -testSelection('viw_middle_spc', 'foo \tbAr\t baz', /A/, 'viw', 'bAr'); -testSelection('vaw_middle_spc', 'foo \tbAr\t baz', /A/, 'vaw', 'bAr\t '); -testSelection('viw_middle_punct', 'foo \tbAr,\t baz', /A/, 'viw', 'bAr'); -testSelection('vaW_middle_punct', 'foo \tbAr,\t baz', /A/, 'vaW', 'bAr,\t '); -testSelection('viw_start_spc', 'foo \tbAr\t baz', /b/, 'viw', 'bAr'); -testSelection('viw_end_spc', 'foo \tbAr\t baz', /r/, 'viw', 'bAr'); -testSelection('viw_eol', 'foo \tbAr', /r/, 'viw', 'bAr'); -testSelection('vi{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'vi{', '\n\tbar\n\t'); -testSelection('va{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'va{', '{\n\tbar\n\t}'); - -testVim('mouse_select', function(cm, vim, helpers) { - cm.setSelection(Pos(0, 2), Pos(0, 4), {origin: '*mouse'}); - is(cm.state.vim.visualMode); - is(!cm.state.vim.visualLine); - is(!cm.state.vim.visualBlock); - helpers.doKeys(''); - is(!cm.somethingSelected()); - helpers.doKeys('g', 'v'); - eq('cd', cm.getSelection()); -}, {value: 'abcdef'}); - -// Operator-motion tests -testVim('D', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('D'); - eq(' wo\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 2); -}, { value: ' word1\nword2\n word3' }); -testVim('C', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('C'); - eq(' wo\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: ' word1\nword2\n word3' }); -testVim('Y', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('Y'); - eq(' word1\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\n word3' }); -testVim('~', function(cm, vim, helpers) { - helpers.doKeys('3', '~'); - eq('ABCdefg', cm.getValue()); - helpers.assertCursorAt(0, 3); -}, { value: 'abcdefg' }); - -// Action tests -testVim('ctrl-a', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(''); - eq('-9', cm.getValue()); - helpers.assertCursorAt(0, 1); - helpers.doKeys('2',''); - eq('-7', cm.getValue()); -}, {value: '-10'}); -testVim('ctrl-x', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(''); - eq('-1', cm.getValue()); - helpers.assertCursorAt(0, 1); - helpers.doKeys('2',''); - eq('-3', cm.getValue()); -}, {value: '0'}); -testVim('/ search forward', function(cm, vim, helpers) { - forEach(['', ''], function(key) { - cm.setCursor(0, 0); - helpers.doKeys(key); - helpers.assertCursorAt(0, 5); - helpers.doKeys('l'); - helpers.doKeys(key); - helpers.assertCursorAt(0, 10); - cm.setCursor(0, 11); - helpers.doKeys(key); - helpers.assertCursorAt(0, 11); - }); -}, {value: '__jmp1 jmp2 jmp'}); -testVim('a', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('a'); - helpers.assertCursorAt(0, 2); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('a_eol', function(cm, vim, helpers) { - cm.setCursor(0, lines[0].length - 1); - helpers.doKeys('a'); - helpers.assertCursorAt(0, lines[0].length); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('A_endOfSelectedArea', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'j', 'l'); - helpers.doKeys('A'); - helpers.assertCursorAt(1, 2); - eq('vim-insert', cm.getOption('keyMap')); -}, {value: 'foo\nbar'}); -testVim('i', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('i'); - helpers.assertCursorAt(0, 1); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('i_repeat', function(cm, vim, helpers) { - helpers.doKeys('3', 'i'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('testtesttest', cm.getValue()); - helpers.assertCursorAt(0, 11); -}, { value: '' }); -testVim('i_repeat_delete', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('2', 'i'); - cm.replaceRange('z', cm.getCursor()); - helpers.doInsertModeKeys('Backspace', 'Backspace'); - helpers.doKeys(''); - eq('abe', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'abcde' }); -testVim('A', function(cm, vim, helpers) { - helpers.doKeys('A'); - helpers.assertCursorAt(0, lines[0].length); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('A_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'A'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('testhello\nmehello\npleahellose', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(0, 0); - helpers.doKeys('.'); - // TODO this doesn't work yet - // eq('teshellothello\nme hello hello\nplehelloahellose', cm.getValue()); -}, {value: 'test\nme\nplease'}); -testVim('I', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('I'); - helpers.assertCursorAt(0, lines[0].textStart); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('I_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('3', 'I'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('testtesttestblah', cm.getValue()); - helpers.assertCursorAt(0, 11); -}, { value: 'blah' }); -testVim('I_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'l', 'l', 'I'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('hellotest\nhellome\nhelloplease', cm.getValue()); -}, {value: 'test\nme\nplease'}); -testVim('o', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('o'); - eq('word1\n\nword2', cm.getValue()); - helpers.assertCursorAt(1, 0); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'word1\nword2' }); -testVim('o_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('3', 'o'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('\ntest\ntest\ntest', cm.getValue()); - helpers.assertCursorAt(3, 3); -}, { value: '' }); -testVim('O', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('O'); - eq('\nword1\nword2', cm.getValue()); - helpers.assertCursorAt(0, 0); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'word1\nword2' }); -testVim('J', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('J'); - var expectedValue = 'word1 word2\nword3\n word4'; - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1); -}, { value: 'word1 \n word2\nword3\n word4' }); -testVim('J_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('3', 'J'); - var expectedValue = 'word1 word2 word3\n word4'; - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1); -}, { value: 'word1 \n word2\nword3\n word4' }); -testVim('p', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); - helpers.doKeys('p'); - eq('__abc\ndef_', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_register', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); - helpers.doKeys('"', 'a', 'p'); - eq('__abc\ndef_', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_wrong_register', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); - helpers.doKeys('p'); - eq('___', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: '___' }); -testVim('p_line', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); - helpers.doKeys('2', 'p'); - eq('___\n a\nd\n a\nd', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_lastline', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true); - helpers.doKeys('2', 'p'); - eq('___\n a\nd\n a\nd', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim(']p_first_indent_is_smaller', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq(' ___\n abc\n def', cm.getValue()); -}, { value: ' ___' }); -testVim(']p_first_indent_is_larger', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq(' ___\n abc\ndef', cm.getValue()); -}, { value: ' ___' }); -testVim(']p_with_tab_indents', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', '\t\tabc\n\t\t\tdef\n', true); - helpers.doKeys(']', 'p'); - eq('\t___\n\tabc\n\t\tdef', cm.getValue()); -}, { value: '\t___', indentWithTabs: true}); -testVim(']p_with_spaces_translated_to_tabs', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq('\t___\n\tabc\n\t\tdef', cm.getValue()); -}, { value: '\t___', indentWithTabs: true, tabSize: 2 }); -testVim('[p', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys('[', 'p'); - eq(' abc\n def\n ___', cm.getValue()); -}, { value: ' ___' }); -testVim('P', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); - helpers.doKeys('P'); - eq('_abc\ndef__', cm.getValue()); - helpers.assertCursorAt(1, 3); -}, { value: '___' }); -testVim('P_line', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); - helpers.doKeys('2', 'P'); - eq(' a\nd\n a\nd\n___', cm.getValue()); - helpers.assertCursorAt(0, 2); -}, { value: '___' }); -testVim('r', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('3', 'r', 'u'); - eq('wuuuet\nanother', cm.getValue(),'3r failed'); - helpers.assertCursorAt(0, 3); - cm.setCursor(0, 4); - helpers.doKeys('v', 'j', 'h', 'r', ''); - eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); -}, { value: 'wordet\nanother' }); -testVim('r_visual_block', function(cm, vim, helpers) { - cm.setCursor(2, 3); - helpers.doKeys('', 'k', 'k', 'h', 'h', 'r', 'l'); - eq('1lll\n5lll\nalllefg', cm.getValue()); - helpers.doKeys('', 'l', 'j', 'r', ''); - eq('1 l\n5 l\nalllefg', cm.getValue()); - cm.setCursor(2, 0); - helpers.doKeys('o'); - helpers.doKeys(''); - cm.replaceRange('\t\t', cm.getCursor()); - helpers.doKeys('', 'h', 'h', 'r', 'r'); - eq('1 l\n5 l\nalllefg\nrrrrrrrr', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('R', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('R'); - helpers.assertCursorAt(0, 1); - eq('vim-replace', cm.getOption('keyMap')); - is(cm.state.overwrite, 'Setting overwrite state failed'); -}); -testVim('mark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('`', 't'); - helpers.assertCursorAt(2, 2); - cm.setCursor(2, 0); - cm.replaceRange(' h', cm.getCursor()); - cm.setCursor(0, 0); - helpers.doKeys('\'', 't'); - helpers.assertCursorAt(2, 3); -}); -testVim('jumpToMark_next', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 2); - cm.setCursor(0, 0); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_next_repeat', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(0, 0); - helpers.doKeys('2', ']', '`'); - helpers.assertCursorAt(3, 2); - cm.setCursor(0, 0); - helpers.doKeys('2', ']', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_next_sameline', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 2); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 4); -}); -testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(4, 0); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(4, 0); -}); -testVim('jumpToMark_next_nomark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 2); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 1); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_next_action', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('d', ']', '`'); - helpers.assertCursorAt(0, 0); - var actual = cm.getLine(0); - var expected = 'pop pop 0 1 2 3 4'; - eq(actual, expected, "Deleting while jumping to the next mark failed."); -}); -testVim('jumpToMark_next_line_action', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('d', ']', '\''); - helpers.assertCursorAt(0, 1); - var actual = cm.getLine(0); - var expected = ' (a) [b] {c} ' - eq(actual, expected, "Deleting while jumping to the next mark line failed."); -}); -testVim('jumpToMark_prev', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(4, 0); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 2); - cm.setCursor(4, 0); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(5, 0); - helpers.doKeys('2', '[', '`'); - helpers.assertCursorAt(3, 2); - cm.setCursor(5, 0); - helpers.doKeys('2', '[', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 2); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) { - cm.setCursor(4, 4); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 0); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 2); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 6); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('delmark_single', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 't'); - helpers.doEx('delmarks t'); - cm.setCursor(0, 0); - helpers.doKeys('`', 't'); - helpers.assertCursorAt(0, 0); -}); -testVim('delmark_range', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks b-d'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_multi', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks bcd'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_multi_space', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks b c d'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_all', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks a b-de'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(0, 0); -}); -testVim('visual', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l'); - helpers.assertCursorAt(0, 4); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); - helpers.doKeys('d'); - eq('15', cm.getValue()); -}, { value: '12345' }); -testVim('visual_yank', function(cm, vim, helpers) { - helpers.doKeys('v', '3', 'l', 'y'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('p'); - eq('aa te test for yank', cm.getValue()); -}, { value: 'a test for yank' }) -testVim('visual_w', function(cm, vim, helpers) { - helpers.doKeys('v', 'w'); - eq(cm.getSelection(), 'motion t'); -}, { value: 'motion test'}); -testVim('visual_initial_selection', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v'); - cm.getSelection('n'); -}, { value: 'init'}); -testVim('visual_crossover_left', function(cm, vim, helpers) { - cm.setCursor(0, 2); - helpers.doKeys('v', 'l', 'h', 'h'); - cm.getSelection('ro'); -}, { value: 'cross'}); -testVim('visual_crossover_left', function(cm, vim, helpers) { - cm.setCursor(0, 2); - helpers.doKeys('v', 'h', 'l', 'l'); - cm.getSelection('os'); -}, { value: 'cross'}); -testVim('visual_crossover_up', function(cm, vim, helpers) { - cm.setCursor(3, 2); - helpers.doKeys('v', 'j', 'k', 'k'); - eqPos(Pos(2, 2), cm.getCursor('head')); - eqPos(Pos(3, 3), cm.getCursor('anchor')); - helpers.doKeys('k'); - eqPos(Pos(1, 2), cm.getCursor('head')); - eqPos(Pos(3, 3), cm.getCursor('anchor')); -}, { value: 'cross\ncross\ncross\ncross\ncross\n'}); -testVim('visual_crossover_down', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('v', 'k', 'j', 'j'); - eqPos(Pos(2, 3), cm.getCursor('head')); - eqPos(Pos(1, 2), cm.getCursor('anchor')); - helpers.doKeys('j'); - eqPos(Pos(3, 3), cm.getCursor('head')); - eqPos(Pos(1, 2), cm.getCursor('anchor')); -}, { value: 'cross\ncross\ncross\ncross\ncross\n'}); -testVim('visual_exit', function(cm, vim, helpers) { - helpers.doKeys('', 'l', 'j', 'j', ''); - eqPos(cm.getCursor('anchor'), cm.getCursor('head')); - eq(vim.visualMode, false); -}, { value: 'hello\nworld\nfoo' }); -testVim('visual_line', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd'); - eq(' 4\n 5', cm.getValue()); -}, { value: ' 1\n 2\n 3\n 4\n 5' }); -testVim('visual_block_move_to_eol', function(cm, vim, helpers) { - // moveToEol should move all block cursors to end of line - cm.setCursor(0, 0); - helpers.doKeys('', 'G', '$'); - var selections = cm.getSelections().join(); - eq("123,45,6", selections); -}, {value: '123\n45\n6'}); -testVim('visual_block_different_line_lengths', function(cm, vim, helpers) { - // test the block selection with lines of different length - // i.e. extending the selection - // till the end of the longest line. - helpers.doKeys('', 'l', 'j', 'j', '6', 'l', 'd'); - helpers.doKeys('d', 'd', 'd', 'd'); - eq('', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('visual_block_truncate_on_short_line', function(cm, vim, helpers) { - // check for left side selection in case - // of moving up to a shorter line. - cm.replaceRange('', cm.getCursor()); - cm.setCursor(3, 4); - helpers.doKeys('', 'l', 'k', 'k', 'd'); - eq('hello world\n{\ntis\nsa!', cm.getValue()); -}, {value: 'hello world\n{\nthis is\nsparta!'}); -testVim('visual_block_corners', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('', '2', 'l', 'k'); - // circle around the anchor - // and check the selections - var selections = cm.getSelections(); - eq('345891', selections.join('')); - helpers.doKeys('4', 'h'); - selections = cm.getSelections(); - eq('123678', selections.join('')); - helpers.doKeys('j', 'j'); - selections = cm.getSelections(); - eq('678abc', selections.join('')); - helpers.doKeys('4', 'l'); - selections = cm.getSelections(); - eq('891cde', selections.join('')); -}, {value: '12345\n67891\nabcde'}); -testVim('visual_block_mode_switch', function(cm, vim, helpers) { - // switch between visual modes - cm.setCursor(1, 1); - // blockwise to characterwise visual - helpers.doKeys('', 'j', 'l', 'v'); - selections = cm.getSelections(); - eq('7891\nabc', selections.join('')); - // characterwise to blockwise - helpers.doKeys(''); - selections = cm.getSelections(); - eq('78bc', selections.join('')); - // blockwise to linewise visual - helpers.doKeys('V'); - selections = cm.getSelections(); - eq('67891\nabcde', selections.join('')); -}, {value: '12345\n67891\nabcde'}); -testVim('visual_block_crossing_short_line', function(cm, vim, helpers) { - // visual block with long and short lines - cm.setCursor(0, 3); - helpers.doKeys('', 'j', 'j', 'j'); - var selections = cm.getSelections().join(); - eq('4,,d,b', selections); - helpers.doKeys('3', 'k'); - selections = cm.getSelections().join(); - eq('4', selections); - helpers.doKeys('5', 'j', 'k'); - selections = cm.getSelections().join(""); - eq(10, selections.length); -}, {value: '123456\n78\nabcdefg\nfoobar\n}\n'}); -testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '3' , 'l', ''); - eqPos(makeCursor(0, 3), cm.getCursor()); - helpers.doKeys('h', '', '2' , 'j' ,'3' , 'l'); - eq(cm.getSelections().join(), "3456,,cdef"); - helpers.doKeys('4' , 'h'); - eq(cm.getSelections().join(), "23,8,bc"); - helpers.doKeys('2' , 'l'); - eq(cm.getSelections().join(), "34,,cd"); -}, {value: '123456\n78\nabcdefg\nfoobar'}); - -testVim('visual_marks', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l', 'j', 'j', 'v'); - // Test visual mode marks - cm.setCursor(2, 1); - helpers.doKeys('\'', '<'); - helpers.assertCursorAt(0, 1); - helpers.doKeys('\'', '>'); - helpers.assertCursorAt(2, 0); -}); -testVim('visual_join', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J'); - eq(' 1 2 3\n 4\n 5', cm.getValue()); - is(!vim.visualMode); -}, { value: ' 1\n 2\n 3\n 4\n 5' }); -testVim('visual_join_2', function(cm, vim, helpers) { - helpers.doKeys('G', 'V', 'g', 'g', 'J'); - eq('1 2 3 4 5 6 ', cm.getValue()); - is(!vim.visualMode); -}, { value: '1\n2\n3\n4\n5\n6\n'}); -testVim('visual_blank', function(cm, vim, helpers) { - helpers.doKeys('v', 'k'); - eq(vim.visualMode, true); -}, { value: '\n' }); -testVim('reselect_visual', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v'); - helpers.assertCursorAt(0, 5); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); - helpers.doKeys('v'); - cm.setCursor(1, 0); - helpers.doKeys('v', 'l', 'l', 'p'); - eq('123456\n2345\nbar', cm.getValue()); - cm.setCursor(0, 0); - helpers.doKeys('g', 'v'); - // here the fake cursor is at (1, 3) - helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); - helpers.doKeys('v'); - cm.setCursor(2, 0); - helpers.doKeys('v', 'l', 'l', 'g', 'v'); - helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); - helpers.doKeys('g', 'v'); - helpers.assertCursorAt(2, 3); - eqPos(makeCursor(2, 0), cm.getCursor('anchor')); - eq('123456\n2345\nbar', cm.getValue()); -}, { value: '123456\nfoo\nbar' }); -testVim('reselect_visual_line', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd'); - eq('foo\nand\nbar', cm.getValue()); - cm.setCursor(1, 0); - helpers.doKeys('V', 'y', 'j'); - helpers.doKeys('V', 'p' , 'g', 'v', 'd'); - eq('foo\nand', cm.getValue()); -}, { value: 'hello\nthis\nis\nfoo\nand\nbar' }); -testVim('reselect_visual_block', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('', 'k', 'h', ''); - cm.setCursor(2, 1); - helpers.doKeys('v', 'l', 'g', 'v'); - eqPos(Pos(1, 2), vim.sel.anchor); - eqPos(Pos(0, 1), vim.sel.head); - // Ensure selection is done with visual block mode rather than one - // continuous range. - eq(cm.getSelections().join(''), '23oo') - helpers.doKeys('g', 'v'); - eqPos(Pos(2, 1), vim.sel.anchor); - eqPos(Pos(2, 2), vim.sel.head); - helpers.doKeys(''); - // Ensure selection of deleted range - cm.setCursor(1, 1); - helpers.doKeys('v', '', 'j', 'd', 'g', 'v'); - eq(cm.getSelections().join(''), 'or'); -}, { value: '123456\nfoo\nbar' }); -testVim('s_normal', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('s'); - helpers.doKeys(''); - eq('ac', cm.getValue()); -}, { value: 'abc'}); -testVim('s_visual', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v', 's'); - helpers.doKeys(''); - helpers.assertCursorAt(0, 0); - eq('ac', cm.getValue()); -}, { value: 'abc'}); -testVim('o_visual', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys('v','l','l','l','o'); - helpers.assertCursorAt(0,0); - helpers.doKeys('v','v','j','j','j','o'); - helpers.assertCursorAt(0,0); - helpers.doKeys('O'); - helpers.doKeys('l','l') - helpers.assertCursorAt(3, 3); - helpers.doKeys('d'); - eq('p',cm.getValue()); -}, { value: 'abcd\nefgh\nijkl\nmnop'}); -testVim('o_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('','3','j','l','l', 'o'); - eqPos(Pos(3, 3), vim.sel.anchor); - eqPos(Pos(0, 1), vim.sel.head); - helpers.doKeys('O'); - eqPos(Pos(3, 1), vim.sel.anchor); - eqPos(Pos(0, 3), vim.sel.head); - helpers.doKeys('o'); - eqPos(Pos(0, 3), vim.sel.anchor); - eqPos(Pos(3, 1), vim.sel.head); -}, { value: 'abcd\nefgh\nijkl\nmnop'}); -testVim('changeCase_visual', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'l', 'l'); - helpers.doKeys('U'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('v', 'l', 'l'); - helpers.doKeys('u'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('l', 'l', 'l', '.'); - helpers.assertCursorAt(0, 3); - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'v', 'j', 'U', 'q'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('j', '@', 'a'); - helpers.assertCursorAt(1, 0); - cm.setCursor(3, 0); - helpers.doKeys('V', 'U', 'j', '.'); - eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue()); -}, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'}); -testVim('changeCase_visual_block', function(cm, vim, helpers) { - cm.setCursor(2, 1); - helpers.doKeys('', 'k', 'k', 'h', 'U'); - eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue()); - cm.setCursor(0, 2); - helpers.doKeys('.'); - eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue()); - // check when last line is shorter. - cm.setCursor(2, 2); - helpers.doKeys('.'); - eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue()); -}, { value: 'abcdef\nghijkl\nmnopq\nfoo'}); -testVim('visual_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'l', 'l', 'y'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('3', 'l', 'j', 'v', 'l', 'p'); - helpers.assertCursorAt(1, 5); - eq('this is a\nunithitest for visual paste', cm.getValue()); - cm.setCursor(0, 0); - // in case of pasting whole line - helpers.doKeys('y', 'y'); - cm.setCursor(1, 6); - helpers.doKeys('v', 'l', 'l', 'l', 'p'); - helpers.assertCursorAt(2, 0); - eq('this is a\nunithi\nthis is a\n for visual paste', cm.getValue()); -}, { value: 'this is a\nunit test for visual paste'}); - -// This checks the contents of the register used to paste the text -testVim('v_paste_from_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - cm.setCursor(1, 0); - helpers.doKeys('v', 'p'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+register/.test(text)); - }); -}, { value: 'register contents\nare not erased'}); -testVim('S_normal', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('j', 'S'); - helpers.doKeys(''); - helpers.assertCursorAt(1, 0); - eq('aa\n\ncc', cm.getValue()); -}, { value: 'aa\nbb\ncc'}); -testVim('blockwise_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '3', 'j', 'l', 'y'); - cm.setCursor(0, 2); - // paste one char after the current cursor position - helpers.doKeys('p'); - eq('helhelo\nworwold\nfoofo\nbarba', cm.getValue()); - cm.setCursor(0, 0); - helpers.doKeys('v', '4', 'l', 'y'); - cm.setCursor(0, 0); - helpers.doKeys('', '3', 'j', 'p'); - eq('helheelhelo\norwold\noofo\narba', cm.getValue()); -}, { value: 'hello\nworld\nfoo\nbar'}); -testVim('blockwise_paste_long/short_line', function(cm, vim, helpers) { - // extend short lines in case of different line lengths. - cm.setCursor(0, 0); - helpers.doKeys('', 'j', 'j', 'y'); - cm.setCursor(0, 3); - helpers.doKeys('p'); - eq('hellho\nfoo f\nbar b', cm.getValue()); -}, { value: 'hello\nfoo\nbar'}); -testVim('blockwise_paste_cut_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'x'); - cm.setCursor(0, 0); - helpers.doKeys('P'); - eq('cut\nand\npaste\nme', cm.getValue()); -}, { value: 'cut\nand\npaste\nme'}); -testVim('blockwise_paste_from_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', '"', 'a', 'y'); - cm.setCursor(0, 3); - helpers.doKeys('"', 'a', 'p'); - eq('foobfar\nhellho\nworlwd', cm.getValue()); -}, { value: 'foobar\nhello\nworld'}); -testVim('blockwise_paste_last_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'l', 'y'); - cm.setCursor(3, 0); - helpers.doKeys('p'); - eq('cut\nand\npaste\nmcue\n an\n pa', cm.getValue()); -}, { value: 'cut\nand\npaste\nme'}); - -testVim('S_visual', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v', 'j', 'S'); - helpers.doKeys(''); - helpers.assertCursorAt(0, 0); - eq('\ncc', cm.getValue()); -}, { value: 'aa\nbb\ncc'}); - -testVim('/ and n/N', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 11); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 6); - helpers.doKeys('N'); - helpers.assertCursorAt(0, 11); - - cm.setCursor(0, 0); - helpers.doKeys('2', '/'); - helpers.assertCursorAt(1, 6); -}, { value: 'match nope match \n nope Match' }); -testVim('/_case', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('Match'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 6); -}, { value: 'match nope match \n nope Match' }); -testVim('/_2_pcre', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', true); - cm.openDialog = helpers.fakeOpenDialog('(word){2}'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 9); - helpers.doKeys('n'); - helpers.assertCursorAt(2, 1); -}, { value: 'word\n another wordword\n wordwordword\n' }); -testVim('/_2_nopcre', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', false); - cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 9); - helpers.doKeys('n'); - helpers.assertCursorAt(2, 1); -}, { value: 'word\n another wordword\n wordwordword\n' }); -testVim('/_nongreedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('aa'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('?_nongreedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('aa'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('/_greedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a+'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('?_greedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a+'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('/_greedy_0_or_more', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a*'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 5); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 0); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa\n aa'}); -testVim('?_greedy_0_or_more', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a*'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 0); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 5); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa\n aa'}); -testVim('? and n/N', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 6); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 11); - helpers.doKeys('N'); - helpers.assertCursorAt(1, 6); - - cm.setCursor(0, 0); - helpers.doKeys('2', '?'); - helpers.assertCursorAt(0, 11); -}, { value: 'match nope match \n nope Match' }); -testVim('*', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 22); - - cm.setCursor(0, 9); - helpers.doKeys('2', '*'); - helpers.assertCursorAt(1, 8); -}, { value: 'nomatch match nomatch match \nnomatch Match' }); -testVim('*_no_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 0); -}, { value: ' \n match \n' }); -testVim('*_symbol', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('*'); - helpers.assertCursorAt(1, 0); -}, { value: ' /}\n/} match \n' }); -testVim('#', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('#'); - helpers.assertCursorAt(1, 8); - - cm.setCursor(0, 9); - helpers.doKeys('2', '#'); - helpers.assertCursorAt(0, 22); -}, { value: 'nomatch match nomatch match \nnomatch Match' }); -testVim('*_seek', function(cm, vim, helpers) { - // Should skip over space and symbols. - cm.setCursor(0, 3); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 22); -}, { value: ' := match nomatch match \nnomatch Match' }); -testVim('#', function(cm, vim, helpers) { - // Should skip over space and symbols. - cm.setCursor(0, 3); - helpers.doKeys('#'); - helpers.assertCursorAt(1, 8); -}, { value: ' := match nomatch match \nnomatch Match' }); -testVim('g*', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('g', '*'); - helpers.assertCursorAt(0, 18); - cm.setCursor(0, 8); - helpers.doKeys('3', 'g', '*'); - helpers.assertCursorAt(1, 8); -}, { value: 'matches match alsoMatch\nmatchme matching' }); -testVim('g#', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('g', '#'); - helpers.assertCursorAt(0, 0); - cm.setCursor(0, 8); - helpers.doKeys('3', 'g', '#'); - helpers.assertCursorAt(1, 0); -}, { value: 'matches match alsoMatch\nmatchme matching' }); -testVim('macro_insert', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '0', 'i'); - cm.replaceRange('foo', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q', '@', 'a'); - eq('foofoo', cm.getValue()); -}, { value: ''}); -testVim('macro_insert_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '$', 'a'); - cm.replaceRange('larry.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('a'); - cm.replaceRange('curly.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('a'); - cm.replaceRange('moe.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('@', 'a'); - // At this point, the most recent edit should be the 2nd insert change - // inside the macro, i.e. "curly.". - helpers.doKeys('.'); - eq('larry.curly.moe.larry.curly.curly.', cm.getValue()); -}, { value: ''}); -testVim('macro_space', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', ''); - helpers.assertCursorAt(0, 2); - helpers.doKeys('q', 'a', '', '', 'q'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0, 6); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0, 8); -}, { value: 'one line of text.'}); -testVim('macro_t_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 't', 'e', 'q'); - helpers.assertCursorAt(0, 1); - helpers.doKeys('l', '@', 'a'); - helpers.assertCursorAt(0, 6); - helpers.doKeys('l', ';'); - helpers.assertCursorAt(0, 12); -}, { value: 'one line of text.'}); -testVim('macro_f_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'b', 'f', 'e', 'q'); - helpers.assertCursorAt(0, 2); - helpers.doKeys('@', 'b'); - helpers.assertCursorAt(0, 7); - helpers.doKeys(';'); - helpers.assertCursorAt(0, 13); -}, { value: 'one line of text.'}); -testVim('macro_slash_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'c'); - cm.openDialog = helpers.fakeOpenDialog('e'); - helpers.doKeys('/', 'q'); - helpers.assertCursorAt(0, 2); - helpers.doKeys('@', 'c'); - helpers.assertCursorAt(0, 7); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 13); -}, { value: 'one line of text.'}); -testVim('macro_multislash_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'd'); - cm.openDialog = helpers.fakeOpenDialog('e'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('t'); - helpers.doKeys('/', 'q'); - helpers.assertCursorAt(0, 12); - helpers.doKeys('@', 'd'); - helpers.assertCursorAt(0, 15); -}, { value: 'one line of text to rule them all.'}); -testVim('macro_parens', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'z', 'i'); - cm.replaceRange('(', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('e', 'a'); - cm.replaceRange(')', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('w', '@', 'z'); - helpers.doKeys('w', '@', 'z'); - eq('(see) (spot) (run)', cm.getValue()); -}, { value: 'see spot run'}); -testVim('macro_overwrite', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'z', '0', 'i'); - cm.replaceRange('I ', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('e'); - // Now replace the macro with something else. - helpers.doKeys('q', 'z', 'a'); - cm.replaceRange('.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('e', '@', 'z'); - helpers.doKeys('e', '@', 'z'); - eq('I see. spot. run.', cm.getValue()); -}, { value: 'see spot run'}); -testVim('macro_search_f', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'f', ' '); - helpers.assertCursorAt(0,3); - helpers.doKeys('q', '0'); - helpers.assertCursorAt(0,0); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0,3); -}, { value: 'The quick brown fox jumped over the lazy dog.'}); -testVim('macro_search_2f', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '2', 'f', ' '); - helpers.assertCursorAt(0,9); - helpers.doKeys('q', '0'); - helpers.assertCursorAt(0,0); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0,9); -}, { value: 'The quick brown fox jumped over the lazy dog.'}); -testVim('yank_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'b', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo/.test(text)); - is(/b\s+bar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', 'l', 'j', '"', 'a', 'y'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+oo\nar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_line_to_line_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'A', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_word_to_word_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - helpers.doKeys('j', '"', 'A', 'y', 'w'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foobar/.test(text)); - is(/"\s+foobar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_line_to_word_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - helpers.doKeys('j', '"', 'A', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_word_to_line_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'A', 'y', 'w'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('macro_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'i'); - cm.replaceRange('gangnam', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('q', 'b', 'o'); - cm.replaceRange('style', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+i/.test(text)); - is(/b\s+o/.test(text)); - }); - helpers.doKeys(':'); -}, { value: ''}); -testVim('._register', function(cm,vim,helpers) { - cm.setCursor(0,0); - helpers.doKeys('i'); - cm.replaceRange('foo',cm.getCursor()); - helpers.doKeys(''); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/\.\s+foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim(':_register', function(cm,vim,helpers) { - helpers.doEx('bar'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/:\s+bar/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_register_escape', function(cm, vim, helpers) { - // Check that the register is restored if the user escapes rather than confirms. - cm.openDialog = helpers.fakeOpenDialog('waldo'); - helpers.doKeys('/'); - var onKeyDown; - var onKeyUp; - var KEYCODES = { - f: 70, - o: 79, - Esc: 27 - }; - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - onKeyUp = options.onKeyUp; - }; - var close = function() {}; - helpers.doKeys('/'); - // Fake some keyboard events coming in. - onKeyDown({keyCode: KEYCODES.f}, '', close); - onKeyUp({keyCode: KEYCODES.f}, '', close); - onKeyDown({keyCode: KEYCODES.o}, 'f', close); - onKeyUp({keyCode: KEYCODES.o}, 'f', close); - onKeyDown({keyCode: KEYCODES.o}, 'fo', close); - onKeyUp({keyCode: KEYCODES.o}, 'fo', close); - onKeyDown({keyCode: KEYCODES.Esc}, 'foo', close); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/waldo/.test(text)); - is(!/foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_register', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('foo'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/\/\s+foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_history', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('this'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('checks'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('search'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('history'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('checks'); - helpers.doKeys('/'); - var onKeyDown; - var onKeyUp; - var query = ''; - var keyCodes = { - Up: 38, - Down: 40 - }; - cm.openDialog = function(template, callback, options) { - onKeyUp = options.onKeyUp; - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') query = newVal; - } - helpers.doKeys('/'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'checks'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'history'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'search'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'this'); - onKeyDown({keyCode: keyCodes.Down}, query, close); - onKeyUp({keyCode: keyCodes.Down}, query, close); - eq(query, 'search'); -}, {value: ''}); -testVim('exCommand_history', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('registers'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('sort'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('map'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('invalid'); - helpers.doKeys(':'); - var onKeyDown; - var onKeyUp; - var input = ''; - var keyCodes = { - Up: 38, - Down: 40, - s: 115 - }; - cm.openDialog = function(template, callback, options) { - onKeyUp = options.onKeyUp; - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') input = newVal; - } - helpers.doKeys(':'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'invalid'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'map'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'sort'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'registers'); - onKeyDown({keyCode: keyCodes.s}, '', close); - input = 's'; - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'sort'); -}, {value: ''}); -testVim('.', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('2', 'd', 'w'); - helpers.doKeys('.'); - eq('5 6', cm.getValue()); -}, { value: '1 2 3 4 5 6'}); -testVim('._repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('2', 'd', 'w'); - helpers.doKeys('3', '.'); - eq('6', cm.getValue()); -}, { value: '1 2 3 4 5 6'}); -testVim('._insert', function(cm, vim, helpers) { - helpers.doKeys('i'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('testestt', cm.getValue()); - helpers.assertCursorAt(0, 6); -}, { value: ''}); -testVim('._insert_repeat', function(cm, vim, helpers) { - helpers.doKeys('i'); - cm.replaceRange('test', cm.getCursor()); - cm.setCursor(0, 4); - helpers.doKeys(''); - helpers.doKeys('2', '.'); - eq('testesttestt', cm.getValue()); - helpers.assertCursorAt(0, 10); -}, { value: ''}); -testVim('._repeat_insert', function(cm, vim, helpers) { - helpers.doKeys('3', 'i'); - cm.replaceRange('te', cm.getCursor()); - cm.setCursor(0, 2); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('tetettetetee', cm.getValue()); - helpers.assertCursorAt(0, 10); -}, { value: ''}); -testVim('._insert_o', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - cm.setCursor(1, 1); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('\nz\nz', cm.getValue()); - helpers.assertCursorAt(2, 0); -}, { value: ''}); -testVim('._insert_o_repeat', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(1, 0); - helpers.doKeys('2', '.'); - eq('\nz\nz\nz', cm.getValue()); - helpers.assertCursorAt(3, 0); -}, { value: ''}); -testVim('._insert_o_indent', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(1, 2); - helpers.doKeys('.'); - eq('{\n z\n z', cm.getValue()); - helpers.assertCursorAt(2, 2); -}, { value: '{'}); -testVim('._insert_cw', function(cm, vim, helpers) { - helpers.doKeys('c', 'w'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(0, 3); - helpers.doKeys('2', 'l'); - helpers.doKeys('.'); - eq('test test word3', cm.getValue()); - helpers.assertCursorAt(0, 8); -}, { value: 'word1 word2 word3' }); -testVim('._insert_cw_repeat', function(cm, vim, helpers) { - // For some reason, repeat cw in desktop VIM will does not repeat insert mode - // changes. Will conform to that behavior. - helpers.doKeys('c', 'w'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(0, 4); - helpers.doKeys('l'); - helpers.doKeys('2', '.'); - eq('test test', cm.getValue()); - helpers.assertCursorAt(0, 8); -}, { value: 'word1 word2 word3' }); -testVim('._delete', function(cm, vim, helpers) { - cm.setCursor(0, 5); - helpers.doKeys('i'); - helpers.doInsertModeKeys('Backspace'); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('zace', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'zabcde'}); -testVim('._delete_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('i'); - helpers.doInsertModeKeys('Backspace'); - helpers.doKeys(''); - helpers.doKeys('2', '.'); - eq('zzce', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'zzabcde'}); -testVim('._visual_>', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('V', 'j', '>'); - cm.setCursor(2, 0) - helpers.doKeys('.'); - eq(' 1\n 2\n 3\n 4', cm.getValue()); - helpers.assertCursorAt(2, 2); -}, { value: '1\n2\n3\n4'}); -testVim('f;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(9, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('F;', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('F', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(2, cm.getCursor().ch); -}, { value: '01x3xx6x8x'}); -testVim('t;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(8, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('T;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(2, cm.getCursor().ch); -}, { value: '0xx3xx678x'}); -testVim('f,', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('f', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(2, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('F,', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('F', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(9, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('t,', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('t', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(3, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('T,', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('T', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(8, cm.getCursor().ch); -}, { value: '01x3xx67xx'}); -testVim('fd,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('d', ';'); - eq('56789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('d', ','); - eq('01239', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fd,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('d', ';'); - eq('01239', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('d', ','); - eq('56789', cm.getValue()); -}, { value: '0123456789'}); -testVim('td,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('d', ';'); - eq('456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('d', ','); - eq('012349', cm.getValue()); -}, { value: '0123456789'}); -testVim('Td,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('d', ';'); - eq('012349', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('d', ','); - eq('456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('fc,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('c', ';', ''); - eq('56789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('c', ','); - eq('01239', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fc,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('c', ';', ''); - eq('01239', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('c', ','); - eq('56789', cm.getValue()); -}, { value: '0123456789'}); -testVim('tc,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('c', ';', ''); - eq('456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('c', ','); - eq('012349', cm.getValue()); -}, { value: '0123456789'}); -testVim('Tc,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('c', ';', ''); - eq('012349', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('c', ','); - eq('456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('fy,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('y', ';', 'P'); - eq('012340123456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('y', ',', 'P'); - eq('012345678456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fy,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('y', ';', 'p'); - eq('012345678945678', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('y', ',', 'P'); - eq('012340123456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('ty,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('y', ';', 'P'); - eq('01230123456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('y', ',', 'p'); - eq('01234567895678', cm.getValue()); -}, { value: '0123456789'}); -testVim('Ty,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('y', ';', 'p'); - eq('01234567895678', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('y', ',', 'P'); - eq('01230123456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('HML', function(cm, vim, helpers) { - var lines = 35; - var textHeight = cm.defaultTextHeight(); - cm.setSize(600, lines*textHeight); - cm.setCursor(120, 0); - helpers.doKeys('H'); - helpers.assertCursorAt(86, 2); - helpers.doKeys('L'); - helpers.assertCursorAt(120, 4); - helpers.doKeys('M'); - helpers.assertCursorAt(103,4); -}, { value: (function(){ - var lines = new Array(100); - var upper = ' xx\n'; - var lower = ' xx\n'; - upper = lines.join(upper); - lower = lines.join(lower); - return upper + lower; -})()}); - -var zVals = []; -forEach(['zb','zz','zt','z-','z.','z'], function(e, idx){ - var lineNum = 250; - var lines = 35; - testVim(e, function(cm, vim, helpers) { - var k1 = e[0]; - var k2 = e.substring(1); - var textHeight = cm.defaultTextHeight(); - cm.setSize(600, lines*textHeight); - cm.setCursor(lineNum, 0); - helpers.doKeys(k1, k2); - zVals[idx] = cm.getScrollInfo().top; - }, { value: (function(){ - return new Array(500).join('\n'); - })()}); -}); -testVim('zb', function(cm, vim, helpers){ - eq(zVals[2], zVals[5]); -}); - -var moveTillCharacterSandbox = - 'The quick brown fox \n' - 'jumped over the lazy dog.' -testVim('moveTillCharacter', function(cm, vim, helpers){ - cm.setCursor(0, 0); - // Search for the 'q'. - cm.openDialog = helpers.fakeOpenDialog('q'); - helpers.doKeys('/'); - eq(4, cm.getCursor().ch); - // Jump to just before the first o in the list. - helpers.doKeys('t'); - helpers.doKeys('o'); - eq('The quick brown fox \n', cm.getValue()); - // Delete that one character. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('o'); - eq('The quick bown fox \n', cm.getValue()); - // Delete everything until the next 'o'. - helpers.doKeys('.'); - eq('The quick box \n', cm.getValue()); - // An unmatched character should have no effect. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('q'); - eq('The quick box \n', cm.getValue()); - // Matches should only be possible on single lines. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('z'); - eq('The quick box \n', cm.getValue()); - // After all that, the search for 'q' should still be active, so the 'N' command - // can run it again in reverse. Use that to delete everything back to the 'q'. - helpers.doKeys('d'); - helpers.doKeys('N'); - eq('The ox \n', cm.getValue()); - eq(4, cm.getCursor().ch); -}, { value: moveTillCharacterSandbox}); -testVim('searchForPipe', function(cm, vim, helpers){ - CodeMirror.Vim.setOption('pcre', false); - cm.setCursor(0, 0); - // Search for the '|'. - cm.openDialog = helpers.fakeOpenDialog('|'); - helpers.doKeys('/'); - eq(4, cm.getCursor().ch); -}, { value: 'this|that'}); - - -var scrollMotionSandbox = - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; -testVim('scrollMotion', function(cm, vim, helpers){ - var prevCursor, prevScrollInfo; - cm.setCursor(0, 0); - // ctrl-y at the top of the file should have no effect. - helpers.doKeys(''); - eq(0, cm.getCursor().line); - prevScrollInfo = cm.getScrollInfo(); - helpers.doKeys(''); - eq(1, cm.getCursor().line); - is(prevScrollInfo.top < cm.getScrollInfo().top); - // Jump to the end of the sandbox. - cm.setCursor(1000, 0); - prevCursor = cm.getCursor(); - // ctrl-e at the bottom of the file should have no effect. - helpers.doKeys(''); - eq(prevCursor.line, cm.getCursor().line); - prevScrollInfo = cm.getScrollInfo(); - helpers.doKeys(''); - eq(prevCursor.line - 1, cm.getCursor().line, "Y"); - is(prevScrollInfo.top > cm.getScrollInfo().top); -}, { value: scrollMotionSandbox}); - -var squareBracketMotionSandbox = ''+ - '({\n'+//0 - ' ({\n'+//11 - ' /*comment {\n'+//2 - ' */(\n'+//3 - '#else \n'+//4 - ' /* )\n'+//5 - '#if }\n'+//6 - ' )}*/\n'+//7 - ')}\n'+//8 - '{}\n'+//9 - '#else {{\n'+//10 - '{}\n'+//11 - '}\n'+//12 - '{\n'+//13 - '#endif\n'+//14 - '}\n'+//15 - '}\n'+//16 - '#else';//17 -testVim('[[, ]]', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(']', ']'); - helpers.assertCursorAt(9,0); - helpers.doKeys('2', ']', ']'); - helpers.assertCursorAt(13,0); - helpers.doKeys(']', ']'); - helpers.assertCursorAt(17,0); - helpers.doKeys('[', '['); - helpers.assertCursorAt(13,0); - helpers.doKeys('2', '[', '['); - helpers.assertCursorAt(9,0); - helpers.doKeys('[', '['); - helpers.assertCursorAt(0,0); -}, { value: squareBracketMotionSandbox}); -testVim('[], ][', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(']', '['); - helpers.assertCursorAt(12,0); - helpers.doKeys('2', ']', '['); - helpers.assertCursorAt(16,0); - helpers.doKeys(']', '['); - helpers.assertCursorAt(17,0); - helpers.doKeys('[', ']'); - helpers.assertCursorAt(16,0); - helpers.doKeys('2', '[', ']'); - helpers.assertCursorAt(12,0); - helpers.doKeys('[', ']'); - helpers.assertCursorAt(0,0); -}, { value: squareBracketMotionSandbox}); -testVim('[{, ]}', function(cm, vim, helpers) { - cm.setCursor(4, 10); - helpers.doKeys('[', '{'); - helpers.assertCursorAt(2,12); - helpers.doKeys('2', '[', '{'); - helpers.assertCursorAt(0,1); - cm.setCursor(4, 10); - helpers.doKeys(']', '}'); - helpers.assertCursorAt(6,11); - helpers.doKeys('2', ']', '}'); - helpers.assertCursorAt(8,1); - cm.setCursor(0,1); - helpers.doKeys(']', '}'); - helpers.assertCursorAt(8,1); - helpers.doKeys('[', '{'); - helpers.assertCursorAt(0,1); -}, { value: squareBracketMotionSandbox}); -testVim('[(, ])', function(cm, vim, helpers) { - cm.setCursor(4, 10); - helpers.doKeys('[', '('); - helpers.assertCursorAt(3,14); - helpers.doKeys('2', '[', '('); - helpers.assertCursorAt(0,0); - cm.setCursor(4, 10); - helpers.doKeys(']', ')'); - helpers.assertCursorAt(5,11); - helpers.doKeys('2', ']', ')'); - helpers.assertCursorAt(8,0); - helpers.doKeys('[', '('); - helpers.assertCursorAt(0,0); - helpers.doKeys(']', ')'); - helpers.assertCursorAt(8,0); -}, { value: squareBracketMotionSandbox}); -testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) { - forEach(['*', '/'], function(key){ - cm.setCursor(7, 0); - helpers.doKeys('2', '[', key); - helpers.assertCursorAt(2,2); - helpers.doKeys('2', ']', key); - helpers.assertCursorAt(7,5); - }); -}, { value: squareBracketMotionSandbox}); -testVim('[#, ]#', function(cm, vim, helpers) { - cm.setCursor(10, 3); - helpers.doKeys('2', '[', '#'); - helpers.assertCursorAt(4,0); - helpers.doKeys('5', ']', '#'); - helpers.assertCursorAt(17,0); - cm.setCursor(10, 3); - helpers.doKeys(']', '#'); - helpers.assertCursorAt(14,0); -}, { value: squareBracketMotionSandbox}); -testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) { - cm.setCursor(11, 0); - helpers.doKeys('[', 'm'); - helpers.assertCursorAt(10,7); - helpers.doKeys('4', '[', 'm'); - helpers.assertCursorAt(1,3); - helpers.doKeys('5', ']', 'm'); - helpers.assertCursorAt(11,0); - helpers.doKeys('[', 'M'); - helpers.assertCursorAt(9,1); - helpers.doKeys('3', ']', 'M'); - helpers.assertCursorAt(15,0); - helpers.doKeys('5', '[', 'M'); - helpers.assertCursorAt(7,3); -}, { value: squareBracketMotionSandbox}); - -// Ex mode tests -testVim('ex_go_to_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doEx('4'); - helpers.assertCursorAt(3, 0); -}, { value: 'a\nb\nc\nd\ne\n'}); -testVim('ex_write', function(cm, vim, helpers) { - var tmp = CodeMirror.commands.save; - var written; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - // Test that w, wr, wri ... write all trigger :write. - var command = 'write'; - for (var i = 1; i < command.length; i++) { - written = false; - actualCm = null; - helpers.doEx(command.substring(0, i)); - eq(written, true); - eq(actualCm, cm); - } - CodeMirror.commands.save = tmp; -}); -testVim('ex_sort', function(cm, vim, helpers) { - helpers.doEx('sort'); - eq('Z\na\nb\nc\nd', cm.getValue()); -}, { value: 'b\nZ\nd\nc\na'}); -testVim('ex_sort_reverse', function(cm, vim, helpers) { - helpers.doEx('sort!'); - eq('d\nc\nb\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_range', function(cm, vim, helpers) { - helpers.doEx('2,3sort'); - eq('b\nc\nd\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_oneline', function(cm, vim, helpers) { - helpers.doEx('2sort'); - // Expect no change. - eq('b\nd\nc\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_ignoreCase', function(cm, vim, helpers) { - helpers.doEx('sort i'); - eq('a\nb\nc\nd\nZ', cm.getValue()); -}, { value: 'b\nZ\nd\nc\na'}); -testVim('ex_sort_unique', function(cm, vim, helpers) { - helpers.doEx('sort u'); - eq('Z\na\nb\nc\nd', cm.getValue()); -}, { value: 'b\nZ\na\na\nd\na\nc\na'}); -testVim('ex_sort_decimal', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('d3\n s5\n6\n.9', cm.getValue()); -}, { value: '6\nd3\n s5\n.9'}); -testVim('ex_sort_decimal_negative', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('z-9\nd3\n s5\n6\n.9', cm.getValue()); -}, { value: '6\nd3\n s5\n.9\nz-9'}); -testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) { - helpers.doEx('sort! d'); - eq('.9\n6\n s5\nd3', cm.getValue()); -}, { value: '6\nd3\n s5\n.9'}); -testVim('ex_sort_hex', function(cm, vim, helpers) { - helpers.doEx('sort x'); - eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue()); -}, { value: '6\nd3\n s5\n&0xB\n.9'}); -testVim('ex_sort_octal', function(cm, vim, helpers) { - helpers.doEx('sort o'); - eq('.8\n.9\nd3\n s5\n6', cm.getValue()); -}, { value: '6\nd3\n s5\n.9\n.8'}); -testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('y\nz\nc1\nb2\na3', cm.getValue()); -}, { value: 'a3\nz\nc1\ny\nb2'}); -testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) { - helpers.doEx('sort! d'); - eq('a3\nb2\nc1\nz\ny', cm.getValue()); -}, { value: 'a3\nz\nc1\ny\nb2'}); -// test for :global command -testVim('ex_global', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doEx('g/one/s//two'); - eq('two two\n two two\n two two', cm.getValue()); - helpers.doEx('1,2g/two/s//one'); - eq('one one\n one one\n two two', cm.getValue()); -}, {value: 'one one\n one one\n one one'}); -testVim('ex_global_confirm', function(cm, vim, helpers) { - cm.setCursor(0, 0); - var onKeyDown; - var openDialogSave = cm.openDialog; - var KEYCODES = { - a: 65, - n: 78, - q: 81, - y: 89 - }; - // Intercept the ex command, 'global' - cm.openDialog = function(template, callback, options) { - // Intercept the prompt for the embedded ex command, 'substitute' - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - }; - callback('g/one/s//two/gc'); - }; - helpers.doKeys(':'); - var close = function() {}; - onKeyDown({keyCode: KEYCODES.n}, '', close); - onKeyDown({keyCode: KEYCODES.y}, '', close); - onKeyDown({keyCode: KEYCODES.a}, '', close); - onKeyDown({keyCode: KEYCODES.q}, '', close); - onKeyDown({keyCode: KEYCODES.y}, '', close); - eq('one two\n two two\n one one\n two one\n one one', cm.getValue()); -}, {value: 'one one\n one one\n one one\n one one\n one one'}); -// Basic substitute tests. -testVim('ex_substitute_same_line', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('s/one/two/g'); - eq('one one\n two two', cm.getValue()); -}, { value: 'one one\n one one'}); -testVim('ex_substitute_full_file', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('%s/one/two/g'); - eq('two two\n two two', cm.getValue()); -}, { value: 'one one\n one one'}); -testVim('ex_substitute_input_range', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('1,3s/\\d/0/g'); - eq('0\n0\n0\n4', cm.getValue()); -}, { value: '1\n2\n3\n4' }); -testVim('ex_substitute_visual_range', function(cm, vim, helpers) { - cm.setCursor(1, 0); - // Set last visual mode selection marks '< and '> at lines 2 and 4 - helpers.doKeys('V', '2', 'j', 'v'); - helpers.doEx('\'<,\'>s/\\d/0/g'); - eq('1\n0\n0\n0\n5', cm.getValue()); -}, { value: '1\n2\n3\n4\n5' }); -testVim('ex_substitute_empty_query', function(cm, vim, helpers) { - // If the query is empty, use last query. - cm.setCursor(1, 0); - cm.openDialog = helpers.fakeOpenDialog('1'); - helpers.doKeys('/'); - helpers.doEx('s//b/g'); - eq('abb ab2 ab3', cm.getValue()); -}, { value: 'a11 a12 a13' }); -testVim('ex_substitute_javascript', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', false); - cm.setCursor(1, 0); - // Throw all the things that javascript likes to treat as special values - // into the replace part. All should be literal (this is VIM). - helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/g') - eq('a $$ $\' $` $& 0 b', cm.getValue()); -}, { value: 'a 0 b' }); -testVim('ex_substitute_empty_arguments', function(cm,vim,helpers) { - cm.setCursor(0, 0); - helpers.doEx('s/a/b/g'); - cm.setCursor(1, 0); - helpers.doEx('s'); - eq('b b\nb a', cm.getValue()); -}, {value: 'a a\na a'}); - -// More complex substitute tests that test both pcre and nopcre options. -function testSubstitute(name, options) { - testVim(name + '_pcre', function(cm, vim, helpers) { - cm.setCursor(1, 0); - CodeMirror.Vim.setOption('pcre', true); - helpers.doEx(options.expr); - eq(options.expectedValue, cm.getValue()); - }, options); - // If no noPcreExpr is defined, assume that it's the same as the expr. - var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr; - testVim(name + '_nopcre', function(cm, vim, helpers) { - cm.setCursor(1, 0); - CodeMirror.Vim.setOption('pcre', false); - helpers.doEx(noPcreExpr); - eq(options.expectedValue, cm.getValue()); - }, options); -} -testSubstitute('ex_substitute_capture', { - value: 'a11 a12 a13', - expectedValue: 'a1111 a1212 a1313', - // $n is a backreference - expr: 's/(\\d+)/$1$1/g', - // \n is a backreference. - noPcreExpr: 's/\\(\\d+\\)/\\1\\1/g'}); -testSubstitute('ex_substitute_capture2', { - value: 'a 0 b', - expectedValue: 'a $00 b', - expr: 's/(\\d+)/$$$1$1/g', - noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/g'}); -testSubstitute('ex_substitute_nocapture', { - value: 'a11 a12 a13', - expectedValue: 'a$1$1 a$1$1 a$1$1', - expr: 's/(\\d+)/$$1$$1/g', - noPcreExpr: 's/\\(\\d+\\)/$1$1/g'}); -testSubstitute('ex_substitute_nocapture2', { - value: 'a 0 b', - expectedValue: 'a $10 b', - expr: 's/(\\d+)/$$1$1/g', - noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/g'}); -testSubstitute('ex_substitute_nocapture', { - value: 'a b c', - expectedValue: 'a $ c', - expr: 's/b/$$/', - noPcreExpr: 's/b/$/'}); -testSubstitute('ex_substitute_slash_regex', { - value: 'one/two \n three/four', - expectedValue: 'one|two \n three|four', - expr: '%s/\\//|'}); -testSubstitute('ex_substitute_pipe_regex', { - value: 'one|two \n three|four', - expectedValue: 'one,two \n three,four', - expr: '%s/\\|/,/', - noPcreExpr: '%s/|/,/'}); -testSubstitute('ex_substitute_or_regex', { - value: 'one|two \n three|four', - expectedValue: 'ana|twa \n thraa|faar', - expr: '%s/o|e|u/a/g', - noPcreExpr: '%s/o\\|e\\|u/a/g'}); -testSubstitute('ex_substitute_or_word_regex', { - value: 'one|two \n three|four', - expectedValue: 'five|five \n three|four', - expr: '%s/(one|two)/five/g', - noPcreExpr: '%s/\\(one\\|two\\)/five/g'}); -testSubstitute('ex_substitute_backslashslash_regex', { - value: 'one\\two \n three\\four', - expectedValue: 'one,two \n three,four', - expr: '%s/\\\\/,'}); -testSubstitute('ex_substitute_slash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one/two \n three/four', - expr: '%s/,/\\/'}); -testSubstitute('ex_substitute_backslash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one\\two \n three\\four', - expr: '%s/,/\\\\/g'}); -testSubstitute('ex_substitute_multibackslash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes. - expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes. -testSubstitute('ex_substitute_braces_word', { - value: 'ababab abb ab{2}', - expectedValue: 'ab abb ab{2}', - expr: '%s/(ab){2}//g', - noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'}); -testSubstitute('ex_substitute_braces_range', { - value: 'a aa aaa aaaa', - expectedValue: 'a a', - expr: '%s/a{2,3}//g', - noPcreExpr: '%s/a\\{2,3\\}//g'}); -testSubstitute('ex_substitute_braces_literal', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab abb ', - expr: '%s/ab\\{2\\}//g', - noPcreExpr: '%s/ab{2}//g'}); -testSubstitute('ex_substitute_braces_char', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab ab{2}', - expr: '%s/ab{2}//g', - noPcreExpr: '%s/ab\\{2\\}//g'}); -testSubstitute('ex_substitute_braces_no_escape', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab ab{2}', - expr: '%s/ab{2}//g', - noPcreExpr: '%s/ab\\{2}//g'}); -testSubstitute('ex_substitute_count', { - value: '1\n2\n3\n4', - expectedValue: '1\n0\n0\n4', - expr: 's/\\d/0/i 2'}); -testSubstitute('ex_substitute_count_with_range', { - value: '1\n2\n3\n4', - expectedValue: '1\n2\n0\n0', - expr: '1,3s/\\d/0/ 3'}); -testSubstitute('ex_substitute_not_global', { - value: 'aaa\nbaa\ncaa', - expectedValue: 'xaa\nbxa\ncxa', - expr: '%s/a/x/'}); -function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) { - testVim(name, function(cm, vim, helpers) { - var savedOpenDialog = cm.openDialog; - var savedKeyName = CodeMirror.keyName; - var onKeyDown; - var recordedCallback; - var closed = true; // Start out closed, set false on second openDialog. - function close() { - closed = true; - } - // First openDialog should save callback. - cm.openDialog = function(template, callback, options) { - recordedCallback = callback; - } - // Do first openDialog. - helpers.doKeys(':'); - // Second openDialog should save keyDown handler. - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - closed = false; - }; - // Return the command to Vim and trigger second openDialog. - recordedCallback(command); - // The event should really use keyCode, but here just mock it out and use - // key and replace keyName to just return key. - CodeMirror.keyName = function (e) { return e.key; } - keys = keys.toUpperCase(); - for (var i = 0; i < keys.length; i++) { - is(!closed); - onKeyDown({ key: keys.charAt(i) }, '', close); - } - try { - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(finalPos); - is(closed); - } catch(e) { - throw e - } finally { - // Restore overriden functions. - CodeMirror.keyName = savedKeyName; - cm.openDialog = savedOpenDialog; - } - }, { value: initialValue }); -}; -testSubstituteConfirm('ex_substitute_confirm_emptydoc', - '%s/x/b/c', '', '', '', makeCursor(0, 0)); -testSubstituteConfirm('ex_substitute_confirm_nomatch', - '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0)); -testSubstituteConfirm('ex_substitute_confirm_accept', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_random_keys', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_some', - '%s/a/b/cg', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_all', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_accept_then_all', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_quit', - '%s/a/b/cg', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_last', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_oneline', - '1s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_range_accept', - '1,2s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_some', - '1,3s/a/b/cg', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_all', - '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_last', - '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0)); -//:noh should clear highlighting of search-results but allow to resume search through n -testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('?'); - helpers.doEx('noh'); - eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared'); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting'); -}, { value: 'match nope match \n nope Match' }); -testVim('set_boolean', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', true, 'boolean'); - // Test default value is set. - is(CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set to non-boolean - CodeMirror.Vim.setOption('testoption', '5'); - fail(); - } catch (expected) {}; - // Test setOption - CodeMirror.Vim.setOption('testoption', false); - is(!CodeMirror.Vim.getOption('testoption')); -}); -testVim('ex_set_boolean', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', true, 'boolean'); - // Test default value is set. - is(CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set to non-boolean - helpers.doEx('set testoption=22'); - fail(); - } catch (expected) {}; - // Test setOption - helpers.doEx('set notestoption'); - is(!CodeMirror.Vim.getOption('testoption')); -}); -testVim('set_string', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', 'a', 'string'); - // Test default value is set. - eq('a', CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set non-string. - CodeMirror.Vim.setOption('testoption', true); - fail(); - } catch (expected) {}; - try { - // Test fail to set 'notestoption' - CodeMirror.Vim.setOption('notestoption', 'b'); - fail(); - } catch (expected) {}; - // Test setOption - CodeMirror.Vim.setOption('testoption', 'c'); - eq('c', CodeMirror.Vim.getOption('testoption')); -}); -testVim('ex_set_string', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', 'a', 'string'); - // Test default value is set. - eq('a', CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set 'notestoption' - helpers.doEx('set notestoption=b'); - fail(); - } catch (expected) {}; - // Test setOption - helpers.doEx('set testoption=c') - eq('c', CodeMirror.Vim.getOption('testoption')); -}); -// TODO: Reset key maps after each test. -testVim('ex_map_key2key', function(cm, vim, helpers) { - helpers.doEx('map a x'); - helpers.doKeys('a'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); -testVim('ex_unmap_key2key', function(cm, vim, helpers) { - helpers.doEx('unmap a'); - helpers.doKeys('a'); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'abc' }); -testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) { - try { - helpers.doEx('unmap a'); - fail(); - } catch (expected) {} - helpers.doKeys('a'); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'abc' }); -testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) { - helpers.doEx('map ; :'); - var dialogOpened = false; - cm.openDialog = function() { - dialogOpened = true; - } - helpers.doKeys(';'); - eq(dialogOpened, true); -}); -testVim('ex_map_ex2key:', function(cm, vim, helpers) { - helpers.doEx('map :del x'); - helpers.doEx('del'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); -testVim('ex_map_ex2ex', function(cm, vim, helpers) { - helpers.doEx('map :del :w'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - helpers.doEx('del'); - CodeMirror.commands.save = tmp; - eq(written, true); - eq(actualCm, cm); -}); -testVim('ex_map_key2ex', function(cm, vim, helpers) { - helpers.doEx('map a :w'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - helpers.doKeys('a'); - CodeMirror.commands.save = tmp; - eq(written, true); - eq(actualCm, cm); -}); -testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) { - CodeMirror.Vim.map('b', ':w', 'visual'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - // Mapping should not work in normal mode. - helpers.doKeys('b'); - eq(written, false); - // Mapping should work in visual mode. - helpers.doKeys('v', 'b'); - eq(written, true); - eq(actualCm, cm); - - CodeMirror.commands.save = tmp; -}); -testVim('ex_imap', function(cm, vim, helpers) { - CodeMirror.Vim.map('jk', '', 'insert'); - helpers.doKeys('i'); - is(vim.insertMode); - helpers.doKeys('j', 'k'); - is(!vim.insertMode); -}) - -// Testing registration of functions as ex-commands and mapping to -keys -testVim('ex_api_test', function(cm, vim, helpers) { - var res=false; - var val='from'; - CodeMirror.Vim.defineEx('extest','ext',function(cm,params){ - if(params.args)val=params.args[0]; - else res=true; - }); - helpers.doEx(':ext to'); - eq(val,'to','Defining ex-command failed'); - CodeMirror.Vim.map('',':ext'); - helpers.doKeys('',''); - is(res,'Mapping to key failed'); -}); -// For now, this test needs to be last because it messes up : for future tests. -testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) { - helpers.doEx('map : x'); - helpers.doKeys(':'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); - -// Test event handlers -testVim('beforeSelectionChange', function(cm, vim, helpers) { - cm.setCursor(0, 100); - eqPos(cm.getCursor('head'), cm.getCursor('anchor')); -}, { value: 'abc' }); - - diff --git a/shared/html/libs/codemirror/5.0.0/theme/3024-day.css b/shared/html/libs/codemirror/5.0.0/theme/3024-day.css deleted file mode 100644 index 3592816..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/3024-day.css +++ /dev/null @@ -1,40 +0,0 @@ -/* - - Name: 3024 day - Author: Jan T. Sott (http://github.com/idleberg) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-3024-day.CodeMirror {background: #f7f7f7; color: #3a3432;} -.cm-s-3024-day div.CodeMirror-selected {background: #d6d5d4 !important;} -.cm-s-3024-day.CodeMirror ::selection { background: #d6d5d4; } -.cm-s-3024-day.CodeMirror ::-moz-selection { background: #d9d9d9; } - -.cm-s-3024-day .CodeMirror-gutters {background: #f7f7f7; border-right: 0px;} -.cm-s-3024-day .CodeMirror-guttermarker { color: #db2d20; } -.cm-s-3024-day .CodeMirror-guttermarker-subtle { color: #807d7c; } -.cm-s-3024-day .CodeMirror-linenumber {color: #807d7c;} - -.cm-s-3024-day .CodeMirror-cursor {border-left: 1px solid #5c5855 !important;} - -.cm-s-3024-day span.cm-comment {color: #cdab53;} -.cm-s-3024-day span.cm-atom {color: #a16a94;} -.cm-s-3024-day span.cm-number {color: #a16a94;} - -.cm-s-3024-day span.cm-property, .cm-s-3024-day span.cm-attribute {color: #01a252;} -.cm-s-3024-day span.cm-keyword {color: #db2d20;} -.cm-s-3024-day span.cm-string {color: #fded02;} - -.cm-s-3024-day span.cm-variable {color: #01a252;} -.cm-s-3024-day span.cm-variable-2 {color: #01a0e4;} -.cm-s-3024-day span.cm-def {color: #e8bbd0;} -.cm-s-3024-day span.cm-bracket {color: #3a3432;} -.cm-s-3024-day span.cm-tag {color: #db2d20;} -.cm-s-3024-day span.cm-link {color: #a16a94;} -.cm-s-3024-day span.cm-error {background: #db2d20; color: #5c5855;} - -.cm-s-3024-day .CodeMirror-activeline-background {background: #e8f2ff !important;} -.cm-s-3024-day .CodeMirror-matchingbracket { text-decoration: underline; color: #a16a94 !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/3024-night.css b/shared/html/libs/codemirror/5.0.0/theme/3024-night.css deleted file mode 100644 index ccab9d5..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/3024-night.css +++ /dev/null @@ -1,39 +0,0 @@ -/* - - Name: 3024 night - Author: Jan T. Sott (http://github.com/idleberg) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-3024-night.CodeMirror {background: #090300; color: #d6d5d4;} -.cm-s-3024-night div.CodeMirror-selected {background: #3a3432 !important;} -.cm-s-3024-night.CodeMirror ::selection { background: rgba(58, 52, 50, .99); } -.cm-s-3024-night.CodeMirror ::-moz-selection { background: rgba(58, 52, 50, .99); } -.cm-s-3024-night .CodeMirror-gutters {background: #090300; border-right: 0px;} -.cm-s-3024-night .CodeMirror-guttermarker { color: #db2d20; } -.cm-s-3024-night .CodeMirror-guttermarker-subtle { color: #5c5855; } -.cm-s-3024-night .CodeMirror-linenumber {color: #5c5855;} - -.cm-s-3024-night .CodeMirror-cursor {border-left: 1px solid #807d7c !important;} - -.cm-s-3024-night span.cm-comment {color: #cdab53;} -.cm-s-3024-night span.cm-atom {color: #a16a94;} -.cm-s-3024-night span.cm-number {color: #a16a94;} - -.cm-s-3024-night span.cm-property, .cm-s-3024-night span.cm-attribute {color: #01a252;} -.cm-s-3024-night span.cm-keyword {color: #db2d20;} -.cm-s-3024-night span.cm-string {color: #fded02;} - -.cm-s-3024-night span.cm-variable {color: #01a252;} -.cm-s-3024-night span.cm-variable-2 {color: #01a0e4;} -.cm-s-3024-night span.cm-def {color: #e8bbd0;} -.cm-s-3024-night span.cm-bracket {color: #d6d5d4;} -.cm-s-3024-night span.cm-tag {color: #db2d20;} -.cm-s-3024-night span.cm-link {color: #a16a94;} -.cm-s-3024-night span.cm-error {background: #db2d20; color: #807d7c;} - -.cm-s-3024-night .CodeMirror-activeline-background {background: #2F2F2F !important;} -.cm-s-3024-night .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/ambiance-mobile.css b/shared/html/libs/codemirror/5.0.0/theme/ambiance-mobile.css deleted file mode 100644 index 88d332e..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/ambiance-mobile.css +++ /dev/null @@ -1,5 +0,0 @@ -.cm-s-ambiance.CodeMirror { - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} diff --git a/shared/html/libs/codemirror/5.0.0/theme/ambiance.css b/shared/html/libs/codemirror/5.0.0/theme/ambiance.css deleted file mode 100644 index afcf15a..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/ambiance.css +++ /dev/null @@ -1,75 +0,0 @@ -/* ambiance theme for codemirror */ - -/* Color scheme */ - -.cm-s-ambiance .cm-keyword { color: #cda869; } -.cm-s-ambiance .cm-atom { color: #CF7EA9; } -.cm-s-ambiance .cm-number { color: #78CF8A; } -.cm-s-ambiance .cm-def { color: #aac6e3; } -.cm-s-ambiance .cm-variable { color: #ffb795; } -.cm-s-ambiance .cm-variable-2 { color: #eed1b3; } -.cm-s-ambiance .cm-variable-3 { color: #faded3; } -.cm-s-ambiance .cm-property { color: #eed1b3; } -.cm-s-ambiance .cm-operator {color: #fa8d6a;} -.cm-s-ambiance .cm-comment { color: #555; font-style:italic; } -.cm-s-ambiance .cm-string { color: #8f9d6a; } -.cm-s-ambiance .cm-string-2 { color: #9d937c; } -.cm-s-ambiance .cm-meta { color: #D2A8A1; } -.cm-s-ambiance .cm-qualifier { color: yellow; } -.cm-s-ambiance .cm-builtin { color: #9999cc; } -.cm-s-ambiance .cm-bracket { color: #24C2C7; } -.cm-s-ambiance .cm-tag { color: #fee4ff } -.cm-s-ambiance .cm-attribute { color: #9B859D; } -.cm-s-ambiance .cm-header {color: blue;} -.cm-s-ambiance .cm-quote { color: #24C2C7; } -.cm-s-ambiance .cm-hr { color: pink; } -.cm-s-ambiance .cm-link { color: #F4C20B; } -.cm-s-ambiance .cm-special { color: #FF9D00; } -.cm-s-ambiance .cm-error { color: #AF2018; } - -.cm-s-ambiance .CodeMirror-matchingbracket { color: #0f0; } -.cm-s-ambiance .CodeMirror-nonmatchingbracket { color: #f22; } - -.cm-s-ambiance .CodeMirror-selected { background: rgba(255, 255, 255, 0.15); } -.cm-s-ambiance.CodeMirror-focused .CodeMirror-selected { background: rgba(255, 255, 255, 0.10); } -.cm-s-ambiance.CodeMirror ::selection { background: rgba(255, 255, 255, 0.10); } -.cm-s-ambiance.CodeMirror ::-moz-selection { background: rgba(255, 255, 255, 0.10); } - -/* Editor styling */ - -.cm-s-ambiance.CodeMirror { - line-height: 1.40em; - color: #E6E1DC; - background-color: #202020; - -webkit-box-shadow: inset 0 0 10px black; - -moz-box-shadow: inset 0 0 10px black; - box-shadow: inset 0 0 10px black; -} - -.cm-s-ambiance .CodeMirror-gutters { - background: #3D3D3D; - border-right: 1px solid #4D4D4D; - box-shadow: 0 10px 20px black; -} - -.cm-s-ambiance .CodeMirror-linenumber { - text-shadow: 0px 1px 1px #4d4d4d; - color: #111; - padding: 0 5px; -} - -.cm-s-ambiance .CodeMirror-guttermarker { color: #aaa; } -.cm-s-ambiance .CodeMirror-guttermarker-subtle { color: #111; } - -.cm-s-ambiance .CodeMirror-lines .CodeMirror-cursor { - border-left: 1px solid #7991E8; -} - -.cm-s-ambiance .CodeMirror-activeline-background { - background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.031); -} - -.cm-s-ambiance.CodeMirror, -.cm-s-ambiance .CodeMirror-gutters { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAQAAAAHUWYVAABFFUlEQVQYGbzBCeDVU/74/6fj9HIcx/FRHx9JCFmzMyGRURhLZIkUsoeRfUjS2FNDtr6WkMhO9sm+S8maJfu+Jcsg+/o/c+Z4z/t97/vezy3z+z8ekGlnYICG/o7gdk+wmSHZ1z4pJItqapjoKXWahm8NmV6eOTbWUOp6/6a/XIg6GQqmenJ2lDHyvCFZ2cBDbmtHA043VFhHwXxClWmeYAdLhV00Bd85go8VmaFCkbVkzlQENzfBDZ5gtN7HwF0KDrTwJ0dypSOzpaKCMwQHKTIreYIxlmhXTzTWkVm+LTynZhiSBT3RZQ7aGfjGEd3qyXQ1FDymqbKxpspERQN2MiRjNZlFFQXfCNFm9nM1zpAsoYjmtRTc5ajwuaXc5xrWskT97RaKzAGe5ARHhVUsDbjKklziiX5WROcJwSNCNI+9w1Jwv4Zb2r7lCMZ4oq5C0EdTx+2GzNuKpJ+iFf38JEWkHJn9DNF7mmBDITrWEg0VWL3pHU20tSZnuqWu+R3BtYa8XxV1HO7GyD32UkOpL/yDloINFTmvtId+nmAjxRw40VMwVKiwrKLE4bK5UOVntYwhOcSSXKrJHKPJedocpGjVz/ZMIbnYUPB10/eKCrs5apqpgVmWzBYWpmtKHecJPjaUuEgRDDaU0oZghCJ6zNMQ5ZhDYx05r5v2muQdM0EILtXUsaKiQX9WMEUotagQzFbUNN6NUPC2nm5pxEWGCjMc3GdJHjSU2kORLK/JGSrkfGEIjncU/CYUnOipoYemwj8tST9NsJmB7TUVXtbUtXATJVZXBMvYeTXJfobgJUPmGMP/yFaWonaa6BcFO3nqcIqCozSZoZoSr1g4zJOzuyGnxTEX3lUEJ7WcZgme8ddaWvWJo2AJR9DZU3CUIbhCSG6ybSwN6qtJVnCU2svDTP2ZInOw2cBTrqtQahtNZn9NcJ4l2NaSmSkkP1noZWnVwkLmdUPOwLZEwy2Z3S3R+4rIG9hcbpPXHFVWcQdZkn2FOta3cKWQnNRC5g1LsJah4GCzSVsKnCOY5OAFRTBekyyryeyilhFKva75r4Mc0aWanGEaThcy31s439KKxTzJYY5WTHPU1FtIHjQU3Oip4xlNzj/lBw23dYZVliQa7WAXf4shetcQfatI+jWRDBPmyNeW6A1P5kdDgyYJlba0BIM8BZu1JfrFwItyjcAMR3K0BWOIrtMEXyhyrlVEx3ui5dUBjmB/Q3CXW85R4mBD0s7B+4q5tKUjOlb9qqmhi5AZ6GFIC5HXtOobdYGlVdMVbNJ8toNTFcHxnoL+muBagcctjWnbNMuR00uI7nQESwg5q2qqrKWIfrNUmeQocY6HuyxJV02wj36w00yhpmUFenv4p6fUkZYqLyuinx2RGOjhCXYyJF84oiU00YMOOhhquNdfbOB7gU88pY4xJO8LVdp6/q2voeB4R04vIdhSE40xZObx1HGGJ/ja0LBthFInKaLPPFzuCaYaoj8JjPME8yoyxo6zlBqkiUZYgq00OYMswbWO5NGmq+xhipxHLRW29ARjNKXO0wRnear8XSg4XFPLKEPUS1GqvyLwiuBUoa7zpZ0l5xxFwWmWZC1H5h5FwU8eQ7K+g8UcVY6TMQreVQT/8uQ8Z+ALIXnSEa2pYZQneE9RZbSBNYXfWYJzW/h/4j4Dp1tYVcFIC5019Vyi4ThPqSFCzjGWaHQTBU8q6vrVwgxP9Lkm840imWKpcLCjYTtrKuwvsKSnrvHCXGkSMk9p6lhckfRpIeis+N2PiszT+mFLspyGleUhDwcLrZqmyeylxwjBcKHEapqkmyangyLZRVOijwOtCY5SsG5zL0OwlCJ4y5KznF3EUNDDrinwiyLZRzOXtlBbK5ITHFGLp8Q0R6ab6mS7enI2cFrxOyHvOCFaT1HThS1krjCwqWeurCkk+willhCC+RSZnRXBiZaC5RXRIZYKp2lyfrHwiKPKR0JDzrdU2EFgpidawlFDR6FgXUMNa+g1FY3bUQh2cLCwosRdnuQTS/S+JVrGLeWIvtQUvONJxlqSQYYKpwoN2kaocLjdVsis4Mk80ESF2YpSkzwldjHkjFCUutI/r+EHDU8oCs6yzL3PhWiEooZdFMkymlas4AcI3KmoMMNSQ3tHzjGWCrcJJdYyZC7QFGwjRL9p+MrRkAGWzIaWCn9W0F3TsK01c2ZvQw0byvxuQU0r1lM0qJO7wW0kRIMdDTtXEdzi4VIh+EoIHm0mWtAtpCixlabgn83fKTI7anJe9ST7WIK1DMGpQmYeA58ImV6ezOGOzK2Kgq01pd60cKWiUi9Lievb/0vIDPHQ05Kzt4ddPckQBQtoaurjyHnek/nKzpQLrVgKPjIkh2v4uyezpv+Xoo7fPFXaGFp1vaLKxQ4uUpQQS5VuQs7BCq4xRJv7fwpVvvFEB3j+620haOuocqMhWd6TTPAEx+mdFNGHdranFe95WrWmIvlY4F1Dle2ECgc6cto7SryuqGGGha0tFQ5V53migUKmg6XKAo4qS3mik+0OZpAhOLeZKicacgaYcyx5hypYQE02ZA4xi/pNhOQxR4klNKyqacj+mpxnLTnnGSo85++3ZCZq6lrZkXlGEX3o+C9FieccJbZWVFjC0Yo1FZnJhoYMFoI1hEZ9r6hwg75HwzBNhbZCdJEfJwTPGzJvaKImw1yYX1HDAmpXR+ZJQ/SmgqMNVQb5vgamGwLtt7VwvP7Qk1xpiM5x5Cyv93E06MZmgs0Nya2azIKOYKCGBQQW97RmhKNKF02JZqHEJ4o58qp7X5EcZmc56trXEqzjCBZ1MFGR87Ql2tSTs6CGxS05PTzRQorkbw7aKoKXFDXsYW42VJih/q+FP2BdTzDTwVqOYB13liM50vG7wy28qagyuIXMeQI/Oqq8bcn5wJI50xH00CRntyfpL1T4hydYpoXgNiFzoIUTDZnLNRzh4TBHwbYGDvZkxmlyJloyr6tRihpeUG94GnKtIznREF0tzJG/OOr73JBcrSh1k6WuTprgLU+mnSGnv6Zge0NNz+kTDdH8nuAuTdJDCNb21LCiIuqlYbqGzT3RAoZofQfjFazkqeNWdYaGvYTM001EW2oKPvVk1ldUGSgUtHFwjKM1h9jnFcmy5lChoLNaQMGGDsYbKixlaMBmmsx1QjCfflwTfO/gckW0ruZ3jugKR3R5W9hGUWqCgxuFgsuaCHorotGKzGaeZB9DMsaTnKCpMtwTvOzhYk0rdrArKCqcaWmVk1+F372ur1YkKxgatI8Qfe1gIX9wE9FgS8ESmuABIXnRUbCapcKe+nO7slClSZFzpV/LkLncEb1qiO42fS3R855Su2mCLh62t1SYZZYVmKwIHjREF2uihTzB20JOkz7dkxzYQnK0UOU494wh+VWRc6Un2kpTaVgLDFEkJ/uhzRcI0YKGgpGWOlocBU/a4fKoJ/pEaNV6jip3+Es9VXY078rGnmAdf7t9ylPXS34RBSuYPs1UecZTU78WanhBCHpZ5sAoTz0LGZKjPf9TRypqWEiTvOFglL1fCEY3wY/++rbk7C8bWebA6p6om6PgOL2kp44TFJlVNBXae2rqqdZztOJpT87GQsE9jqCPIe9VReZuQ/CIgacsyZdCpIScSYqcZk8r+nsyCzhyfhOqHGOIvrLknC8wTpFcaYiGC/RU1NRbUeUpocQOnkRpGOrIOcNRx+1uA0UrzhSSt+VyS3SJpnFWkzNDqOFGIWcfR86DnmARTQ1HKIL33ExPiemeOhYSSjzlSUZZuE4TveoJLnBUOFof6KiysCbnAEcZgcUNTDOwkqWu3RWtmGpZwlHhJENdZ3miGz0lJlsKnjbwqSHQjpxnFDlTLLwqJPMZMjd7KrzkSG7VsxXBZE+F8YZkb01Oe00yyRK9psh5SYh29ySPKBo2ylNht7ZkZnsKenjKNJu9PNEyZpaCHv4Kt6RQsLvAVp7M9kIimmCUwGeWqLMmGuIotYMmWNpSahkhZw9FqZsVnKJhsjAHvtHMsTM9fCI06Dx/u3vfUXCqfsKRc4oFY2jMsoo/7DJDwZ1CsIKnJu+J9ldkpmiCxQx1rWjI+T9FwcWWzOuaYH0Hj7klNRVWEQpmaqosakiGNTFHdjS/qnUdmf0NJW5xsL0HhimCCZZSRzmSPTXJQ4aaztAwtZnoabebJ+htCaZ7Cm535ByoqXKbX1WRc4Eh2MkRXWzImVc96Cj4VdOKVxR84VdQsIUM8Psoou2byVHyZFuq7O8otbSQ2UAoeEWTudATLGSpZzVLlXVkPU2Jc+27lsw2jmg5T5VhbeE3BT083K9WsTTkFU/Osi0rC5lRlpwRHUiesNS0sOvmqGML1aRbPAxTJD9ZKtxuob+hhl8cwYGWpJ8nub7t5p6coYbMovZ1BTdaKn1jYD6h4GFDNFyT/Kqe1XCXphXHOKLZmuRSRdBPEfVUXQzJm5YGPGGJdvAEr7hHNdGZnuBvrpciGmopOLf5N0uVMy0FfYToJk90uUCbJupaVpO53UJXR2bVpoU00V2KOo4zMFrBd0Jtz2pa0clT5Q5L8IpQ177mWQejPMEJhuQjS10ref6HHjdEhy1P1EYR7GtO0uSsKJQYLiTnG1rVScj5lyazpqWGl5uBbRWl7m6ixGOOnEsMJR7z8J0n6KMnCdxhiNYQCoZ6CmYLnO8omC3MkW3bktlPmEt/VQQHejL3+dOE5FlPdK/Mq8hZxxJtLyRrepLThYKbLZxkSb5W52vYxNOaOxUF0yxMUPwBTYqCzy01XayYK0sJyWBLqX0MwU5CzoymRzV0EjjeUeLgDpTo6ij42ZAzvD01dHUUTPLU96MdLbBME8nFBn7zJCMtJcZokn8YoqU0FS5WFKyniHobguMcmW8N0XkWZjkyN3hqOMtS08r+/xTBwpZSZ3qiVRX8SzMHHjfUNFjgHEPmY9PL3ykEzxkSre/1ZD6z/NuznuB0RcE1TWTm9zRgfUWVJiG6yrzgmWPXC8EAR4Wxhlad0ZbgQyEz3pG5RVEwwDJH2mgKpjcTiCOzn1lfUWANFbZ2BA8balnEweJC9J0iuaeZoI+ippFCztEKVvckR2iice1JvhVytrQwUAZpgsubCPaU7xUe9vWnaOpaSBEspalykhC9bUlOMpT42ZHca6hyrqKmw/wMR8H5ZmdFoBVJb03O4UL0tSNnvIeRmkrLWqrs78gcrEn2tpcboh0UPOW3UUR9PMk4T4nnNKWmCjlrefhCwxRNztfmIQVdDElvS4m1/WuOujoZCs5XVOjtKPGokJzsYCtFYoWonSPT21DheU/wWhM19FcElwqNGOsp9Q8N/cwXaiND1MmeL1Q5XROtYYgGeFq1aTMsoMmcrKjQrOFQTQ1fmBYhmW6o8Jkjc7iDJRTBIo5kgJD5yMEYA3srCg7VFKwiVJkmRCc5ohGOKhsYMn/XBLdo5taZjlb9YAlGWRimqbCsoY7HFAXLa5I1HPRxMMsQDHFkWtRNniqT9UEeNjcE7RUlrCJ4R2CSJuqlKHWvJXjAUNcITYkenuBRB84TbeepcqTj3zZyFJzgYQdHnqfgI0ddUwS6GqWpsKWhjq9cV0vBAEMN2znq+EBfIWT+pClYw5xsTlJU6GeIBsjGmmANTzJZiIYpgrM0Oa8ZMjd7NP87jxhqGOhJlnQtjuQpB+8aEE00wZFznSJPyHxgH3HkPOsJFvYk8zqCHzTs1BYOa4J3PFU+UVRZxlHDM4YavlNUuMoRveiZA2d7grMNc2g+RbSCEKzmgYsUmWmazFJyoiOZ4KnyhKOGRzWJa0+moyV4TVHDzn51Awtqaphfk/lRQ08FX1iiqxTB/kLwd0VynKfEvI6cd4XMV5bMhZ7gZUWVzYQ6Nm2BYzxJbw3bGthEUUMfgbGeorae6DxHtJoZ6alhZ0+ytiVoK1R4z5PTrOECT/SugseEOlb1MMNR4VRNcJy+V1Hg9ONClSZFZjdHlc6W6FBLdJja2MC5hhpu0DBYEY1TFGwiFAxRRCsYkiM9JRb0JNMVkW6CZYT/2EiTGWmo8k+h4FhDNE7BvppoTSFnmCV5xZKzvcCdDo7VVPnIU+I+Rc68juApC90MwcFCsJ5hDqxgScYKreruyQwTqrzoqDCmhWi4IbhB0Yrt3RGa6GfDv52rKXWhh28dyZaWUvcZeMTBaZoSGyiCtRU5J8iviioHaErs7Jkj61syVzTTgOcUOQ8buFBTYWdL5g3T4qlpe0+wvD63heAXRfCCIed9RbCsp2CiI7raUOYOTU13N8PNHvpaGvayo4a3LLT1lDrVEPT2zLUlheB1R+ZTRfKWJ+dcocLJfi11vyJ51lLqJ0WD7tRwryezjiV5W28uJO9qykzX8JDe2lHl/9oyBwa2UMfOngpXCixvKdXTk3wrsKmiVYdZIqsoWEERjbcUNDuiaQomGoIbFdEHmsyWnuR+IeriKDVLnlawlyNHKwKlSU631PKep8J4Q+ayjkSLKYLhalNHlYvttb6fHm0p6OApsZ4l2VfdqZkjuysy6ysKLlckf1KUutCTs39bmCgEyyoasIWlVaMF7mgmWtBT8Kol5xpH9IGllo8cJdopcvZ2sImlDmMIbtDk3KIpeNiS08lQw11NFPTwVFlPP6pJ2gvRfI7gQUfmNAtf6Gs0wQxDsKGlVBdF8rCa3jzdwMaGHOsItrZk7hAyOzpK9VS06j5F49b0VNGOOfKs3lDToMsMBe9ZWtHFEgxTJLs7qrygKZjUnmCYoeAqeU6jqWuLJup4WghOdvCYJnrSkSzoyRkm5M2StQwVltPkfCAk58tET/CSg+8MUecmotMEnhBKfWBIZsg2ihruMJQaoIm+tkTLKEqspMh00w95gvFCQRtDwTT1gVDDSEVdlwqZfxoQRbK0g+tbiBZxzKlpnpypejdDwTaeOvorMk/IJE10h9CqRe28hhLbe0pMsdSwv4ZbhKivo2BjDWfL8UKJgeavwlwb5KlwhyE4u4XkGE2ytZCznKLCDZZq42VzT8HLCrpruFbIfOIINmh/qCdZ1ZBc65kLHR1Bkyf5zn6pN3SvGKIlFNGplhrO9QSXanLOMQTLCa0YJCRrCZm/CZmrLTm7WzCK4GJDiWUdFeYx1LCFg3NMd0XmCuF3Y5rITLDUsYS9zoHVzwnJoYpSTQoObyEzr4cFBNqYTopoaU/wkyLZ2lPhX/5Y95ulxGTV7KjhWrOZgl8MyUUafjYraNjNU1N3IWcjT5WzWqjwtoarHSUObGYO3GCJZpsBlnJGPd6ZYLyl1GdCA2625IwwJDP8GUKymbzuyPlZlvTUsaUh5zFDhRWFzPKKZLAlWdcQbObgF9tOqOsmB1dqcqYJmWstFbZRRI9poolmqiLnU0POvxScpah2iSL5UJNzgScY5+AuIbpO0YD3NCW+dLMszFSdFCWGqG6eVq2uYVNDdICGD6W7EPRWZEY5gpsE9rUkS3mijzzJnm6UpUFXG1hCUeVoS5WfNcFpblELL2qqrCvMvRfd45oalvKU2tiQ6ePJOVMRXase9iTtLJztPxJKLWpo2CRDcJwn2sWSLKIO1WQWNTCvpVUvOZhgSC40JD0dOctaSqzkCRbXsKlb11Oip6PCJ0IwSJM31j3akRxlP7Rwn6aGaUL0qiLnJkvB3xWZ2+Q1TfCwpQH3G0o92UzmX4o/oJNQMMSQc547wVHhdk+VCw01DFYEnTxzZKAm74QmeNNR1w6WzEhNK15VJzuCdxQ53dRUDws5KvwgBMOEgpcVNe0hZI6RXT1Jd0cyj5nsaEAHgVmGaJIlWdsc5Ui2ElrRR6jrRAttNMEAIWrTDFubkZaok7/AkzfIwfuWVq0jHzuCK4QabtLUMVPB3kJ0oyHTSVFlqMALilJf2Rf8k5aaHtMfayocLBS8L89oKoxpJvnAkDPa0qp5DAUTHKWmCcnthlou8iCKaFFLHWcINd1nyIwXqrSxMNmSs6KmoL2QrKuWtlQ5V0120xQ5vRyZS1rgFkWwhiOwiuQbR0OOVhQM9iS3tiXp4RawRPMp5tDletOOBL95MpM01dZTBM9pkn5qF010rIeHFcFZhmSGpYpTsI6nwhqe5C9ynhlpp5ophuRb6WcJFldkVnVEwwxVfrVkvnWUuNLCg5bgboFHPDlDPDmnK7hUrWiIbjadDclujlZcaokOFup4Ri1kacV6jmrrK1hN9bGwpKEBQ4Q6DvIUXOmo6U5LqQM6EPyiKNjVkPnJkDPNEaxhiFay5ExW1NXVUGqcpYYdPcGiCq7z/TSlbhL4pplWXKd7NZO5QQFrefhRQW/NHOsqcIglc4UhWklR8K0QzbAw08CBDnpbgqXdeD/QUsM4RZXDFBW6WJKe/mFPdH0LtBgiq57wFLzlyQzz82qYx5D5WJP5yVJDW01BfyHnS6HKO/reZqId1WGa4Hkh2kWodJ8i6KoIPlAj2hPt76CzXsVR6koPRzWTfKqIentatYpQw2me4AA3y1Kind3SwoOKZDcFXTwl9tWU6mfgRk9d71sKtlNwrjnYw5tC5n5LdKiGry3JKNlHEd3oaMCFHrazBPMp/uNJ+V7IudcSbeOIdjUEdwl0VHCOZo5t6YluEuaC9mQeMgSfOyKnYGFHcIeQ84yQWbuJYJpZw5CzglDH7gKnWqqM9ZTaXcN0TeYhR84eQtJT76JJ1lREe7WnnvsMmRc9FQ7SBBM9mV3lCUdmHk/S2RAMt0QjFNFqQpWjDPQ01DXWUdDBkXziKPjGEP3VP+zIWU2t7im41FOloyWzn/L6dkUy3VLDaZ6appgDLHPjJEsyvJngWEPUyVBiAaHCTEXwrLvSEbV1e1gKJniicWorC1MUrVjB3uDhJE/wgSOzk1DXpk0k73qCM8xw2UvD5kJmDUfOomqMpWCkJRlvKXGmoeBm18USjVIk04SClxTB6YrgLAPLWYK9HLUt5cmc0vYES8GnTeRc6skZbQkWdxRsIcyBRzx1DbTk9FbU0caTPOgJHhJKnOGIVhQqvKmo0llRw9sabrZkDtdg3PqaKi9oatjY8B+G371paMg6+mZFNNtQ04mWBq3rYLOmtWWQp8KJnpy9DdFensyjdqZ+yY40VJlH8wcdLzC8PZnvHMFUTZUrDTkLyQaGus5X5LzpYAf3i+e/ZlhqGqWhh6Ou6xTR9Z6oi5AZZtp7Mj2EEm8oSpxiYZCHU/1fbGdNNNRRoZMhmilEb2gqHOEJDtXkHK/JnG6IrvbPCwV3NhONVdS1thBMs1T4QOBcTWa2IzhMk2nW5Kyn9tXUtpv9RsG2msxk+ZsQzRQacJncpgke0+T8y5Fzj8BiGo7XlJjaTIlpQs7KFjpqGnKuoyEPeIKnFMkZHvopgh81ySxNFWvJWcKRs70j2FOT012IllEEO1n4pD1513Yg2ssQPOThOkvyrqHUdEXOSEsihmBbTbKX1kLBPWqWkLOqJbjB3GBIZmoa8qWl4CG/iZ7oiA72ZL7TJNeZUY7kFQftDcHHluBzRbCegzMtrRjVQpX2lgoPKKLJAkcbMl01XK2p7yhL8pCBbQ3BN2avJgKvttcrWDK3CiUOVxQ8ZP+pqXKyIxnmBymCg5vJjNfkPK4+c8cIfK8ocVt7kmfd/I5SR1hKvCzUtb+lhgc00ZaO6CyhIQP1Uv4yIZjload72PXX0OIJvnFU+0Zf6MhsJwTfW0r0UwQfW4LNLZl5HK261JCZ4qnBaAreVAS3WrjV0LBnNDUNNDToCEeFfwgcb4gOEqLRhirWkexrCEYKVV711DLYEE1XBEsp5tpTGjorkomKYF9FDXv7fR3BGwbettSxnyL53MBPjsxDZjMh+VUW9NRxq1DhVk+FSxQcaGjV9Pawv6eGByw5qzoy7xk4RsOShqjJwWKe/1pEEfzkobeD/dQJmpqedcyBTy2sr4nGNRH0c0SPWTLrqAc0OQcb/gemKgqucQT7ySWKCn2EUotoCvpZct7RO2sy/QW0IWcXd7pQRQyZVwT2USRO87uhjioTLKV2brpMUcMQRbKH/N2T+UlTpaMls6cmc6CCNy3JdYYSUzzJQ4oSD3oKLncULOiJvjBEC2oqnCJkJluCYy2ZQ5so9YYlZ1VLlQU1mXEW1jZERwj/MUSRc24TdexlqLKfQBtDTScJUV8FszXBEY5ktpD5Ur9hYB4Nb1iikw3JoYpkKX+RodRKFt53MMuRnKSpY31PwYaGaILh3wxJGz9TkTPEETxoCWZrgvOlmyMzxFEwVJE5xZKzvyJ4WxEc16Gd4Xe3Weq4XH2jKRikqOkGQ87hQnC7wBmGYLAnesX3M+S87eFATauuN+Qcrh7xIxXJbUIdMw3JGE3ylCWzrieaqCn4zhGM19TQ3z1oH1AX+pWEqIc7wNGAkULBo/ZxRaV9NNyh4Br3rCHZzbzmSfawBL0dNRwpW1kK9mxPXR9povcdrGSZK9c2k0xwFGzjuniCtRSZCZ6ccZ7gaktmgAOtKbG/JnOkJrjcQTdFMsxRQ2cLY3WTIrlCw1eWKn8R6pvt4GFDso3QoL4a3nLk3G6JrtME3dSenpx7PNFTmga0EaJTLQ061sEeQoWXhSo9LTXsaSjoJQRXeZLtDclbCrYzfzHHeaKjHCVOUkQHO3JeEepr56mhiyaYYKjjNU+Fed1wS5VlhWSqI/hYUdDOkaxiKehoyOnrCV5yBHtbWFqTHCCwtpDcYolesVR5yUzTZBb3RNMd0d6WP+SvhuBmRcGxnuQzT95IC285cr41cLGQ6aJJhmi4TMGempxeimBRQw1tFKV+8jd6KuzoSTqqDxzRtpZkurvKEHxlqXKRIjjfUNNXQsNOsRScoWFLT+YeRZVD3GRN0MdQcKqQjHDMrdGGVu3iYJpQx3WGUvfbmxwFfR20WBq0oYY7LMFhhgYtr8jpaEnaOzjawWWaTP8mMr0t/EPDPoqcnxTBI5o58L7uoWnMrpoqPwgVrlAUWE+V+TQl9rawoyP6QGAlQw2TPRX+YSkxyBC8Z6jhHkXBgQL7WII3DVFnRfCrBfxewv9D6xsyjys4VkhWb9pUU627JllV0YDNHMku/ldNMMXDEo4aFnAkk4U6frNEU4XgZUPmEKHUl44KrzmYamjAbh0JFvGnaTLPu1s9jPCwjFpYiN7z1DTOk/nc07CfDFzmCf7i+bfNHXhDtLeBXzTBT5rkMvWOIxpl4EMh2LGJBu2syDnAEx2naEhHDWMMzPZEhygyS1mS5RTJr5ZkoKbEUoYqr2kqdDUE8ztK7OaIntJkFrIECwv8LJTaVx5XJE86go8dFeZ3FN3rjabCAYpoYEeC9zzJVULBbmZhDyd7ko09ydpNZ3nm2Kee4FPPXHnYEF1nqOFEC08LUVcDvYXkJHW8gTaKCk9YGOeIJhqiE4ToPEepdp7IWFjdwnWaufGMwJJCMtUTTBBK9BGCOy2tGGrJTHIwyEOzp6aPzNMOtlZkDvcEWpP5SVNhfkvDxhmSazTJXYrM9U1E0xwFVwqZQwzJxw6+kGGGUj2FglGGmnb1/G51udRSMNlTw6GGnCcUwVcOpmsqTHa06o72sw1RL02p9z0VbnMLOaIX3QKaYKSCFQzBKEUNHTSc48k53RH9wxGMtpQa5KjjW0W0n6XCCCG4yxNNdhQ4R4l1Ff+2sSd6UFHiIEOyqqFgT01mEUMD+joy75jPhOA+oVVLm309FR4yVOlp4RhLiScNmSmaYF5Pw0STrOIoWMSR2UkRXOMp+M4SHW8o8Zoi6OZgjKOaFar8zZDzkWzvKOjkKBjmCXby8JahhjXULY4KlzgKLvAwxVGhvyd4zxB1d9T0piazmKLCVZY5sKiD0y2ZSYrkUEPUbIk+dlQ4SJHTR50k1DPaUWIdTZW9NJwnJMOECgd7ou/MnppMJ02O1VT4Wsh85MnZzcFTngpXGKo84qmwgKbCL/orR/SzJ2crA+t6Mp94KvxJUeIbT3CQu1uIdlQEOzlKfS3UMcrTiFmOuroocrZrT2AcmamOKg8YomeEKm/rlT2sociMaybaUlFhuqHCM2qIJ+rg4EcDFymiDSxzaHdPcpE62pD5kyM5SBMoA1PaUtfIthS85ig1VPiPPYXgYEMNk4Qq7TXBgo7oT57gPUdwgCHzhIVFPFU6OYJzHAX9m5oNrVjeE61miDrqQ4VSa1oiURTsKHC0IfjNwU2WzK6eqK8jWln4g15TVBnqmDteCJ501PGAocJhhqjZdtBEB6lnhLreFJKxmlKbeGrqLiSThVIbCdGzloasa6lpMQXHCME2boLpJgT7yWaemu6wBONbqGNVRS0PKIL7LckbjmQtR7K8I5qtqel+T/ChJTNIKLjdUMNIRyvOEko9YYl2cwQveBikCNawJKcLBbc7+JM92mysNvd/Fqp8a0k6CNEe7cnZrxlW0wQXaXjaktnRwNOGZKYiONwS7a1JVheq3WgJHlQUGKHKmp4KAxXR/ULURcNgoa4zhKSLpZR3kxRRb0NmD0OFn+UCS7CzI1nbP6+o4x47QZE5xRCt3ZagnYcvmpYQktXdk5YKXTzBC57kKEe0VVuiSYqapssMS3C9p2CKkHOg8B8Pa8p5atrIw3qezIWanMGa5HRDNF6RM9wcacl0N+Q8Z8hsIkSnaIIdHRUOEebAPy1zbCkhM062FCJtif7PU+UtoVXzWKqM1PxXO8cfdruhFQ/a6x3JKYagvVDhQEtNiyiiSQ7OsuRsZUku0CRNDs4Sog6KKjsZgk2bYJqijgsEenoKeniinRXBn/U3lgpPdyDZynQx8IiioMnCep5Ky8mjGs6Wty0l1hUQTcNWswS3WRp2kCNZwJG8omG8JphPUaFbC8lEfabwP7VtM9yoaNCAjpR41VNhrD9LkbN722v0CoZMByFzhaW+MyzRYEWFDQwN2M4/JiT76PuljT3VU/A36eaIThb+R9oZGOAJ9tewkgGvqOMNRWYjT/Cwu99Q8LqDE4TgbLWxJ1jaDDAERsFOFrobgjUsBScaguXU8kKm2RL19tRypSHnHNlHiIZqgufs4opgQdVdwxBNNFBR6kVFqb8ogimOzB6a6HTzrlDHEpYaxjiiA4TMQobkDg2vejjfwJGWmnbVFAw3H3hq2NyQfG7hz4aC+w3BbwbesG0swYayvpAs6++Ri1Vfzx93mFChvyN5xVHTS+0p9aqCAxyZ6ZacZyw5+7uuQkFPR9DDk9NOiE7X1PCYJVjVUqq7JlrHwWALF5nfHNGjApdpqgzx5OwilDhCiDYTgnc9waGW4BdLNNUQvOtpzDOWHDH8D7TR/A/85KljEQu3NREc4Pl/6B1Hhc8Umb5CsKMmGC9EPcxoT2amwHNCmeOEnOPbklnMkbOgIvO5UMOpQrS9UGVdt6iH/fURjhI/WOpaW9OKLYRod6HCUEdOX000wpDZQ6hwg6LgZfOqo1RfT/CrJzjekXOGhpc1VW71ZLbXyyp+93ILbC1kPtIEYx0FIx1VDrLoVzXRKRYWk809yYlC9ImcrinxtabKnzRJk3lAU1OLEN1j2zrYzr2myHRXJFf4h4QKT1qSTzTB5+ZNTzTRkAxX8FcLV2uS8eoQQ2aAkFzvCM72sJIcJET3WPjRk5wi32uSS9rfZajpWEvj9hW42F4o5NytSXYy8IKHay10VYdrcl4SkqscrXpMwyGOgtkajheSxdQqmpxP1L3t4R5PqasFnrQEjytq6qgp9Y09Qx9o4S1FzhUCn1kyHSzBWLemoSGvOqLNhZyBjmCaAUYpMgt4Ck7wBBMMwWKWgjsUwTaGVsxWC1mYoKiyqqeGKYqonSIRQ3KIkHO0pmAxTdBHkbOvfllfr+AA+7gnc50huVKYK393FOyg7rbPO/izI7hE4CnHHHnJ0ogNPRUGeUpsrZZTBJcrovUcJe51BPsr6GkJdhCCsZ6aTtMEb2pqWkqeVtDXE/QVggsU/Nl86d9RMF3DxvZTA58agu810RWawCiSzzXBeU3MMW9oyJUedvNEvQyNu1f10BSMddR1vaLCYpYa/mGocLSiYDcLbQz8aMn5iyF4xBNMs1P0QEOV7o5gaWGuzSeLue4tt3ro7y4Tgm4G/mopdZgl6q0o6KzJWE3mMksNr3r+a6CbT8g5wZNzT9O7fi/zpaOmnz3BRoqos+tv9zMbdpxsqDBOEewtJLt7cg5wtKKbvldpSzRRCD43VFheCI7yZLppggMVBS/KMAdHODJvOwq2NQSbKKKPLdFWQs7Fqo+mpl01JXYRgq8dnGLhTiFzqmWsUMdpllZdbKlyvSdYxhI9YghOtxR8LgSLWHK62mGGVoxzBE8LNWzqH9CUesQzFy5RQzTc56mhi6fgXEWwpKfE5Z7M05ZgZUPmo6auiv8YKzDYwWBLMErIbKHJvOwIrvEdhOBcQ9JdU1NHQ7CXn2XIDFBKU2WAgcX9UAUzDXWd5alwuyJ41Z9rjKLCL4aCp4WarhPm2rH+SaHUYE001JDZ2ZAzXPjdMpZWvC9wmqIB2lLhQ01D5jO06hghWMndbM7yRJMsoCj1vYbnFQVrW9jak3OlEJ3s/96+p33dEPRV5GxiqaGjIthUU6FFEZyqCa5qJrpBdzSw95IUnOPIrCUUjRZQFrbw5PR0R1qiYx3cb6nrWUMrBmmiBQxVHtTew5ICP/ip6g4hed/Akob/32wvBHsIOX83cI8hGeNeNPCIkPmXe8fPKx84OMSRM1MTdXSwjCZ4S30jVGhvqTRak/OVhgGazHuOCud5onEO1lJr6ecVyaOK6H7zqlBlIaHE0oroCgfvGJIdPcmfLNGLjpz7hZwZQpUbFME0A1cIJa7VNORkgfsMBatbKgwwJM9bSvQXeNOvbIjelg6WWvo5kvbKaJJNHexkKNHL9xRyFlH8Ti2riB5wVPhUk7nGkJnoCe428LR/wRGdYIlmWebCyxou1rCk4g/ShugBDX0V0ZQWkh0dOVsagkM0yV6OoLd5ye+pRlsCr0n+KiQrGuq5yJDzrTAXHtLUMduTDBVKrSm3eHL+6ijxhFDX9Z5gVU/wliHYTMiMFpKLNMEywu80wd3meoFmt6VbRMPenhrOc6DVe4pgXU8DnnHakLOIIrlF4FZPIw6R+zxBP0dyq6OOZ4Q5sLKCcz084ok+VsMMyQhNZmmBgX5xIXOEJTmi7VsGTvMTNdHHhpzdbE8Du2oKxgvBqQKdDDnTFOylCFaxR1syz2iqrOI/FEpNc3C6f11/7+ASS6l2inq2ciTrCCzgyemrCL5SVPjQkdPZUmGy2c9Sw9FtR1sS30RmsKPCS4rkIC/2U0MduwucYolGaPjKEyhzmiPYXagyWbYz8LWBDdzRimAXzxx4z8K9hpzlhLq+NiQ97HuKorMUfK/OVvC2JfiHUPCQI/q7J2gjK+tTDNxkCc4TMssqCs4TGtLVwQihyoAWgj9bosU80XGW6Ac9TJGziaUh5+hnFcHOnlaM1iRn29NaqGENTTTSUHCH2tWTeV0osUhH6psuVLjRUmGWhm6OZEshGeNowABHcJ2Bpy2ZszRcKkRXd2QuKVEeXnbfaEq825FguqfgfE2whlChSRMdron+LATTPQ2Z369t4B9C5gs/ylzv+CMmepIDPclFQl13W0rspPd1JOcbghGOEutqCv5qacURQl3dDKyvyJlqKXGPgcM9FfawJAMVmdcspcYKOZc4GjDYkFlK05olNMHyHn4zFNykyOxt99RkHlfwmiHo60l2EKI+mhreEKp080Tbug08BVPcgoqC5zWt+NLDTZ7oNSF51N1qie7Va3uCCwyZbkINf/NED6jzOsBdZjFN8oqG3wxVunqCSYYKf3EdhJyf9YWGf7tRU2oH3VHgPr1fe5J9hOgHd7xQ0y7qBwXr23aGErP0cm64JVjZwsOGqL+mhNgZmhJLW2oY4UhedsyBgzrCKrq7BmcpNVhR6jBPq64Vgi+kn6XE68pp8J5/+0wRHGOpsKenQn9DZntPzjRLZpDAdD2fnSgkG9tmIXnUwQ6WVighs7Yi2MxQ0N3CqYaCXkJ0oyOztMDJjmSSpcpvlrk0RMMOjmArQ04PRV1DO1FwhCVaUVPpKUM03JK5SxPsIWRu8/CGHi8UHChiqGFDTbSRJWeYUDDcH6vJWUxR4k1FXbMUwV6e4AJFXS8oMqsZKqzvYQ9DDQdZckY4aGsIhtlubbd2r3j4QBMoTamdPZk7O/Bf62lacZwneNjQoGcdVU7zJOd7ghsUHOkosagic6cnWc8+4gg285R6zZP5s1/LUbCKIznTwK36PkdwlOrl4U1LwfdCCa+IrvFkmgw1PCAUXKWo0sURXWcI2muKJlgyFzhynCY4RBOsqCjoI1R5zREco0n2Vt09BQtYSizgKNHfUmUrQ5UOCh51BFcLmY7umhYqXKQomOop8bUnWNNQcIiBcYaC6xzMNOS8JQQfeqKBmmglB+97ok/lfk3ygaHSyZaCRTzRxQo6GzLfa2jWBPepw+UmT7SQEJyiyRkhBLMVOfcoMjcK0eZChfUNzFAUzCsEN5vP/X1uP/n/aoMX+K+nw/Hjr/9xOo7j7Pju61tLcgvJpTWXNbfN5jLpi6VfCOviTktKlFusQixdEKWmEBUKNaIpjZRSSOXSgzaaKLdabrm1/9nZ+/f+vd/vz/v9+Xy+zZ7PRorYoZqyLrCwQdEAixxVOEXNNnjX2nUSRlkqGmWowk8lxR50JPy9Bo6qJXaXwNvREBvnThPEPrewryLhcAnj5WE15Fqi8W7R1sAuEu86S4ENikItFN4xkv9Af4nXSnUVcLiA9xzesFpivRRVeFKtsMRaKBhuSbjOELnAUtlSQUpXgdfB4Z1oSbnFEetbQ0IrAe+Y+pqnDcEJFj6S8LDZzZHwY4e3XONNlARraomNEt2bkvGsosA3ioyHm+6jCMbI59wqt4eeara28IzEmyPgoRaUOEDhTVdEJhmCoTWfC0p8aNkCp0oYqih2iqGi4yXeMkOsn4LdLLnmKfh/YogjNsPebeFGR4m9BJHLzB61XQ3BtpISfS2FugsK9FAtLWX1dCRcrCnUp44CNzuCowUZmxSRgYaE6Za0W2u/E7CVXCiI/UOR8aAm1+OSyE3mOUcwyc1zBBeoX1kiKy0Zfxck1Gsyulti11i83QTBF5Kg3pDQThFMVHiPSlK+0cSedng/VaS8bOZbtsBcTcZAR8JP5KeqQ1OYKAi20njdNNRpgnsU//K+JnaXJaGTomr7aYIphoRn9aeShJWKEq9LcozSF7QleEfDI5LYm5bgVkFkRwVDBCVu0DDIkGupo8TZBq+/pMQURYErJQmPKGKjNDkWOLx7Jd5QizdUweIaKrlP7SwJDhZvONjLkOsBBX9UpGxnydhXkfBLQ8IxgojQbLFnJf81JytSljclYYyEFyx0kVBvKWOFJmONpshGAcsduQY5giVNCV51eOdJYo/pLhbvM0uDHSevNKRcrKZIqnCtJeEsO95RoqcgGK4ocZcho1tTYtcZvH41pNQ7vA0WrhIfOSraIIntIAi+NXWCErdbkvrWwjRLrt0NKUdL6KSOscTOdMSOUtBHwL6OLA0vNSdynaWQEnCpIvKaIrJJEbvHkmuNhn6OjM8VkSGSqn1uYJCGHnq9I3aLhNME3t6GjIkO7xrNFumpyTNX/NrwX7CrIRiqqWijI9JO4d1iieykyfiposQIQ8YjjsjlBh6oHWbwRjgYJQn2NgSnNycmJAk3NiXhx44Sxykihxm8ybUwT1OVKySc7vi3OXVkdBJ4AyXBeksDXG0IhgtYY0lY5ahCD0ehborIk5aUWRJviMA7Xt5kyRjonrXENkm8yYqgs8VzgrJmClK20uMM3jRJ0FiQICQF9hdETlLQWRIb5ki6WDfWRPobvO6a4GP5mcOrNzDFELtTkONLh9dXE8xypEg7z8A9jkhrQ6Fhjlg/QVktJXxt4WXzT/03Q8IaQWSqIuEvloQ2mqC9Jfi7wRul4RX3pSPlzpoVlmCtI2jvKHCFhjcM3sN6lqF6HxnKelLjXWbwrpR4xzuCrTUZx2qq9oAh8p6ixCUGr78g8oyjRAtB5CZFwi80VerVpI0h+IeBxa6Zg6kWvpDHaioYYuEsRbDC3eOmC2JvGYLeioxGknL2UATNJN6hmtj1DlpLvDVmocYbrGCVJKOrg4X6DgddLA203BKMFngdJJFtFd7vJLm6KEpc5yjQrkk7M80SGe34X24nSex1Ra5Omgb71JKyg8SrU3i/kARKwWpH0kOGhKkObyfd0ZGjvyXlAkVZ4xRbYJ2irFMkFY1SwyWxr2oo4zlNiV+7zmaweFpT4kR3kaDAFW6xpSqzJay05FtYR4HmZhc9UxKbbfF2V8RG1MBmSaE+kmC6JnaRXK9gsiXhJHl/U0qM0WTcbyhwkYIvFGwjSbjfwhiJt8ZSQU+Bd5+marPMOkVkD0muxYLIfEuhh60x/J92itguihJSEMySVPQnTewnEm+620rTQEMsOfo4/kP/0ARvWjitlpSX7GxBgcMEsd3EEeYWvdytd+Saawi6aCIj1CkGb6Aj9rwhx16Cf3vAwFy5pyLhVonXzy51FDpdEblbkdJbUcEPDEFzQ8qNmhzzLTmmKWKbFCXeEuRabp6rxbvAtLF442QjQ+wEA9eL1xSR7Q0JXzlSHjJ4exq89yR0laScJ/FW6z4a73pFMEfDiRZvuvijIt86RaSFOl01riV2mD1UEvxGk/Geg5aWwGki1zgKPG9J2U8PEg8qYvMsZeytiTRXBMslCU8JSlxi8EabjwUldlDNLfzTUmCgxWsjqWCOHavYAqsknKFIO0yQ61VL5AVFxk6WhEaCAkdJgt9aSkzXlKNX2jEa79waYuc7gq0N3GDJGCBhoiTXUEPsdknCUE1CK0fwsiaylSF2uiDyO4XX3pFhNd7R4itFGc0k/ElBZwWvq+GC6szVeEoS/MZ+qylwpKNKv9Z469UOjqCjwlusicyTxG6VpNxcQ8IncoR4RhLbR+NdpGGmJWOcIzJGUuKPGpQg8rrG21dOMqQssJQ4RxH5jaUqnZuQ0F4Q+cjxLwPtpZbIAk3QTJHQWBE5S1BokoVtDd6lhqr9UpHSUxMcIYl9pojsb8h4SBOsMQcqvOWC2E8EVehqiJ1hrrAEbQxeK0NGZ0Gkq+guSRgniM23bIHVkqwx4hiHd7smaOyglyIyQuM978j4VS08J/A2G1KeMBRo4fBaSNhKUEZfQewVQ/C1I+MgfbEleEzCUw7mKXI0M3hd1EESVji8x5uQ41nxs1q4RMJCCXs7Iq9acpxn22oSDnQ/sJTxsCbHIYZiLyhY05TY0ZLIOQrGaSJDDN4t8pVaIrsqqFdEegtizc1iTew5Q4ayBDMUsQMkXocaYkc0hZua412siZ1rSXlR460zRJ5SlHGe5j801RLMlJTxtaOM3Q1pvxJ45zUlWFD7rsAbpfEm1JHxG0eh8w2R7QQVzBUw28FhFp5QZzq8t2rx2joqulYTWSuJdTYfWwqMFMcovFmSyJPNyLhE4E10pHzYjOC3huArRa571ZsGajQpQx38SBP5pyZB6lMU3khDnp0MBV51BE9o2E+TY5Ml2E8S7C0o6w1xvCZjf0HkVEHCzFoyNmqC+9wdcqN+Tp7jSDheE9ws8Y5V0NJCn2bk2tqSY4okdrEhx1iDN8cSudwepWmAGXKcJXK65H9to8jYQRH7SBF01ESUJdd0TayVInaWhLkOjlXE5irKGOnI6GSWGCJa482zBI9rCr0jyTVcEuzriC1vcr6mwFGSiqy5zMwxBH/TJHwjSPhL8+01kaaSUuMFKTcLEvaUePcrSmwn8DZrgikWb7CGPxkSjhQwrRk57tctmxLsb9sZvL9LSlyuSLlWkqOjwduo8b6Uv1DkmudIeFF2dHCgxVtk8dpIvHpBxhEOdhKk7OLIUSdJ+cSRY57B+0DgGUUlNfpthTfGkauzxrvTsUUaCVhlKeteTXCoJDCa2NOKhOmC4G1H8JBd4OBZReSRGkqcb/CO1PyLJTLB4j1q8JYaIutEjSLX8YKM+a6phdMsdLFUoV5RTm9JSkuDN8WcIon0NZMNZWh1q8C7SJEwV5HxrmnnTrf3KoJBlmCYI2ilSLlfEvlE4011NNgjgthzEua0oKK7JLE7HZHlEl60BLMVFewg4EWNt0ThrVNEVkkiTwpKXSWJzdRENgvKGq4IhjsiezgSFtsfCUq8qki5S1LRQeYQQ4nemmCkImWMw3tFUoUBZk4NOeZYEp4XRKTGa6wJjrWNHBVJR4m3FCnbuD6aak2WsMTh3SZImGCIPKNgsDpVwnsa70K31lCFJZYcwwSMFcQulGTsZuEaSdBXkPGZhu0FsdUO73RHjq8MPGGIfaGIbVTk6iuI3GFgucHrIQkmWSJdBd7BBu+uOryWAhY7+Lki9rK5wtEQzWwvtbqGhIMFwWRJsElsY4m9IIg9L6lCX0VklaPAYkfkZEGDnOWowlBJjtMUkcGK4Lg6EtoZInMUBVYLgn0UsdmCyCz7gIGHFfk+k1QwTh5We7A9x+IdJ6CvIkEagms0hR50eH9UnTQJ+2oiKyVlLFUE+8gBGu8MQ3CppUHesnjTHN4QB/UGPhCTHLFPHMFrCqa73gqObUJGa03wgbhHkrCfpEpzNLE7JDS25FMKhlhKKWKfCgqstLCPu1zBXy0J2ztwjtixBu8UTRn9LVtkmCN2iyFhtME70JHRQ1KVZXqKI/KNIKYMCYs1GUMEKbM1bKOI9LDXC7zbHS+bt+1MTWS9odA9DtrYtpbImQJ2VHh/lisEwaHqUk1kjKTAKknkBEXkbkdMGwq0dnhzLJF3NJH3JVwrqOB4Sca2hti75nmJN0WzxS6UxDYoEpxpa4htVlRjkYE7DZGzJVU72uC9IyhQL4i8YfGWSYLLNcHXloyz7QhNifmKSE9JgfGmuyLhc403Xm9vqcp6gXe3xuuv8F6VJNxkyTHEkHG2g0aKXL0MsXc1bGfgas2//dCONXiNLCX+5mB7eZIl1kHh7ajwpikyzlUUWOVOsjSQlsS+M0R+pPje/dzBXRZGO0rMtgQrLLG9VSu9n6CMXS3BhwYmSoIBhsjNBmZbgusE9BCPCP5triU4VhNbJfE+swSP27aayE8tuTpYYjtrYjMVGZdp2NpS1s6aBnKSHDsbKuplKbHM4a0wMFd/5/DmGyKrJSUaW4IBrqUhx0vyfzTBBLPIUcnZdrAkNsKR0sWRspumSns6Ch0v/qqIbBYUWKvPU/CFoyrDJGwSNFhbA/MlzKqjrO80hRbpKx0Jewsi/STftwGSlKc1JZyAzx05dhLEdnfQvhZOqiHWWEAHC7+30FuRcZUgaO5gpaIK+xsiHRUsqaPElTV40xQZQ107Q9BZE1nryDVGU9ZSQ47bmhBpLcYpUt7S+xuK/FiT8qKjwXYw5ypS2iuCv7q1gtgjhuBuB8LCFY5cUuCNtsQOFcT+4Ih9JX+k8Ea6v0iCIRZOtCT0Et00JW5UeC85Cg0ScK0k411HcG1zKtre3SeITBRk7WfwDhEvaYLTHP9le0m8By0JDwn4TlLW/aJOvGHxdjYUes+ScZigCkYQdNdEOhkiezgShqkx8ueKjI8lDfK2oNiOFvrZH1hS+tk7NV7nOmLHicGWEgubkXKdwdtZknCLJXaCpkrjZBtLZFsDP9CdxWsSr05Sxl6CMmoFbCOgryX40uDtamB7SVmXW4Ihlgpmq+00tBKUUa83WbjLUNkzDmY7cow1JDygyPGlhgGKYKz4vcV7QBNbJIgM11TUqZaMdwTeSguH6rOaw1JRKzaaGyxVm2EJ/uCIrVWUcZUkcp2grMsEjK+DMwS59jQk3Kd6SEq1d0S6uVmO4Bc1lDXTUcHjluCXEq+1OlBDj1pi9zgiXxnKuE0SqTXwhqbETW6RggMEnGl/q49UT2iCzgJvRwVXS2K/d6+ZkyUl7jawSVLit46EwxVljDZwoSQ20sDBihztHfk2yA8NVZghiXwrYHQdfKAOtzsayjhY9bY0yE2CWEeJ9xfzO423xhL5syS2TFJofO2pboHob0nY4GiAgRrvGQEDa/FWSsoaaYl0syRsEt3kWoH3B01shCXhTUWe9w3Bt44SC9QCh3eShQctwbaK2ApLroGCMlZrYqvlY3qYhM0aXpFkPOuoqJ3Dm6fxXrGwVF9gCWZagjPqznfkuMKQ8DPTQRO8ZqG1hPGKEm9IgpGW4DZDgTNriTxvFiq+Lz+0cKfp4wj6OCK9JSnzNSn9LFU7UhKZZMnYwcJ8s8yRsECScK4j5UOB95HFO0CzhY4xJxuCix0lDlEUeMdS6EZBkTsUkZ4K74dugyTXS7aNgL8aqjDfkCE0ZbwkCXpaWCKhl8P7VD5jxykivSyxyZrYERbe168LYu9ZYh86IkscgVLE7tWPKmJv11CgoyJltMEbrohtVAQfO4ImltiHEroYEs7RxAarVpY8AwXMcMReFOTYWe5iiLRQxJ5Q8DtJ8LQhWOhIeFESPGsILhbNDRljNbHzNRlTFbk2S3L0NOS6V1KFJYKUbSTcIIhM0wQ/s2TM0SRMNcQmSap3jCH4yhJZKSkwyRHpYYgsFeQ4U7xoCB7VVOExhXepo9ABBsYbvGWKXPME3lyH95YioZ0gssQRWWbI+FaSMkXijZXwgiTlYdPdkNLaETxlyDVIwqeaEus0aTcYcg0RVOkpR3CSJqIddK+90JCxzsDVloyrFd5ZAr4TBKfaWa6boEA7C7s6EpYaeFPjveooY72mjIccLHJ9HUwVlDhKkmutJDJBwnp1rvulJZggKDRfbXAkvC/4l3ozQOG9a8lxjx0i7nV4jSXc7vhe3OwIxjgSHjdEhhsif9YkPGlus3iLFDnWOFhtCZbJg0UbQcIaR67JjthoCyMEZRwhiXWyxO5QxI6w5NhT4U1WsJvDO60J34fW9hwzwlKij6ZAW9ne4L0s8C6XeBMEkd/LQy1VucBRot6QMlbivaBhoBgjqGiCJNhsqVp/S2SsG6DIONCR0dXhvWbJ+MRRZJkkuEjgDXJjFQW6SSL7GXK8Z2CZg7cVsbWGoKmEpzQ5elpiy8Ryg7dMkLLUEauzeO86CuwlSOlgYLojZWeJ9xM3S1PWfEfKl5ISLQ0MEKR8YOB2QfCxJBjrKPCN4f9MkaSsqoVXJBmP7EpFZ9UQfOoOFwSzBN4MQ8LsGrymlipcJQhmy0GaQjPqCHaXRwuCZwRbqK2Fg9wlClZqYicrIgMdZfxTQ0c7TBIbrChxmuzoKG8XRaSrIhhiyNFJkrC7oIAWMEOQa5aBekPCRknCo4IKPrYkvCDI8aYmY7WFtprgekcJZ3oLIqssCSMtFbQTJKwXYy3BY5oCh2iKPCpJOE+zRdpYgi6O2KmOAgvVCYaU4ySRek1sgyFhJ403QFHiVEmJHwtybO1gs8Hr5+BETQX3War0qZngYGgtVZtoqd6vFSk/UwdZElYqyjrF4HXUeFspIi9IGKf4j92pKGAdCYMVsbcV3kRF0N+R8LUd5PCsIGWoxDtBkCI0nKofdJQxT+LtZflvuc8Q3CjwWkq8KwUpHzkK/NmSsclCL0nseQdj5FRH5CNHSgtLiW80Of5HU9Hhlsga9bnBq3fEVltKfO5IaSTmGjjc4J0otcP7QsJUSQM8pEj5/wCuUuC2DWz8AAAAAElFTkSuQmCC"); -} diff --git a/shared/html/libs/codemirror/5.0.0/theme/base16-dark.css b/shared/html/libs/codemirror/5.0.0/theme/base16-dark.css deleted file mode 100644 index b009d2b..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/base16-dark.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Name: Base16 Default Dark - Author: Chris Kempson (http://chriskempson.com) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-base16-dark.CodeMirror {background: #151515; color: #e0e0e0;} -.cm-s-base16-dark div.CodeMirror-selected {background: #303030 !important;} -.cm-s-base16-dark.CodeMirror ::selection { background: rgba(48, 48, 48, .99); } -.cm-s-base16-dark.CodeMirror ::-moz-selection { background: rgba(48, 48, 48, .99); } -.cm-s-base16-dark .CodeMirror-gutters {background: #151515; border-right: 0px;} -.cm-s-base16-dark .CodeMirror-guttermarker { color: #ac4142; } -.cm-s-base16-dark .CodeMirror-guttermarker-subtle { color: #505050; } -.cm-s-base16-dark .CodeMirror-linenumber {color: #505050;} -.cm-s-base16-dark .CodeMirror-cursor {border-left: 1px solid #b0b0b0 !important;} - -.cm-s-base16-dark span.cm-comment {color: #8f5536;} -.cm-s-base16-dark span.cm-atom {color: #aa759f;} -.cm-s-base16-dark span.cm-number {color: #aa759f;} - -.cm-s-base16-dark span.cm-property, .cm-s-base16-dark span.cm-attribute {color: #90a959;} -.cm-s-base16-dark span.cm-keyword {color: #ac4142;} -.cm-s-base16-dark span.cm-string {color: #f4bf75;} - -.cm-s-base16-dark span.cm-variable {color: #90a959;} -.cm-s-base16-dark span.cm-variable-2 {color: #6a9fb5;} -.cm-s-base16-dark span.cm-def {color: #d28445;} -.cm-s-base16-dark span.cm-bracket {color: #e0e0e0;} -.cm-s-base16-dark span.cm-tag {color: #ac4142;} -.cm-s-base16-dark span.cm-link {color: #aa759f;} -.cm-s-base16-dark span.cm-error {background: #ac4142; color: #b0b0b0;} - -.cm-s-base16-dark .CodeMirror-activeline-background {background: #202020 !important;} -.cm-s-base16-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/base16-light.css b/shared/html/libs/codemirror/5.0.0/theme/base16-light.css deleted file mode 100644 index 15df6d3..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/base16-light.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Name: Base16 Default Light - Author: Chris Kempson (http://chriskempson.com) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-base16-light.CodeMirror {background: #f5f5f5; color: #202020;} -.cm-s-base16-light div.CodeMirror-selected {background: #e0e0e0 !important;} -.cm-s-base16-light.CodeMirror ::selection { background: #e0e0e0; } -.cm-s-base16-light.CodeMirror ::-moz-selection { background: #e0e0e0; } -.cm-s-base16-light .CodeMirror-gutters {background: #f5f5f5; border-right: 0px;} -.cm-s-base16-light .CodeMirror-guttermarker { color: #ac4142; } -.cm-s-base16-light .CodeMirror-guttermarker-subtle { color: #b0b0b0; } -.cm-s-base16-light .CodeMirror-linenumber {color: #b0b0b0;} -.cm-s-base16-light .CodeMirror-cursor {border-left: 1px solid #505050 !important;} - -.cm-s-base16-light span.cm-comment {color: #8f5536;} -.cm-s-base16-light span.cm-atom {color: #aa759f;} -.cm-s-base16-light span.cm-number {color: #aa759f;} - -.cm-s-base16-light span.cm-property, .cm-s-base16-light span.cm-attribute {color: #90a959;} -.cm-s-base16-light span.cm-keyword {color: #ac4142;} -.cm-s-base16-light span.cm-string {color: #f4bf75;} - -.cm-s-base16-light span.cm-variable {color: #90a959;} -.cm-s-base16-light span.cm-variable-2 {color: #6a9fb5;} -.cm-s-base16-light span.cm-def {color: #d28445;} -.cm-s-base16-light span.cm-bracket {color: #202020;} -.cm-s-base16-light span.cm-tag {color: #ac4142;} -.cm-s-base16-light span.cm-link {color: #aa759f;} -.cm-s-base16-light span.cm-error {background: #ac4142; color: #505050;} - -.cm-s-base16-light .CodeMirror-activeline-background {background: #DDDCDC !important;} -.cm-s-base16-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/blackboard.css b/shared/html/libs/codemirror/5.0.0/theme/blackboard.css deleted file mode 100644 index 02289b6..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/blackboard.css +++ /dev/null @@ -1,32 +0,0 @@ -/* Port of TextMate's Blackboard theme */ - -.cm-s-blackboard.CodeMirror { background: #0C1021; color: #F8F8F8; } -.cm-s-blackboard .CodeMirror-selected { background: #253B76 !important; } -.cm-s-blackboard.CodeMirror ::selection { background: rgba(37, 59, 118, .99); } -.cm-s-blackboard.CodeMirror ::-moz-selection { background: rgba(37, 59, 118, .99); } -.cm-s-blackboard .CodeMirror-gutters { background: #0C1021; border-right: 0; } -.cm-s-blackboard .CodeMirror-guttermarker { color: #FBDE2D; } -.cm-s-blackboard .CodeMirror-guttermarker-subtle { color: #888; } -.cm-s-blackboard .CodeMirror-linenumber { color: #888; } -.cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; } - -.cm-s-blackboard .cm-keyword { color: #FBDE2D; } -.cm-s-blackboard .cm-atom { color: #D8FA3C; } -.cm-s-blackboard .cm-number { color: #D8FA3C; } -.cm-s-blackboard .cm-def { color: #8DA6CE; } -.cm-s-blackboard .cm-variable { color: #FF6400; } -.cm-s-blackboard .cm-operator { color: #FBDE2D;} -.cm-s-blackboard .cm-comment { color: #AEAEAE; } -.cm-s-blackboard .cm-string { color: #61CE3C; } -.cm-s-blackboard .cm-string-2 { color: #61CE3C; } -.cm-s-blackboard .cm-meta { color: #D8FA3C; } -.cm-s-blackboard .cm-builtin { color: #8DA6CE; } -.cm-s-blackboard .cm-tag { color: #8DA6CE; } -.cm-s-blackboard .cm-attribute { color: #8DA6CE; } -.cm-s-blackboard .cm-header { color: #FF6400; } -.cm-s-blackboard .cm-hr { color: #AEAEAE; } -.cm-s-blackboard .cm-link { color: #8DA6CE; } -.cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; } - -.cm-s-blackboard .CodeMirror-activeline-background {background: #3C3636 !important;} -.cm-s-blackboard .CodeMirror-matchingbracket {outline:1px solid grey;color:white !important} \ No newline at end of file diff --git a/shared/html/libs/codemirror/5.0.0/theme/cobalt.css b/shared/html/libs/codemirror/5.0.0/theme/cobalt.css deleted file mode 100644 index 3915589..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/cobalt.css +++ /dev/null @@ -1,25 +0,0 @@ -.cm-s-cobalt.CodeMirror { background: #002240; color: white; } -.cm-s-cobalt div.CodeMirror-selected { background: #b36539 !important; } -.cm-s-cobalt.CodeMirror ::selection { background: rgba(179, 101, 57, .99); } -.cm-s-cobalt.CodeMirror ::-moz-selection { background: rgba(179, 101, 57, .99); } -.cm-s-cobalt .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; } -.cm-s-cobalt .CodeMirror-guttermarker { color: #ffee80; } -.cm-s-cobalt .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-cobalt .CodeMirror-linenumber { color: #d0d0d0; } -.cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-cobalt span.cm-comment { color: #08f; } -.cm-s-cobalt span.cm-atom { color: #845dc4; } -.cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; } -.cm-s-cobalt span.cm-keyword { color: #ffee80; } -.cm-s-cobalt span.cm-string { color: #3ad900; } -.cm-s-cobalt span.cm-meta { color: #ff9d00; } -.cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; } -.cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; } -.cm-s-cobalt span.cm-bracket { color: #d8d8d8; } -.cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; } -.cm-s-cobalt span.cm-link { color: #845dc4; } -.cm-s-cobalt span.cm-error { color: #9d1e15; } - -.cm-s-cobalt .CodeMirror-activeline-background {background: #002D57 !important;} -.cm-s-cobalt .CodeMirror-matchingbracket {outline:1px solid grey;color:white !important} diff --git a/shared/html/libs/codemirror/5.0.0/theme/colorforth.css b/shared/html/libs/codemirror/5.0.0/theme/colorforth.css deleted file mode 100644 index 73fbf80..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/colorforth.css +++ /dev/null @@ -1,33 +0,0 @@ -.cm-s-colorforth.CodeMirror { background: #000000; color: #f8f8f8; } -.cm-s-colorforth .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; } -.cm-s-colorforth .CodeMirror-guttermarker { color: #FFBD40; } -.cm-s-colorforth .CodeMirror-guttermarker-subtle { color: #78846f; } -.cm-s-colorforth .CodeMirror-linenumber { color: #bababa; } -.cm-s-colorforth .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-colorforth span.cm-comment { color: #ededed; } -.cm-s-colorforth span.cm-def { color: #ff1c1c; font-weight:bold; } -.cm-s-colorforth span.cm-keyword { color: #ffd900; } -.cm-s-colorforth span.cm-builtin { color: #00d95a; } -.cm-s-colorforth span.cm-variable { color: #73ff00; } -.cm-s-colorforth span.cm-string { color: #007bff; } -.cm-s-colorforth span.cm-number { color: #00c4ff; } -.cm-s-colorforth span.cm-atom { color: #606060; } - -.cm-s-colorforth span.cm-variable-2 { color: #EEE; } -.cm-s-colorforth span.cm-variable-3 { color: #DDD; } -.cm-s-colorforth span.cm-property {} -.cm-s-colorforth span.cm-operator {} - -.cm-s-colorforth span.cm-meta { color: yellow; } -.cm-s-colorforth span.cm-qualifier { color: #FFF700; } -.cm-s-colorforth span.cm-bracket { color: #cc7; } -.cm-s-colorforth span.cm-tag { color: #FFBD40; } -.cm-s-colorforth span.cm-attribute { color: #FFF700; } -.cm-s-colorforth span.cm-error { color: #f00; } - -.cm-s-colorforth .CodeMirror-selected { background: #333d53 !important; } - -.cm-s-colorforth span.cm-compilation { background: rgba(255, 255, 255, 0.12); } - -.cm-s-colorforth .CodeMirror-activeline-background {background: #253540 !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/eclipse.css b/shared/html/libs/codemirror/5.0.0/theme/eclipse.css deleted file mode 100644 index 317218e..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/eclipse.css +++ /dev/null @@ -1,23 +0,0 @@ -.cm-s-eclipse span.cm-meta {color: #FF1717;} -.cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; } -.cm-s-eclipse span.cm-atom {color: #219;} -.cm-s-eclipse span.cm-number {color: #164;} -.cm-s-eclipse span.cm-def {color: #00f;} -.cm-s-eclipse span.cm-variable {color: black;} -.cm-s-eclipse span.cm-variable-2 {color: #0000C0;} -.cm-s-eclipse span.cm-variable-3 {color: #0000C0;} -.cm-s-eclipse span.cm-property {color: black;} -.cm-s-eclipse span.cm-operator {color: black;} -.cm-s-eclipse span.cm-comment {color: #3F7F5F;} -.cm-s-eclipse span.cm-string {color: #2A00FF;} -.cm-s-eclipse span.cm-string-2 {color: #f50;} -.cm-s-eclipse span.cm-qualifier {color: #555;} -.cm-s-eclipse span.cm-builtin {color: #30a;} -.cm-s-eclipse span.cm-bracket {color: #cc7;} -.cm-s-eclipse span.cm-tag {color: #170;} -.cm-s-eclipse span.cm-attribute {color: #00c;} -.cm-s-eclipse span.cm-link {color: #219;} -.cm-s-eclipse span.cm-error {color: #f00;} - -.cm-s-eclipse .CodeMirror-activeline-background {background: #e8f2ff !important;} -.cm-s-eclipse .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/elegant.css b/shared/html/libs/codemirror/5.0.0/theme/elegant.css deleted file mode 100644 index dd7df7b..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/elegant.css +++ /dev/null @@ -1,13 +0,0 @@ -.cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;} -.cm-s-elegant span.cm-comment {color: #262; font-style: italic; line-height: 1em;} -.cm-s-elegant span.cm-meta {color: #555; font-style: italic; line-height: 1em;} -.cm-s-elegant span.cm-variable {color: black;} -.cm-s-elegant span.cm-variable-2 {color: #b11;} -.cm-s-elegant span.cm-qualifier {color: #555;} -.cm-s-elegant span.cm-keyword {color: #730;} -.cm-s-elegant span.cm-builtin {color: #30a;} -.cm-s-elegant span.cm-link {color: #762;} -.cm-s-elegant span.cm-error {background-color: #fdd;} - -.cm-s-elegant .CodeMirror-activeline-background {background: #e8f2ff !important;} -.cm-s-elegant .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/erlang-dark.css b/shared/html/libs/codemirror/5.0.0/theme/erlang-dark.css deleted file mode 100644 index 25c7e0a..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/erlang-dark.css +++ /dev/null @@ -1,34 +0,0 @@ -.cm-s-erlang-dark.CodeMirror { background: #002240; color: white; } -.cm-s-erlang-dark div.CodeMirror-selected { background: #b36539 !important; } -.cm-s-erlang-dark.CodeMirror ::selection { background: rgba(179, 101, 57, .99); } -.cm-s-erlang-dark.CodeMirror ::-moz-selection { background: rgba(179, 101, 57, .99); } -.cm-s-erlang-dark .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; } -.cm-s-erlang-dark .CodeMirror-guttermarker { color: white; } -.cm-s-erlang-dark .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-erlang-dark .CodeMirror-linenumber { color: #d0d0d0; } -.cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-erlang-dark span.cm-atom { color: #f133f1; } -.cm-s-erlang-dark span.cm-attribute { color: #ff80e1; } -.cm-s-erlang-dark span.cm-bracket { color: #ff9d00; } -.cm-s-erlang-dark span.cm-builtin { color: #eaa; } -.cm-s-erlang-dark span.cm-comment { color: #77f; } -.cm-s-erlang-dark span.cm-def { color: #e7a; } -.cm-s-erlang-dark span.cm-keyword { color: #ffee80; } -.cm-s-erlang-dark span.cm-meta { color: #50fefe; } -.cm-s-erlang-dark span.cm-number { color: #ffd0d0; } -.cm-s-erlang-dark span.cm-operator { color: #d55; } -.cm-s-erlang-dark span.cm-property { color: #ccc; } -.cm-s-erlang-dark span.cm-qualifier { color: #ccc; } -.cm-s-erlang-dark span.cm-quote { color: #ccc; } -.cm-s-erlang-dark span.cm-special { color: #ffbbbb; } -.cm-s-erlang-dark span.cm-string { color: #3ad900; } -.cm-s-erlang-dark span.cm-string-2 { color: #ccc; } -.cm-s-erlang-dark span.cm-tag { color: #9effff; } -.cm-s-erlang-dark span.cm-variable { color: #50fe50; } -.cm-s-erlang-dark span.cm-variable-2 { color: #e0e; } -.cm-s-erlang-dark span.cm-variable-3 { color: #ccc; } -.cm-s-erlang-dark span.cm-error { color: #9d1e15; } - -.cm-s-erlang-dark .CodeMirror-activeline-background {background: #013461 !important;} -.cm-s-erlang-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/lesser-dark.css b/shared/html/libs/codemirror/5.0.0/theme/lesser-dark.css deleted file mode 100644 index 5af8b7f..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/lesser-dark.css +++ /dev/null @@ -1,47 +0,0 @@ -/* -http://lesscss.org/ dark theme -Ported to CodeMirror by Peter Kroon -*/ -.cm-s-lesser-dark { - line-height: 1.3em; -} -.cm-s-lesser-dark.CodeMirror { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; } -.cm-s-lesser-dark div.CodeMirror-selected {background: #45443B !important;} /* 33322B*/ -.cm-s-lesser-dark.CodeMirror ::selection { background: rgba(69, 68, 59, .99); } -.cm-s-lesser-dark.CodeMirror ::-moz-selection { background: rgba(69, 68, 59, .99); } -.cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white !important; } -.cm-s-lesser-dark pre { padding: 0 8px; }/*editable code holder*/ - -.cm-s-lesser-dark.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/ - -.cm-s-lesser-dark .CodeMirror-gutters { background: #262626; border-right:1px solid #aaa; } -.cm-s-lesser-dark .CodeMirror-guttermarker { color: #599eff; } -.cm-s-lesser-dark .CodeMirror-guttermarker-subtle { color: #777; } -.cm-s-lesser-dark .CodeMirror-linenumber { color: #777; } - -.cm-s-lesser-dark span.cm-keyword { color: #599eff; } -.cm-s-lesser-dark span.cm-atom { color: #C2B470; } -.cm-s-lesser-dark span.cm-number { color: #B35E4D; } -.cm-s-lesser-dark span.cm-def {color: white;} -.cm-s-lesser-dark span.cm-variable { color:#D9BF8C; } -.cm-s-lesser-dark span.cm-variable-2 { color: #669199; } -.cm-s-lesser-dark span.cm-variable-3 { color: white; } -.cm-s-lesser-dark span.cm-property {color: #92A75C;} -.cm-s-lesser-dark span.cm-operator {color: #92A75C;} -.cm-s-lesser-dark span.cm-comment { color: #666; } -.cm-s-lesser-dark span.cm-string { color: #BCD279; } -.cm-s-lesser-dark span.cm-string-2 {color: #f50;} -.cm-s-lesser-dark span.cm-meta { color: #738C73; } -.cm-s-lesser-dark span.cm-qualifier {color: #555;} -.cm-s-lesser-dark span.cm-builtin { color: #ff9e59; } -.cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; } -.cm-s-lesser-dark span.cm-tag { color: #669199; } -.cm-s-lesser-dark span.cm-attribute {color: #00c;} -.cm-s-lesser-dark span.cm-header {color: #a0a;} -.cm-s-lesser-dark span.cm-quote {color: #090;} -.cm-s-lesser-dark span.cm-hr {color: #999;} -.cm-s-lesser-dark span.cm-link {color: #00c;} -.cm-s-lesser-dark span.cm-error { color: #9d1e15; } - -.cm-s-lesser-dark .CodeMirror-activeline-background {background: #3C3A3A !important;} -.cm-s-lesser-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/mbo.css b/shared/html/libs/codemirror/5.0.0/theme/mbo.css deleted file mode 100644 index e398795..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/mbo.css +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************/ -/* Based on mbonaci's Brackets mbo theme */ -/* https://github.com/mbonaci/global/blob/master/Mbo.tmTheme */ -/* Create your own: http://tmtheme-editor.herokuapp.com */ -/****************************************************************/ - -.cm-s-mbo.CodeMirror {background: #2c2c2c; color: #ffffec;} -.cm-s-mbo div.CodeMirror-selected {background: #716C62 !important;} -.cm-s-mbo.CodeMirror ::selection { background: rgba(113, 108, 98, .99); } -.cm-s-mbo.CodeMirror ::-moz-selection { background: rgba(113, 108, 98, .99); } -.cm-s-mbo .CodeMirror-gutters {background: #4e4e4e; border-right: 0px;} -.cm-s-mbo .CodeMirror-guttermarker { color: white; } -.cm-s-mbo .CodeMirror-guttermarker-subtle { color: grey; } -.cm-s-mbo .CodeMirror-linenumber {color: #dadada;} -.cm-s-mbo .CodeMirror-cursor {border-left: 1px solid #ffffec !important;} - -.cm-s-mbo span.cm-comment {color: #95958a;} -.cm-s-mbo span.cm-atom {color: #00a8c6;} -.cm-s-mbo span.cm-number {color: #00a8c6;} - -.cm-s-mbo span.cm-property, .cm-s-mbo span.cm-attribute {color: #9ddfe9;} -.cm-s-mbo span.cm-keyword {color: #ffb928;} -.cm-s-mbo span.cm-string {color: #ffcf6c;} -.cm-s-mbo span.cm-string.cm-property {color: #ffffec;} - -.cm-s-mbo span.cm-variable {color: #ffffec;} -.cm-s-mbo span.cm-variable-2 {color: #00a8c6;} -.cm-s-mbo span.cm-def {color: #ffffec;} -.cm-s-mbo span.cm-bracket {color: #fffffc; font-weight: bold;} -.cm-s-mbo span.cm-tag {color: #9ddfe9;} -.cm-s-mbo span.cm-link {color: #f54b07;} -.cm-s-mbo span.cm-error {border-bottom: #636363; color: #ffffec;} -.cm-s-mbo span.cm-qualifier {color: #ffffec;} - -.cm-s-mbo .CodeMirror-activeline-background {background: #494b41 !important;} -.cm-s-mbo .CodeMirror-matchingbracket {color: #222 !important;} -.cm-s-mbo .CodeMirror-matchingtag {background: rgba(255, 255, 255, .37);} diff --git a/shared/html/libs/codemirror/5.0.0/theme/mdn-like.css b/shared/html/libs/codemirror/5.0.0/theme/mdn-like.css deleted file mode 100644 index 93293c0..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/mdn-like.css +++ /dev/null @@ -1,46 +0,0 @@ -/* - MDN-LIKE Theme - Mozilla - Ported to CodeMirror by Peter Kroon - Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues - GitHub: @peterkroon - - The mdn-like theme is inspired on the displayed code examples at: https://developer.mozilla.org/en-US/docs/Web/CSS/animation - -*/ -.cm-s-mdn-like.CodeMirror { color: #999; background-color: #fff; } -.cm-s-mdn-like .CodeMirror-selected { background: #cfc !important; } -.cm-s-mdn-like.CodeMirror ::selection { background: #cfc; } -.cm-s-mdn-like.CodeMirror ::-moz-selection { background: #cfc; } - -.cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 6px solid rgba(0,83,159,0.65); color: #333; } -.cm-s-mdn-like .CodeMirror-linenumber { color: #aaa; margin-left: 3px; } -div.cm-s-mdn-like .CodeMirror-cursor { border-left: 2px solid #222; } - -.cm-s-mdn-like .cm-keyword { color: #6262FF; } -.cm-s-mdn-like .cm-atom { color: #F90; } -.cm-s-mdn-like .cm-number { color: #ca7841; } -.cm-s-mdn-like .cm-def { color: #8DA6CE; } -.cm-s-mdn-like span.cm-variable-2, .cm-s-mdn-like span.cm-tag { color: #690; } -.cm-s-mdn-like span.cm-variable-3, .cm-s-mdn-like span.cm-def { color: #07a; } - -.cm-s-mdn-like .cm-variable { color: #07a; } -.cm-s-mdn-like .cm-property { color: #905; } -.cm-s-mdn-like .cm-qualifier { color: #690; } - -.cm-s-mdn-like .cm-operator { color: #cda869; } -.cm-s-mdn-like .cm-comment { color:#777; font-weight:normal; } -.cm-s-mdn-like .cm-string { color:#07a; font-style:italic; } -.cm-s-mdn-like .cm-string-2 { color:#bd6b18; } /*?*/ -.cm-s-mdn-like .cm-meta { color: #000; } /*?*/ -.cm-s-mdn-like .cm-builtin { color: #9B7536; } /*?*/ -.cm-s-mdn-like .cm-tag { color: #997643; } -.cm-s-mdn-like .cm-attribute { color: #d6bb6d; } /*?*/ -.cm-s-mdn-like .cm-header { color: #FF6400; } -.cm-s-mdn-like .cm-hr { color: #AEAEAE; } -.cm-s-mdn-like .cm-link { color:#ad9361; font-style:italic; text-decoration:none; } -.cm-s-mdn-like .cm-error { border-bottom: 1px solid red; } - -div.cm-s-mdn-like .CodeMirror-activeline-background {background: #efefff;} -div.cm-s-mdn-like span.CodeMirror-matchingbracket {outline:1px solid grey; color: inherit;} - -.cm-s-mdn-like.CodeMirror { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFcAAAAyCAYAAAAp8UeFAAAHvklEQVR42s2b63bcNgyEQZCSHCdt2vd/0tWF7I+Q6XgMXiTtuvU5Pl57ZQKkKHzEAOtF5KeIJBGJ8uvL599FRFREZhFx8DeXv8trn68RuGaC8TRfo3SNp9dlDDHedyLyTUTeRWStXKPZrjtpZxaRw5hPqozRs1N8/enzIiQRWcCgy4MUA0f+XWliDhyL8Lfyvx7ei/Ae3iQFHyw7U/59pQVIMEEPEz0G7XiwdRjzSfC3UTtz9vchIntxvry5iMgfIhJoEflOz2CQr3F5h/HfeFe+GTdLaKcu9L8LTeQb/R/7GgbsfKedyNdoHsN31uRPWrfZ5wsj/NzzRQHuToIdU3ahwnsKPxXCjJITuOsi7XLc7SG/v5GdALs7wf8JjTFiB5+QvTEfRyGOfX3Lrx8wxyQi3sNq46O7QahQiCsRFgqddjBouVEHOKDgXAQHD9gJCr5sMKkEdjwsarG/ww3BMHBU7OBjXnzdyY7SfCxf5/z6ATccrwlKuwC/jhznnPF4CgVzhhVf4xp2EixcBActO75iZ8/fM9zAs2OMzKdslgXWJ9XG8PQoOAMA5fGcsvORgv0doBXyHrCwfLJAOwo71QLNkb8n2Pl6EWiR7OCibtkPaz4Kc/0NNAze2gju3zOwekALDaCFPI5vjPFmgGY5AZqyGEvH1x7QfIb8YtxMnA/b+QQ0aQDAwc6JMFg8CbQZ4qoYEEHbRwNojuK3EHwd7VALSgq+MNDKzfT58T8qdpADrgW0GmgcAS1lhzztJmkAzcPNOQbsWEALBDSlMKUG0Eq4CLAQWvEVQ9WU57gZJwZtgPO3r9oBTQ9WO8TjqXINx8R0EYpiZEUWOF3FxkbJkgU9B2f41YBrIj5ZfsQa0M5kTgiAAqM3ShXLgu8XMqcrQBvJ0CL5pnTsfMB13oB8athpAq2XOQmcGmoACCLydx7nToa23ATaSIY2ichfOdPTGxlasXMLaL0MLZAOwAKIM+y8CmicobGdCcbbK9DzN+yYGVoNNI5iUKTMyYOjPse4A8SM1MmcXgU0toOq1yO/v8FOxlASyc7TgeYaAMBJHcY1CcCwGI/TK4AmDbDyKYBBtFUkRwto8gygiQEaByFgJ00BH2M8JWwQS1nafDXQCidWyOI8AcjDCSjCLk8ngObuAm3JAHAdubAmOaK06V8MNEsKPJOhobSprwQa6gD7DclRQdqcwL4zxqgBrQcabUiBLclRDKAlWp+etPkBaNMA0AKlrHwTdEByZAA4GM+SNluSY6wAzcMNewxmgig5Ks0nkrSpBvSaQHMdKTBAnLojOdYyGpQ254602ZILPdTD1hdlggdIm74jbTp8vDwF5ZYUeLWGJpWsh6XNyXgcYwVoJQTEhhTYkxzZjiU5npU2TaB979TQehlaAVq4kaGpiPwwwLkYUuBbQwocyQTv1tA0+1UFWoJF3iv1oq+qoSk8EQdJmwHkziIF7oOZk14EGitibAdjLYYK78H5vZOhtWpoI0ATGHs0Q8OMb4Ey+2bU2UYztCtA0wFAs7TplGLRVQCcqaFdGSPCeTI1QNIC52iWNzof6Uib7xjEp07mNNoUYmVosVItHrHzRlLgBn9LFyRHaQCtVUMbtTNhoXWiTOO9k/V8BdAc1Oq0ArSQs6/5SU0hckNy9NnXqQY0PGYo5dWJ7nINaN6o958FWin27aBaWRka1r5myvLOAm0j30eBJqCxHLReVclxhxOEN2JfDWjxBtAC7MIH1fVaGdoOp4qJYDgKtKPSFNID2gSnGldrCqkFZ+5UeQXQBIRrSwocbdZYQT/2LwRahBPBXoHrB8nxaGROST62DKUbQOMMzZIC9abkuELfQzQALWTnDNAm8KHWFOJgJ5+SHIvTPcmx1xQyZRhNL5Qci689aXMEaN/uNIWkEwDAvFpOZmgsBaaGnbs1NPa1Jm32gBZAIh1pCtG7TSH4aE0y1uVY4uqoFPisGlpP2rSA5qTecWn5agK6BzSpgAyD+wFaqhnYoSZ1Vwr8CmlTQbrcO3ZaX0NAEyMbYaAlyquFoLKK3SPby9CeVUPThrSJmkCAE0CrKUQadi4DrdSlWhmah0YL9z9vClH59YGbHx1J8VZTyAjQepJjmXwAKTDQI3omc3p1U4gDUf6RfcdYfrUp5ClAi2J3Ba6UOXGo+K+bQrjjssitG2SJzshaLwMtXgRagUNpYYoVkMSBLM+9GGiJZMvduG6DRZ4qc04DMPtQQxOjEtACmhO7K1AbNbQDEggZyJwscFpAGwENhoBeUwh3bWolhe8BTYVKxQEWrSUn/uhcM5KhvUu/+eQu0Lzhi+VrK0PrZZNDQKs9cpYUuFYgMVpD4/NxenJTiMCNqdUEUf1qZWjppLT5qSkkUZbCwkbZMSuVnu80hfSkzRbQeqCZSAh6huR4VtoM2gHAlLf72smuWgE+VV7XpE25Ab2WFDgyhnSuKbs4GuGzCjR+tIoUuMFg3kgcWKLTwRqanJQ2W00hAsenfaApRC42hbCvK1SlE0HtE9BGgneJO+ELamitD1YjjOYnNYVcraGhtKkW0EqVVeDx733I2NH581k1NNxNLG0i0IJ8/NjVaOZ0tYZ2Vtr0Xv7tPV3hkWp9EFkgS/J0vosngTaSoaG06WHi+xObQkaAdlbanP8B2+2l0f90LmUAAAAASUVORK5CYII=); } diff --git a/shared/html/libs/codemirror/5.0.0/theme/midnight.css b/shared/html/libs/codemirror/5.0.0/theme/midnight.css deleted file mode 100644 index 296af4f..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/midnight.css +++ /dev/null @@ -1,47 +0,0 @@ -/* Based on the theme at http://bonsaiden.github.com/JavaScript-Garden */ - -/**/ -.cm-s-midnight span.CodeMirror-matchhighlight { background: #494949; } -.cm-s-midnight.CodeMirror-focused span.CodeMirror-matchhighlight { background: #314D67 !important; } - -/**/ -.cm-s-midnight .CodeMirror-activeline-background {background: #253540 !important;} - -.cm-s-midnight.CodeMirror { - background: #0F192A; - color: #D1EDFF; -} - -.cm-s-midnight.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;} - -.cm-s-midnight div.CodeMirror-selected {background: #314D67 !important;} -.cm-s-midnight.CodeMirror ::selection { background: rgba(49, 77, 103, .99); } -.cm-s-midnight.CodeMirror ::-moz-selection { background: rgba(49, 77, 103, .99); } -.cm-s-midnight .CodeMirror-gutters {background: #0F192A; border-right: 1px solid;} -.cm-s-midnight .CodeMirror-guttermarker { color: white; } -.cm-s-midnight .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-midnight .CodeMirror-linenumber {color: #D0D0D0;} -.cm-s-midnight .CodeMirror-cursor { - border-left: 1px solid #F8F8F0 !important; -} - -.cm-s-midnight span.cm-comment {color: #428BDD;} -.cm-s-midnight span.cm-atom {color: #AE81FF;} -.cm-s-midnight span.cm-number {color: #D1EDFF;} - -.cm-s-midnight span.cm-property, .cm-s-midnight span.cm-attribute {color: #A6E22E;} -.cm-s-midnight span.cm-keyword {color: #E83737;} -.cm-s-midnight span.cm-string {color: #1DC116;} - -.cm-s-midnight span.cm-variable {color: #FFAA3E;} -.cm-s-midnight span.cm-variable-2 {color: #FFAA3E;} -.cm-s-midnight span.cm-def {color: #4DD;} -.cm-s-midnight span.cm-bracket {color: #D1EDFF;} -.cm-s-midnight span.cm-tag {color: #449;} -.cm-s-midnight span.cm-link {color: #AE81FF;} -.cm-s-midnight span.cm-error {background: #F92672; color: #F8F8F0;} - -.cm-s-midnight .CodeMirror-matchingbracket { - text-decoration: underline; - color: white !important; -} diff --git a/shared/html/libs/codemirror/5.0.0/theme/monokai.css b/shared/html/libs/codemirror/5.0.0/theme/monokai.css deleted file mode 100644 index 6dfcc73..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/monokai.css +++ /dev/null @@ -1,33 +0,0 @@ -/* Based on Sublime Text's Monokai theme */ - -.cm-s-monokai.CodeMirror {background: #272822; color: #f8f8f2;} -.cm-s-monokai div.CodeMirror-selected {background: #49483E !important;} -.cm-s-monokai.CodeMirror ::selection { background: rgba(73, 72, 62, .99); } -.cm-s-monokai.CodeMirror ::-moz-selection { background: rgba(73, 72, 62, .99); } -.cm-s-monokai .CodeMirror-gutters {background: #272822; border-right: 0px;} -.cm-s-monokai .CodeMirror-guttermarker { color: white; } -.cm-s-monokai .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-monokai .CodeMirror-linenumber {color: #d0d0d0;} -.cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;} - -.cm-s-monokai span.cm-comment {color: #75715e;} -.cm-s-monokai span.cm-atom {color: #ae81ff;} -.cm-s-monokai span.cm-number {color: #ae81ff;} - -.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;} -.cm-s-monokai span.cm-keyword {color: #f92672;} -.cm-s-monokai span.cm-string {color: #e6db74;} - -.cm-s-monokai span.cm-variable {color: #a6e22e;} -.cm-s-monokai span.cm-variable-2 {color: #9effff;} -.cm-s-monokai span.cm-def {color: #fd971f;} -.cm-s-monokai span.cm-bracket {color: #f8f8f2;} -.cm-s-monokai span.cm-tag {color: #f92672;} -.cm-s-monokai span.cm-link {color: #ae81ff;} -.cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;} - -.cm-s-monokai .CodeMirror-activeline-background {background: #373831 !important;} -.cm-s-monokai .CodeMirror-matchingbracket { - text-decoration: underline; - color: white !important; -} diff --git a/shared/html/libs/codemirror/5.0.0/theme/neo.css b/shared/html/libs/codemirror/5.0.0/theme/neo.css deleted file mode 100644 index cecaaf2..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/neo.css +++ /dev/null @@ -1,43 +0,0 @@ -/* neo theme for codemirror */ - -/* Color scheme */ - -.cm-s-neo.CodeMirror { - background-color:#ffffff; - color:#2e383c; - line-height:1.4375; -} -.cm-s-neo .cm-comment {color:#75787b} -.cm-s-neo .cm-keyword, .cm-s-neo .cm-property {color:#1d75b3} -.cm-s-neo .cm-atom,.cm-s-neo .cm-number {color:#75438a} -.cm-s-neo .cm-node,.cm-s-neo .cm-tag {color:#9c3328} -.cm-s-neo .cm-string {color:#b35e14} -.cm-s-neo .cm-variable,.cm-s-neo .cm-qualifier {color:#047d65} - - -/* Editor styling */ - -.cm-s-neo pre { - padding:0; -} - -.cm-s-neo .CodeMirror-gutters { - border:none; - border-right:10px solid transparent; - background-color:transparent; -} - -.cm-s-neo .CodeMirror-linenumber { - padding:0; - color:#e0e2e5; -} - -.cm-s-neo .CodeMirror-guttermarker { color: #1d75b3; } -.cm-s-neo .CodeMirror-guttermarker-subtle { color: #e0e2e5; } - -.cm-s-neo div.CodeMirror-cursor { - width: auto; - border: 0; - background: rgba(155,157,162,0.37); - z-index: 1; -} diff --git a/shared/html/libs/codemirror/5.0.0/theme/night.css b/shared/html/libs/codemirror/5.0.0/theme/night.css deleted file mode 100644 index 6b2ac6c..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/night.css +++ /dev/null @@ -1,28 +0,0 @@ -/* Loosely based on the Midnight Textmate theme */ - -.cm-s-night.CodeMirror { background: #0a001f; color: #f8f8f8; } -.cm-s-night div.CodeMirror-selected { background: #447 !important; } -.cm-s-night.CodeMirror ::selection { background: rgba(68, 68, 119, .99); } -.cm-s-night.CodeMirror ::-moz-selection { background: rgba(68, 68, 119, .99); } -.cm-s-night .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; } -.cm-s-night .CodeMirror-guttermarker { color: white; } -.cm-s-night .CodeMirror-guttermarker-subtle { color: #bbb; } -.cm-s-night .CodeMirror-linenumber { color: #f8f8f8; } -.cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-night span.cm-comment { color: #6900a1; } -.cm-s-night span.cm-atom { color: #845dc4; } -.cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; } -.cm-s-night span.cm-keyword { color: #599eff; } -.cm-s-night span.cm-string { color: #37f14a; } -.cm-s-night span.cm-meta { color: #7678e2; } -.cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; } -.cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; } -.cm-s-night span.cm-bracket { color: #8da6ce; } -.cm-s-night span.cm-comment { color: #6900a1; } -.cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; } -.cm-s-night span.cm-link { color: #845dc4; } -.cm-s-night span.cm-error { color: #9d1e15; } - -.cm-s-night .CodeMirror-activeline-background {background: #1C005A !important;} -.cm-s-night .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/paraiso-dark.css b/shared/html/libs/codemirror/5.0.0/theme/paraiso-dark.css deleted file mode 100644 index af914b6..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/paraiso-dark.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Name: Paraíso (Dark) - Author: Jan T. Sott - - Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror) - Inspired by the art of Rubens LP (http://www.rubenslp.com.br) - -*/ - -.cm-s-paraiso-dark.CodeMirror {background: #2f1e2e; color: #b9b6b0;} -.cm-s-paraiso-dark div.CodeMirror-selected {background: #41323f !important;} -.cm-s-paraiso-dark.CodeMirror ::selection { background: rgba(65, 50, 63, .99); } -.cm-s-paraiso-dark.CodeMirror ::-moz-selection { background: rgba(65, 50, 63, .99); } -.cm-s-paraiso-dark .CodeMirror-gutters {background: #2f1e2e; border-right: 0px;} -.cm-s-paraiso-dark .CodeMirror-guttermarker { color: #ef6155; } -.cm-s-paraiso-dark .CodeMirror-guttermarker-subtle { color: #776e71; } -.cm-s-paraiso-dark .CodeMirror-linenumber {color: #776e71;} -.cm-s-paraiso-dark .CodeMirror-cursor {border-left: 1px solid #8d8687 !important;} - -.cm-s-paraiso-dark span.cm-comment {color: #e96ba8;} -.cm-s-paraiso-dark span.cm-atom {color: #815ba4;} -.cm-s-paraiso-dark span.cm-number {color: #815ba4;} - -.cm-s-paraiso-dark span.cm-property, .cm-s-paraiso-dark span.cm-attribute {color: #48b685;} -.cm-s-paraiso-dark span.cm-keyword {color: #ef6155;} -.cm-s-paraiso-dark span.cm-string {color: #fec418;} - -.cm-s-paraiso-dark span.cm-variable {color: #48b685;} -.cm-s-paraiso-dark span.cm-variable-2 {color: #06b6ef;} -.cm-s-paraiso-dark span.cm-def {color: #f99b15;} -.cm-s-paraiso-dark span.cm-bracket {color: #b9b6b0;} -.cm-s-paraiso-dark span.cm-tag {color: #ef6155;} -.cm-s-paraiso-dark span.cm-link {color: #815ba4;} -.cm-s-paraiso-dark span.cm-error {background: #ef6155; color: #8d8687;} - -.cm-s-paraiso-dark .CodeMirror-activeline-background {background: #4D344A !important;} -.cm-s-paraiso-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/paraiso-light.css b/shared/html/libs/codemirror/5.0.0/theme/paraiso-light.css deleted file mode 100644 index e198066..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/paraiso-light.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Name: Paraíso (Light) - Author: Jan T. Sott - - Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror) - Inspired by the art of Rubens LP (http://www.rubenslp.com.br) - -*/ - -.cm-s-paraiso-light.CodeMirror {background: #e7e9db; color: #41323f;} -.cm-s-paraiso-light div.CodeMirror-selected {background: #b9b6b0 !important;} -.cm-s-paraiso-light.CodeMirror ::selection { background: #b9b6b0; } -.cm-s-paraiso-light.CodeMirror ::-moz-selection { background: #b9b6b0; } -.cm-s-paraiso-light .CodeMirror-gutters {background: #e7e9db; border-right: 0px;} -.cm-s-paraiso-light .CodeMirror-guttermarker { color: black; } -.cm-s-paraiso-light .CodeMirror-guttermarker-subtle { color: #8d8687; } -.cm-s-paraiso-light .CodeMirror-linenumber {color: #8d8687;} -.cm-s-paraiso-light .CodeMirror-cursor {border-left: 1px solid #776e71 !important;} - -.cm-s-paraiso-light span.cm-comment {color: #e96ba8;} -.cm-s-paraiso-light span.cm-atom {color: #815ba4;} -.cm-s-paraiso-light span.cm-number {color: #815ba4;} - -.cm-s-paraiso-light span.cm-property, .cm-s-paraiso-light span.cm-attribute {color: #48b685;} -.cm-s-paraiso-light span.cm-keyword {color: #ef6155;} -.cm-s-paraiso-light span.cm-string {color: #fec418;} - -.cm-s-paraiso-light span.cm-variable {color: #48b685;} -.cm-s-paraiso-light span.cm-variable-2 {color: #06b6ef;} -.cm-s-paraiso-light span.cm-def {color: #f99b15;} -.cm-s-paraiso-light span.cm-bracket {color: #41323f;} -.cm-s-paraiso-light span.cm-tag {color: #ef6155;} -.cm-s-paraiso-light span.cm-link {color: #815ba4;} -.cm-s-paraiso-light span.cm-error {background: #ef6155; color: #776e71;} - -.cm-s-paraiso-light .CodeMirror-activeline-background {background: #CFD1C4 !important;} -.cm-s-paraiso-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/pastel-on-dark.css b/shared/html/libs/codemirror/5.0.0/theme/pastel-on-dark.css deleted file mode 100644 index 0d06f63..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/pastel-on-dark.css +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Pastel On Dark theme ported from ACE editor - * @license MIT - * @copyright AtomicPages LLC 2014 - * @author Dennis Thompson, AtomicPages LLC - * @version 1.1 - * @source https://github.com/atomicpages/codemirror-pastel-on-dark-theme - */ - -.cm-s-pastel-on-dark.CodeMirror { - background: #2c2827; - color: #8F938F; - line-height: 1.5; - font-size: 14px; -} -.cm-s-pastel-on-dark div.CodeMirror-selected { background: rgba(221,240,255,0.2) !important; } -.cm-s-pastel-on-dark.CodeMirror ::selection { background: rgba(221,240,255,0.2); } -.cm-s-pastel-on-dark.CodeMirror ::-moz-selection { background: rgba(221,240,255,0.2); } - -.cm-s-pastel-on-dark .CodeMirror-gutters { - background: #34302f; - border-right: 0px; - padding: 0 3px; -} -.cm-s-pastel-on-dark .CodeMirror-guttermarker { color: white; } -.cm-s-pastel-on-dark .CodeMirror-guttermarker-subtle { color: #8F938F; } -.cm-s-pastel-on-dark .CodeMirror-linenumber { color: #8F938F; } -.cm-s-pastel-on-dark .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; } -.cm-s-pastel-on-dark span.cm-comment { color: #A6C6FF; } -.cm-s-pastel-on-dark span.cm-atom { color: #DE8E30; } -.cm-s-pastel-on-dark span.cm-number { color: #CCCCCC; } -.cm-s-pastel-on-dark span.cm-property { color: #8F938F; } -.cm-s-pastel-on-dark span.cm-attribute { color: #a6e22e; } -.cm-s-pastel-on-dark span.cm-keyword { color: #AEB2F8; } -.cm-s-pastel-on-dark span.cm-string { color: #66A968; } -.cm-s-pastel-on-dark span.cm-variable { color: #AEB2F8; } -.cm-s-pastel-on-dark span.cm-variable-2 { color: #BEBF55; } -.cm-s-pastel-on-dark span.cm-variable-3 { color: #DE8E30; } -.cm-s-pastel-on-dark span.cm-def { color: #757aD8; } -.cm-s-pastel-on-dark span.cm-bracket { color: #f8f8f2; } -.cm-s-pastel-on-dark span.cm-tag { color: #C1C144; } -.cm-s-pastel-on-dark span.cm-link { color: #ae81ff; } -.cm-s-pastel-on-dark span.cm-qualifier,.cm-s-pastel-on-dark span.cm-builtin { color: #C1C144; } -.cm-s-pastel-on-dark span.cm-error { - background: #757aD8; - color: #f8f8f0; -} -.cm-s-pastel-on-dark .CodeMirror-activeline-background { background: rgba(255, 255, 255, 0.031) !important; } -.cm-s-pastel-on-dark .CodeMirror-matchingbracket { - border: 1px solid rgba(255,255,255,0.25); - color: #8F938F !important; - margin: -1px -1px 0 -1px; -} diff --git a/shared/html/libs/codemirror/5.0.0/theme/rubyblue.css b/shared/html/libs/codemirror/5.0.0/theme/rubyblue.css deleted file mode 100644 index d2fc0ec..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/rubyblue.css +++ /dev/null @@ -1,25 +0,0 @@ -.cm-s-rubyblue.CodeMirror { background: #112435; color: white; } -.cm-s-rubyblue div.CodeMirror-selected { background: #38566F !important; } -.cm-s-rubyblue.CodeMirror ::selection { background: rgba(56, 86, 111, 0.99); } -.cm-s-rubyblue.CodeMirror ::-moz-selection { background: rgba(56, 86, 111, 0.99); } -.cm-s-rubyblue .CodeMirror-gutters { background: #1F4661; border-right: 7px solid #3E7087; } -.cm-s-rubyblue .CodeMirror-guttermarker { color: white; } -.cm-s-rubyblue .CodeMirror-guttermarker-subtle { color: #3E7087; } -.cm-s-rubyblue .CodeMirror-linenumber { color: white; } -.cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; line-height: 1em; } -.cm-s-rubyblue span.cm-atom { color: #F4C20B; } -.cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; } -.cm-s-rubyblue span.cm-keyword { color: #F0F; } -.cm-s-rubyblue span.cm-string { color: #F08047; } -.cm-s-rubyblue span.cm-meta { color: #F0F; } -.cm-s-rubyblue span.cm-variable-2, .cm-s-rubyblue span.cm-tag { color: #7BD827; } -.cm-s-rubyblue span.cm-variable-3, .cm-s-rubyblue span.cm-def { color: white; } -.cm-s-rubyblue span.cm-bracket { color: #F0F; } -.cm-s-rubyblue span.cm-link { color: #F4C20B; } -.cm-s-rubyblue span.CodeMirror-matchingbracket { color:#F0F !important; } -.cm-s-rubyblue span.cm-builtin, .cm-s-rubyblue span.cm-special { color: #FF9D00; } -.cm-s-rubyblue span.cm-error { color: #AF2018; } - -.cm-s-rubyblue .CodeMirror-activeline-background {background: #173047 !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/solarized.css b/shared/html/libs/codemirror/5.0.0/theme/solarized.css deleted file mode 100644 index 4a10b7c..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/solarized.css +++ /dev/null @@ -1,165 +0,0 @@ -/* -Solarized theme for code-mirror -http://ethanschoonover.com/solarized -*/ - -/* -Solarized color pallet -http://ethanschoonover.com/solarized/img/solarized-palette.png -*/ - -.solarized.base03 { color: #002b36; } -.solarized.base02 { color: #073642; } -.solarized.base01 { color: #586e75; } -.solarized.base00 { color: #657b83; } -.solarized.base0 { color: #839496; } -.solarized.base1 { color: #93a1a1; } -.solarized.base2 { color: #eee8d5; } -.solarized.base3 { color: #fdf6e3; } -.solarized.solar-yellow { color: #b58900; } -.solarized.solar-orange { color: #cb4b16; } -.solarized.solar-red { color: #dc322f; } -.solarized.solar-magenta { color: #d33682; } -.solarized.solar-violet { color: #6c71c4; } -.solarized.solar-blue { color: #268bd2; } -.solarized.solar-cyan { color: #2aa198; } -.solarized.solar-green { color: #859900; } - -/* Color scheme for code-mirror */ - -.cm-s-solarized { - line-height: 1.45em; - color-profile: sRGB; - rendering-intent: auto; -} -.cm-s-solarized.cm-s-dark { - color: #839496; - background-color: #002b36; - text-shadow: #002b36 0 1px; -} -.cm-s-solarized.cm-s-light { - background-color: #fdf6e3; - color: #657b83; - text-shadow: #eee8d5 0 1px; -} - -.cm-s-solarized .CodeMirror-widget { - text-shadow: none; -} - - -.cm-s-solarized .cm-keyword { color: #cb4b16 } -.cm-s-solarized .cm-atom { color: #d33682; } -.cm-s-solarized .cm-number { color: #d33682; } -.cm-s-solarized .cm-def { color: #2aa198; } - -.cm-s-solarized .cm-variable { color: #268bd2; } -.cm-s-solarized .cm-variable-2 { color: #b58900; } -.cm-s-solarized .cm-variable-3 { color: #6c71c4; } - -.cm-s-solarized .cm-property { color: #2aa198; } -.cm-s-solarized .cm-operator {color: #6c71c4;} - -.cm-s-solarized .cm-comment { color: #586e75; font-style:italic; } - -.cm-s-solarized .cm-string { color: #859900; } -.cm-s-solarized .cm-string-2 { color: #b58900; } - -.cm-s-solarized .cm-meta { color: #859900; } -.cm-s-solarized .cm-qualifier { color: #b58900; } -.cm-s-solarized .cm-builtin { color: #d33682; } -.cm-s-solarized .cm-bracket { color: #cb4b16; } -.cm-s-solarized .CodeMirror-matchingbracket { color: #859900; } -.cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; } -.cm-s-solarized .cm-tag { color: #93a1a1 } -.cm-s-solarized .cm-attribute { color: #2aa198; } -.cm-s-solarized .cm-header { color: #586e75; } -.cm-s-solarized .cm-quote { color: #93a1a1; } -.cm-s-solarized .cm-hr { - color: transparent; - border-top: 1px solid #586e75; - display: block; -} -.cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; } -.cm-s-solarized .cm-special { color: #6c71c4; } -.cm-s-solarized .cm-em { - color: #999; - text-decoration: underline; - text-decoration-style: dotted; -} -.cm-s-solarized .cm-strong { color: #eee; } -.cm-s-solarized .cm-error, -.cm-s-solarized .cm-invalidchar { - color: #586e75; - border-bottom: 1px dotted #dc322f; -} - -.cm-s-solarized.cm-s-dark .CodeMirror-selected { background: #073642; } -.cm-s-solarized.cm-s-dark.CodeMirror ::selection { background: rgba(7, 54, 66, 0.99); } -.cm-s-solarized.cm-s-dark.CodeMirror ::-moz-selection { background: rgba(7, 54, 66, 0.99); } - -.cm-s-solarized.cm-s-light .CodeMirror-selected { background: #eee8d5; } -.cm-s-solarized.cm-s-light.CodeMirror ::selection { background: #eee8d5; } -.cm-s-solarized.cm-s-lightCodeMirror ::-moz-selection { background: #eee8d5; } - -/* Editor styling */ - - - -/* Little shadow on the view-port of the buffer view */ -.cm-s-solarized.CodeMirror { - -moz-box-shadow: inset 7px 0 12px -6px #000; - -webkit-box-shadow: inset 7px 0 12px -6px #000; - box-shadow: inset 7px 0 12px -6px #000; -} - -/* Gutter border and some shadow from it */ -.cm-s-solarized .CodeMirror-gutters { - border-right: 1px solid; -} - -/* Gutter colors and line number styling based of color scheme (dark / light) */ - -/* Dark */ -.cm-s-solarized.cm-s-dark .CodeMirror-gutters { - background-color: #002b36; - border-color: #00232c; -} - -.cm-s-solarized.cm-s-dark .CodeMirror-linenumber { - text-shadow: #021014 0 -1px; -} - -/* Light */ -.cm-s-solarized.cm-s-light .CodeMirror-gutters { - background-color: #fdf6e3; - border-color: #eee8d5; -} - -/* Common */ -.cm-s-solarized .CodeMirror-linenumber { - color: #586e75; - padding: 0 5px; -} -.cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; } -.cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; } -.cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; } - -.cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text { - color: #586e75; -} - -.cm-s-solarized .CodeMirror-lines .CodeMirror-cursor { - border-left: 1px solid #819090; -} - -/* -Active line. Negative margin compensates left padding of the text in the -view-port -*/ -.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background { - background: rgba(255, 255, 255, 0.10); -} -.cm-s-solarized.cm-s-light .CodeMirror-activeline-background { - background: rgba(0, 0, 0, 0.10); -} diff --git a/shared/html/libs/codemirror/5.0.0/theme/the-matrix.css b/shared/html/libs/codemirror/5.0.0/theme/the-matrix.css deleted file mode 100644 index f29b22b..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/the-matrix.css +++ /dev/null @@ -1,30 +0,0 @@ -.cm-s-the-matrix.CodeMirror { background: #000000; color: #00FF00; } -.cm-s-the-matrix div.CodeMirror-selected { background: #2D2D2D !important; } -.cm-s-the-matrix.CodeMirror ::selection { background: rgba(45, 45, 45, 0.99); } -.cm-s-the-matrix.CodeMirror ::-moz-selection { background: rgba(45, 45, 45, 0.99); } -.cm-s-the-matrix .CodeMirror-gutters { background: #060; border-right: 2px solid #00FF00; } -.cm-s-the-matrix .CodeMirror-guttermarker { color: #0f0; } -.cm-s-the-matrix .CodeMirror-guttermarker-subtle { color: white; } -.cm-s-the-matrix .CodeMirror-linenumber { color: #FFFFFF; } -.cm-s-the-matrix .CodeMirror-cursor { border-left: 1px solid #00FF00 !important; } - -.cm-s-the-matrix span.cm-keyword {color: #008803; font-weight: bold;} -.cm-s-the-matrix span.cm-atom {color: #3FF;} -.cm-s-the-matrix span.cm-number {color: #FFB94F;} -.cm-s-the-matrix span.cm-def {color: #99C;} -.cm-s-the-matrix span.cm-variable {color: #F6C;} -.cm-s-the-matrix span.cm-variable-2 {color: #C6F;} -.cm-s-the-matrix span.cm-variable-3 {color: #96F;} -.cm-s-the-matrix span.cm-property {color: #62FFA0;} -.cm-s-the-matrix span.cm-operator {color: #999} -.cm-s-the-matrix span.cm-comment {color: #CCCCCC;} -.cm-s-the-matrix span.cm-string {color: #39C;} -.cm-s-the-matrix span.cm-meta {color: #C9F;} -.cm-s-the-matrix span.cm-qualifier {color: #FFF700;} -.cm-s-the-matrix span.cm-builtin {color: #30a;} -.cm-s-the-matrix span.cm-bracket {color: #cc7;} -.cm-s-the-matrix span.cm-tag {color: #FFBD40;} -.cm-s-the-matrix span.cm-attribute {color: #FFF700;} -.cm-s-the-matrix span.cm-error {color: #FF0000;} - -.cm-s-the-matrix .CodeMirror-activeline-background {background: #040;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/tomorrow-night-bright.css b/shared/html/libs/codemirror/5.0.0/theme/tomorrow-night-bright.css deleted file mode 100644 index decb82d..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/tomorrow-night-bright.css +++ /dev/null @@ -1,35 +0,0 @@ -/* - - Name: Tomorrow Night - Bright - Author: Chris Kempson - - Port done by Gerard Braad - -*/ - -.cm-s-tomorrow-night-bright.CodeMirror {background: #000000; color: #eaeaea;} -.cm-s-tomorrow-night-bright div.CodeMirror-selected {background: #424242 !important;} -.cm-s-tomorrow-night-bright .CodeMirror-gutters {background: #000000; border-right: 0px;} -.cm-s-tomorrow-night-bright .CodeMirror-guttermarker { color: #e78c45; } -.cm-s-tomorrow-night-bright .CodeMirror-guttermarker-subtle { color: #777; } -.cm-s-tomorrow-night-bright .CodeMirror-linenumber {color: #424242;} -.cm-s-tomorrow-night-bright .CodeMirror-cursor {border-left: 1px solid #6A6A6A !important;} - -.cm-s-tomorrow-night-bright span.cm-comment {color: #d27b53;} -.cm-s-tomorrow-night-bright span.cm-atom {color: #a16a94;} -.cm-s-tomorrow-night-bright span.cm-number {color: #a16a94;} - -.cm-s-tomorrow-night-bright span.cm-property, .cm-s-tomorrow-night-bright span.cm-attribute {color: #99cc99;} -.cm-s-tomorrow-night-bright span.cm-keyword {color: #d54e53;} -.cm-s-tomorrow-night-bright span.cm-string {color: #e7c547;} - -.cm-s-tomorrow-night-bright span.cm-variable {color: #b9ca4a;} -.cm-s-tomorrow-night-bright span.cm-variable-2 {color: #7aa6da;} -.cm-s-tomorrow-night-bright span.cm-def {color: #e78c45;} -.cm-s-tomorrow-night-bright span.cm-bracket {color: #eaeaea;} -.cm-s-tomorrow-night-bright span.cm-tag {color: #d54e53;} -.cm-s-tomorrow-night-bright span.cm-link {color: #a16a94;} -.cm-s-tomorrow-night-bright span.cm-error {background: #d54e53; color: #6A6A6A;} - -.cm-s-tomorrow-night-bright .CodeMirror-activeline-background {background: #2a2a2a !important;} -.cm-s-tomorrow-night-bright .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/tomorrow-night-eighties.css b/shared/html/libs/codemirror/5.0.0/theme/tomorrow-night-eighties.css deleted file mode 100644 index 5fca3ca..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/tomorrow-night-eighties.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Name: Tomorrow Night - Eighties - Author: Chris Kempson - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-tomorrow-night-eighties.CodeMirror {background: #000000; color: #CCCCCC;} -.cm-s-tomorrow-night-eighties div.CodeMirror-selected {background: #2D2D2D !important;} -.cm-s-tomorrow-night-eighties.CodeMirror ::selection { background: rgba(45, 45, 45, 0.99); } -.cm-s-tomorrow-night-eighties.CodeMirror ::-moz-selection { background: rgba(45, 45, 45, 0.99); } -.cm-s-tomorrow-night-eighties .CodeMirror-gutters {background: #000000; border-right: 0px;} -.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker { color: #f2777a; } -.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker-subtle { color: #777; } -.cm-s-tomorrow-night-eighties .CodeMirror-linenumber {color: #515151;} -.cm-s-tomorrow-night-eighties .CodeMirror-cursor {border-left: 1px solid #6A6A6A !important;} - -.cm-s-tomorrow-night-eighties span.cm-comment {color: #d27b53;} -.cm-s-tomorrow-night-eighties span.cm-atom {color: #a16a94;} -.cm-s-tomorrow-night-eighties span.cm-number {color: #a16a94;} - -.cm-s-tomorrow-night-eighties span.cm-property, .cm-s-tomorrow-night-eighties span.cm-attribute {color: #99cc99;} -.cm-s-tomorrow-night-eighties span.cm-keyword {color: #f2777a;} -.cm-s-tomorrow-night-eighties span.cm-string {color: #ffcc66;} - -.cm-s-tomorrow-night-eighties span.cm-variable {color: #99cc99;} -.cm-s-tomorrow-night-eighties span.cm-variable-2 {color: #6699cc;} -.cm-s-tomorrow-night-eighties span.cm-def {color: #f99157;} -.cm-s-tomorrow-night-eighties span.cm-bracket {color: #CCCCCC;} -.cm-s-tomorrow-night-eighties span.cm-tag {color: #f2777a;} -.cm-s-tomorrow-night-eighties span.cm-link {color: #a16a94;} -.cm-s-tomorrow-night-eighties span.cm-error {background: #f2777a; color: #6A6A6A;} - -.cm-s-tomorrow-night-eighties .CodeMirror-activeline-background {background: #343600 !important;} -.cm-s-tomorrow-night-eighties .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/twilight.css b/shared/html/libs/codemirror/5.0.0/theme/twilight.css deleted file mode 100644 index 889a83d..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/twilight.css +++ /dev/null @@ -1,32 +0,0 @@ -.cm-s-twilight.CodeMirror { background: #141414; color: #f7f7f7; } /**/ -.cm-s-twilight .CodeMirror-selected { background: #323232 !important; } /**/ -.cm-s-twilight.CodeMirror ::selection { background: rgba(50, 50, 50, 0.99); } -.cm-s-twilight.CodeMirror ::-moz-selection { background: rgba(50, 50, 50, 0.99); } - -.cm-s-twilight .CodeMirror-gutters { background: #222; border-right: 1px solid #aaa; } -.cm-s-twilight .CodeMirror-guttermarker { color: white; } -.cm-s-twilight .CodeMirror-guttermarker-subtle { color: #aaa; } -.cm-s-twilight .CodeMirror-linenumber { color: #aaa; } -.cm-s-twilight .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-twilight .cm-keyword { color: #f9ee98; } /**/ -.cm-s-twilight .cm-atom { color: #FC0; } -.cm-s-twilight .cm-number { color: #ca7841; } /**/ -.cm-s-twilight .cm-def { color: #8DA6CE; } -.cm-s-twilight span.cm-variable-2, .cm-s-twilight span.cm-tag { color: #607392; } /**/ -.cm-s-twilight span.cm-variable-3, .cm-s-twilight span.cm-def { color: #607392; } /**/ -.cm-s-twilight .cm-operator { color: #cda869; } /**/ -.cm-s-twilight .cm-comment { color:#777; font-style:italic; font-weight:normal; } /**/ -.cm-s-twilight .cm-string { color:#8f9d6a; font-style:italic; } /**/ -.cm-s-twilight .cm-string-2 { color:#bd6b18 } /*?*/ -.cm-s-twilight .cm-meta { background-color:#141414; color:#f7f7f7; } /*?*/ -.cm-s-twilight .cm-builtin { color: #cda869; } /*?*/ -.cm-s-twilight .cm-tag { color: #997643; } /**/ -.cm-s-twilight .cm-attribute { color: #d6bb6d; } /*?*/ -.cm-s-twilight .cm-header { color: #FF6400; } -.cm-s-twilight .cm-hr { color: #AEAEAE; } -.cm-s-twilight .cm-link { color:#ad9361; font-style:italic; text-decoration:none; } /**/ -.cm-s-twilight .cm-error { border-bottom: 1px solid red; } - -.cm-s-twilight .CodeMirror-activeline-background {background: #27282E !important;} -.cm-s-twilight .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/vibrant-ink.css b/shared/html/libs/codemirror/5.0.0/theme/vibrant-ink.css deleted file mode 100644 index 8ea5359..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/vibrant-ink.css +++ /dev/null @@ -1,34 +0,0 @@ -/* Taken from the popular Visual Studio Vibrant Ink Schema */ - -.cm-s-vibrant-ink.CodeMirror { background: black; color: white; } -.cm-s-vibrant-ink .CodeMirror-selected { background: #35493c !important; } -.cm-s-vibrant-ink.CodeMirror ::selection { background: rgba(53, 73, 60, 0.99); } -.cm-s-vibrant-ink.CodeMirror ::-moz-selection { background: rgba(53, 73, 60, 0.99); } - -.cm-s-vibrant-ink .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; } -.cm-s-vibrant-ink .CodeMirror-guttermarker { color: white; } -.cm-s-vibrant-ink .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-vibrant-ink .CodeMirror-linenumber { color: #d0d0d0; } -.cm-s-vibrant-ink .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-vibrant-ink .cm-keyword { color: #CC7832; } -.cm-s-vibrant-ink .cm-atom { color: #FC0; } -.cm-s-vibrant-ink .cm-number { color: #FFEE98; } -.cm-s-vibrant-ink .cm-def { color: #8DA6CE; } -.cm-s-vibrant-ink span.cm-variable-2, .cm-s-vibrant span.cm-tag { color: #FFC66D } -.cm-s-vibrant-ink span.cm-variable-3, .cm-s-vibrant span.cm-def { color: #FFC66D } -.cm-s-vibrant-ink .cm-operator { color: #888; } -.cm-s-vibrant-ink .cm-comment { color: gray; font-weight: bold; } -.cm-s-vibrant-ink .cm-string { color: #A5C25C } -.cm-s-vibrant-ink .cm-string-2 { color: red } -.cm-s-vibrant-ink .cm-meta { color: #D8FA3C; } -.cm-s-vibrant-ink .cm-builtin { color: #8DA6CE; } -.cm-s-vibrant-ink .cm-tag { color: #8DA6CE; } -.cm-s-vibrant-ink .cm-attribute { color: #8DA6CE; } -.cm-s-vibrant-ink .cm-header { color: #FF6400; } -.cm-s-vibrant-ink .cm-hr { color: #AEAEAE; } -.cm-s-vibrant-ink .cm-link { color: blue; } -.cm-s-vibrant-ink .cm-error { border-bottom: 1px solid red; } - -.cm-s-vibrant-ink .CodeMirror-activeline-background {background: #27282E !important;} -.cm-s-vibrant-ink .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} diff --git a/shared/html/libs/codemirror/5.0.0/theme/xq-dark.css b/shared/html/libs/codemirror/5.0.0/theme/xq-dark.css deleted file mode 100644 index d537993..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/xq-dark.css +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright (C) 2011 by MarkLogic Corporation -Author: Mike Brevoort - -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. -*/ -.cm-s-xq-dark.CodeMirror { background: #0a001f; color: #f8f8f8; } -.cm-s-xq-dark .CodeMirror-selected { background: #27007A !important; } -.cm-s-xq-dark.CodeMirror ::selection { background: rgba(39, 0, 122, 0.99); } -.cm-s-xq-dark.CodeMirror ::-moz-selection { background: rgba(39, 0, 122, 0.99); } -.cm-s-xq-dark .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; } -.cm-s-xq-dark .CodeMirror-guttermarker { color: #FFBD40; } -.cm-s-xq-dark .CodeMirror-guttermarker-subtle { color: #f8f8f8; } -.cm-s-xq-dark .CodeMirror-linenumber { color: #f8f8f8; } -.cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-xq-dark span.cm-keyword {color: #FFBD40;} -.cm-s-xq-dark span.cm-atom {color: #6C8CD5;} -.cm-s-xq-dark span.cm-number {color: #164;} -.cm-s-xq-dark span.cm-def {color: #FFF; text-decoration:underline;} -.cm-s-xq-dark span.cm-variable {color: #FFF;} -.cm-s-xq-dark span.cm-variable-2 {color: #EEE;} -.cm-s-xq-dark span.cm-variable-3 {color: #DDD;} -.cm-s-xq-dark span.cm-property {} -.cm-s-xq-dark span.cm-operator {} -.cm-s-xq-dark span.cm-comment {color: gray;} -.cm-s-xq-dark span.cm-string {color: #9FEE00;} -.cm-s-xq-dark span.cm-meta {color: yellow;} -.cm-s-xq-dark span.cm-qualifier {color: #FFF700;} -.cm-s-xq-dark span.cm-builtin {color: #30a;} -.cm-s-xq-dark span.cm-bracket {color: #cc7;} -.cm-s-xq-dark span.cm-tag {color: #FFBD40;} -.cm-s-xq-dark span.cm-attribute {color: #FFF700;} -.cm-s-xq-dark span.cm-error {color: #f00;} - -.cm-s-xq-dark .CodeMirror-activeline-background {background: #27282E !important;} -.cm-s-xq-dark .CodeMirror-matchingbracket {outline:1px solid grey; color:white !important;} \ No newline at end of file diff --git a/shared/html/libs/codemirror/5.0.0/theme/xq-light.css b/shared/html/libs/codemirror/5.0.0/theme/xq-light.css deleted file mode 100644 index 20b5c79..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/xq-light.css +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright (C) 2011 by MarkLogic Corporation -Author: Mike Brevoort - -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. -*/ -.cm-s-xq-light span.cm-keyword {line-height: 1em; font-weight: bold; color: #5A5CAD; } -.cm-s-xq-light span.cm-atom {color: #6C8CD5;} -.cm-s-xq-light span.cm-number {color: #164;} -.cm-s-xq-light span.cm-def {text-decoration:underline;} -.cm-s-xq-light span.cm-variable {color: black; } -.cm-s-xq-light span.cm-variable-2 {color:black;} -.cm-s-xq-light span.cm-variable-3 {color: black; } -.cm-s-xq-light span.cm-property {} -.cm-s-xq-light span.cm-operator {} -.cm-s-xq-light span.cm-comment {color: #0080FF; font-style: italic;} -.cm-s-xq-light span.cm-string {color: red;} -.cm-s-xq-light span.cm-meta {color: yellow;} -.cm-s-xq-light span.cm-qualifier {color: grey} -.cm-s-xq-light span.cm-builtin {color: #7EA656;} -.cm-s-xq-light span.cm-bracket {color: #cc7;} -.cm-s-xq-light span.cm-tag {color: #3F7F7F;} -.cm-s-xq-light span.cm-attribute {color: #7F007F;} -.cm-s-xq-light span.cm-error {color: #f00;} - -.cm-s-xq-light .CodeMirror-activeline-background {background: #e8f2ff !important;} -.cm-s-xq-light .CodeMirror-matchingbracket {outline:1px solid grey;color:black !important;background:yellow;} \ No newline at end of file diff --git a/shared/html/libs/codemirror/5.0.0/theme/zenburn.css b/shared/html/libs/codemirror/5.0.0/theme/zenburn.css deleted file mode 100644 index f817198..0000000 --- a/shared/html/libs/codemirror/5.0.0/theme/zenburn.css +++ /dev/null @@ -1,37 +0,0 @@ -/** - * " - * Using Zenburn color palette from the Emacs Zenburn Theme - * https://github.com/bbatsov/zenburn-emacs/blob/master/zenburn-theme.el - * - * Also using parts of https://github.com/xavi/coderay-lighttable-theme - * " - * From: https://github.com/wisenomad/zenburn-lighttable-theme/blob/master/zenburn.css - */ - -.cm-s-zenburn .CodeMirror-gutters { background: #3f3f3f !important; } -.cm-s-zenburn .CodeMirror-foldgutter-open, .CodeMirror-foldgutter-folded { color: #999; } -.cm-s-zenburn .CodeMirror-cursor { border-left: 1px solid white !important; } -.cm-s-zenburn { background-color: #3f3f3f; color: #dcdccc; } -.cm-s-zenburn span.cm-builtin { color: #dcdccc; font-weight: bold; } -.cm-s-zenburn span.cm-comment { color: #7f9f7f; } -.cm-s-zenburn span.cm-keyword { color: #f0dfaf; font-weight: bold; } -.cm-s-zenburn span.cm-atom { color: #bfebbf; } -.cm-s-zenburn span.cm-def { color: #dcdccc; } -.cm-s-zenburn span.cm-variable { color: #dfaf8f; } -.cm-s-zenburn span.cm-variable-2 { color: #dcdccc; } -.cm-s-zenburn span.cm-string { color: #cc9393; } -.cm-s-zenburn span.cm-string-2 { color: #cc9393; } -.cm-s-zenburn span.cm-number { color: #dcdccc; } -.cm-s-zenburn span.cm-tag { color: #93e0e3; } -.cm-s-zenburn span.cm-property { color: #dfaf8f; } -.cm-s-zenburn span.cm-attribute { color: #dfaf8f; } -.cm-s-zenburn span.cm-qualifier { color: #7cb8bb; } -.cm-s-zenburn span.cm-meta { color: #f0dfaf; } -.cm-s-zenburn span.cm-header { color: #f0efd0; } -.cm-s-zenburn span.cm-operator { color: #f0efd0; } -.cm-s-zenburn span.CodeMirror-matchingbracket { box-sizing: border-box; background: transparent; border-bottom: 1px solid; } -.cm-s-zenburn span.CodeMirror-nonmatchingbracket { border-bottom: 1px solid; background: none; } -.cm-s-zenburn .CodeMirror-activeline { background: #000000; } -.cm-s-zenburn .CodeMirror-activeline-background { background: #000000; } -.cm-s-zenburn .CodeMirror-selected { background: #545454; } -.cm-s-zenburn .CodeMirror-focused .CodeMirror-selected { background: #4f4f4f; } diff --git a/shared/html/libs/winjs/1.0/js/en-us/base.strings.js b/shared/html/libs/winjs/1.0/js/en-us/base.strings.js deleted file mode 100644 index fa62e0b..0000000 --- a/shared/html/libs/winjs/1.0/js/en-us/base.strings.js +++ /dev/null @@ -1,63 +0,0 @@ -/// -/*! - © Microsoft. All rights reserved. - - This library is supported for use in Windows Store apps only. - - Build: 1.0.9200.20789.win8_ldr.130802-2151 - - Version: Microsoft.WinJS.1.0 -*/ - -(function (global) { - global.strings = global.strings || {}; - - var appxVersion = "Microsoft.WinJS.1.0"; - var developerPrefix = "Developer."; - if (appxVersion.indexOf(developerPrefix) === 0) { - appxVersion = appxVersion.substring(developerPrefix.length); - } - - function addStrings(keyPrefix, strings) { - Object.keys(strings).forEach(function (key) { - global.strings[keyPrefix + key.replace("\\", "/")] = strings[key]; - }); - } - -addStrings( -"ms-resource://"+appxVersion+"/base/", - -{ - "attributeBindingSingleProperty": "Attribute binding requires a single destination attribute name, often in the form \"this['aria-label']\" or \"width\".", - "bindingInitializerNotFound": "Initializer not found:'{0}'", - "cannotBindToThis": "Can't bind to 'this'.", - "creatingNewProperty": "Creating new property {0}. Full path:{1}", - "dataSourceNotFound": "Data source not found:{0}", - "duplicateBindingDetected": "Binding against element with id {0} failed because a duplicate id was detected.", - "elementNotFound": "Element not found:{0}", - "errorActivatingControl": "Error activating control: {0}", - "errorInitializingBindings": "Error initializing bindings: {0}", - "exceptionFromBindingInitializer": "Exception thrown from binding initializer: {0}", - "idBindingNotSupported": "Declarative binding to ID field is not supported. Initializer: {0}", - "illegalListLength": "List length must be assigned a finite positive number", - "invalidBinding": "Invalid binding:'{0}'. Expected to be ':;'. {1}", - "invalidFragmentUri": "Unsupported uri for fragment loading. Fragments in the local context can only load from package content or local sources. To load fragments from other sources, use a web context.", - "invalidOptionsRecord": "Invalid options record: '{0}', expected to be in the format of an object literal. {1}", - "malformedFormatStringInput": "Malformed, did you mean to escape your '{0}'?", - "nestedDOMElementBindingNotSupported": "Binding through a property {0} of type HTMLElement is not supported, Full path:{1}.", - "nestingExceeded": "NestingExceeded", - "notFound": "NotFound: {0}", - "notSupportedForProcessing": "Value is not supported within a declarative processing context, if you want it to be supported mark it using WinJS.Utilities.markSupportedForProcessing. The value was: '{0}'", - "nonStaticHTML": "Unable to add dynamic content. A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property or the document.write method to add a script element will generate this exception. If the content is safe and from a trusted source, use a method to explicitly manipulate elements and attributes, such as createElement, or use setInnerHTMLUnsafe (or other unsafe method).", - "propertyDoesNotExist": "{0} doesn't exist. Full path:{1}", - "propertyIsUndefined": "{0} is undefined", - "sparseArrayNotSupported": "Sparse arrays are not supported with proxy: true", - "unexpectedTokenExpectedToken": "Unexpected token: {0}, expected token: {1}, at offset {2}", - "unexpectedTokenExpectedTokens": "Unexpected token: {0}, expected one of: {1}, at offset {2}", - "unexpectedTokenGeneric": "Unexpected token: {0}, at offset {1}", - "unsupportedDataTypeForBinding": "Unsupported data type" -} - -); - -}(this)); diff --git a/shared/html/libs/winjs/1.0/js/en-us/ui.strings.js b/shared/html/libs/winjs/1.0/js/en-us/ui.strings.js deleted file mode 100644 index 759c1cc..0000000 --- a/shared/html/libs/winjs/1.0/js/en-us/ui.strings.js +++ /dev/null @@ -1,300 +0,0 @@ -/// -/*! - © Microsoft. All rights reserved. - - This library is supported for use in Windows Store apps only. - - Build: 1.0.9200.20789.win8_ldr.130802-2151 - - Version: Microsoft.WinJS.1.0 -*/ - -(function (global) { - global.strings = global.strings || {}; - - var appxVersion = "Microsoft.WinJS.1.0"; - var developerPrefix = "Developer."; - if (appxVersion.indexOf(developerPrefix) === 0) { - appxVersion = appxVersion.substring(developerPrefix.length); - } - - function addStrings(keyPrefix, strings) { - Object.keys(strings).forEach(function (key) { - global.strings[keyPrefix + key.replace("\\", "/")] = strings[key]; - }); - } - -addStrings( -"ms-resource://"+appxVersion+"/ui/", - -{ - "appBarAriaLabel": "App Bar", - "appBarCommandAriaLabel": "App Bar Item", - "automaticallyLoadPagesIsInvalid": "Invalid argument: automaticallyLoadPages must be a boolean.", - "averageRating": "Average Rating", - "backbuttonarialabel": "Back", - "badAlignment": "Invalid argument: Flyout alignment should be 'center' (default), 'left', or 'right'.", - "badAxis": "Invalid argument: orientation must be a string, either 'horizontal' or 'vertical'", - "badButtonElement": "Invalid argument: For a button, toggle, or flyout command, the element must be null or a button element", - "badClick": "Invalid argument: The onclick property for an {0} must be a function", - "badCurrentPage": "Invalid argument: currentPage must be a number greater than or equal to zero and be within the bounds of the datasource", - "badFlyout": "Invalid argument: The flyout property for an {0} must be a Flyout or String id of a Flyout", - "badHrElement": "Invalid argument: For a separator, the element must be null or an hr element", - "badItemSpacingAmount": "Invalid argument: itemSpacing must be a number greater than or equal to zero", - "badLayout": "Invalid argument: The layout property must be 'custom' or 'commands'", - "badPlacement": "Invalid argument: Flyout placement should be 'top' (default), 'bottom', 'left', 'right', or 'auto'.", - "badReference": "Invalid argument: Invalid href to settings flyout fragment", - "cannotChangeCommandsWhenVisible": "Invalid argument: You must call hide() before changing {0} commands", - "cannotChangeHiddenProperty": "Unable to set hidden property while parent {0} is visible.", - "cannotChangeLayoutWhenVisible": "Invalid argument: The layout property cannot be set when the AppBar is visible, call hide() first", - "cannotChangePlacementWhenVisible": "Invalid argument: The placement property cannot be set when the AppBar is visible, call hide() first", - "clearYourRating" : "Clear your rating", - "closeOverlay" : "Close", - "duplicateConstruction": "Invalid argument: Controls may only be instantiated one time for each DOM element", - "flipViewNavigationDuringStateChange": "Error: After changing itemDataSource or itemTemplate, any navigation in the FlipView control should be delayed until the pageselected event is fired.", - "flipViewPanningContainerAriaLabel": "Scrolling Container", - "flyoutAriaLabel": "Flyout", - "indexIsInvalid": "Invalid argument: index must be a non-negative integer.", - "invalidCountReturned": "Error: data adapter should return undefined, null, CountResult.unknown, or a non-negative integer for the count.", - "invalidIndexReturned": "Error: data adapter should return undefined, null or a non-negative integer for the index.", - "invalidItemReturned": "Error: data adapter returned item that is not an object.", - "invalidItemsManagerCallback": "Invalid argument: {0} must be a function.", - "invalidKeyReturned": "Error: data adapter returned item with undefined or null key.", - "invalidViewBoxChildren": "ViewBox expects to only have one child element", - "invalidTemplate": "Invalid template: Templates must be created before being passed to the ListView, and must contain a valid tree of elements.", - "invalidZoomFactor": "Invalid zoomFactor", - "invalidRequestedCountReturned": "Error: data adapter should return CountResult.unknown, CountResult.failure, or a non-negative integer for the count.", - "itemIsInvalid": "Invalid argument: item must be a DOM element that was returned by the Items Manager, and has not been replaced or released.", - "itemRendererIsInvalid": "Invalid argument: itemRenderer must be a function.", - "keyIsInvalid": "Invalid argument: key must be a string.", - "layoutIsInvalid": "Invalid argument: layout must be one of following values: 'verticalgrid', 'horizontalgrid' or 'list'.", - "layoutNotInitialized": "Layout is not initialized.", - "listDataAdapterIsInvalid": "Invalid argument: listDataAdapter must be an object or an array.", - "listDataSourceIsInvalid": "Invalid argument: dataSource must be an object.", - "listViewInvalidItem": "Item must provide index, key or description of corresponding item.", - "listViewViewportAriaLabel": "Scrolling Container", - "loadingBehaviorIsInvalid": "Invalid argument: loadingBehavior must be 'incremental' or 'randomAccess'.", - "menuCommandAriaLabel": "Menu Item", - "menuAriaLabel": "Menu", - "modeIsInvalid": "Invalid argument: mode must be one of following values: 'none', 'single' or 'multi'.", - "mustContainCommands": "Invalid HTML: AppBars/Menus must contain only AppBarCommands/MenuCommands", - "noAnchor": "Invalid argument: Showing flyout requires a DOM element as its parameter.", - "noitemsManagerForCount": "Invalid operation: can't get count if no dataSource has been set", - "notCompatibleWithSemanticZoom": "ListView can only be used with SemanticZoom if randomAccess loading behavior is specified.", - "off" : "Off", - "on" : "On", - "pagesToLoadIsInvalid": "Invalid argument: pagesToLoad must be a positive number.", - "pagesToLoadThresholdIsInvalid": "Invalid argument: pagesToLoadThreshold must be a positive number.", - "requiresCommands": "Invalid argument: commands must not be empty", - "selectAMPM": "Select A.M P.M", - "selectDay": "Select Day", - "selectHour": "Select Hour", - "selectMinute": "Select Minute", - "selectMonth": "Select Month", - "selectYear": "Select Year", - "settingsFlyoutAriaLabel": "Settings Flyout", - "tentativeRating": "Tentative Rating", - "tooltipStringsIsInvalid": "Invalid argument: tooltipStrings must be null or an array of strings.", - "unrated": "Unrated", - "userRating": "User Rating", - // AppBar Icons follow, the format of the ui.js and ui.resjson differ for - // the AppBarIcon namespace. The remainder of the file therefore differs. - // Code point comments are the icon glyphs in the 'Segoe UI Symbol' font. - "appBarIcons\\previous": "\uE100", //  group:Media - "appBarIcons\\next": "\uE101", //  group:Media - "appBarIcons\\play": "\uE102", //  group:Media - "appBarIcons\\pause": "\uE103", //  group:Media - "appBarIcons\\edit": "\uE104", //  group:File - "appBarIcons\\save": "\uE105", //  group:File - "appBarIcons\\clear": "\uE106", //  group:File - "appBarIcons\\delete": "\uE107", //  group:File - "appBarIcons\\remove": "\uE108", //  group:File - "appBarIcons\\add": "\uE109", //  group:File - "appBarIcons\\cancel": "\uE10A", //  group:Editing - "appBarIcons\\accept": "\uE10B", //  group:General - "appBarIcons\\more": "\uE10C", //  group:General - "appBarIcons\\redo": "\uE10D", //  group:Editing - "appBarIcons\\undo": "\uE10E", //  group:Editing - "appBarIcons\\home": "\uE10F", //  group:General - "appBarIcons\\up": "\uE110", //  group:General - "appBarIcons\\forward": "\uE111", //  group:General - "appBarIcons\\right": "\uE111", //  group:General - "appBarIcons\\back": "\uE112", //  group:General - "appBarIcons\\left": "\uE112", //  group:General - "appBarIcons\\favorite": "\uE113", //  group:Media - "appBarIcons\\camera": "\uE114", //  group:System - "appBarIcons\\settings": "\uE115", //  group:System - "appBarIcons\\video": "\uE116", //  group:Media - "appBarIcons\\sync": "\uE117", //  group:Media - "appBarIcons\\download": "\uE118", //  group:Media - "appBarIcons\\mail": "\uE119", //  group:Mail and calendar - "appBarIcons\\find": "\uE11A", //  group:Data - "appBarIcons\\help": "\uE11B", //  group:General - "appBarIcons\\upload": "\uE11C", //  group:Media - "appBarIcons\\emoji": "\uE11D", //  group:Communications - "appBarIcons\\twopage": "\uE11E", //  group:Layout - "appBarIcons\\leavechat": "\uE11F", //  group:Communications - "appBarIcons\\mailforward": "\uE120", //  group:Mail and calendar - "appBarIcons\\clock": "\uE121", //  group:General - "appBarIcons\\send": "\uE122", //  group:Mail and calendar - "appBarIcons\\crop": "\uE123", //  group:Editing - "appBarIcons\\rotatecamera": "\uE124", //  group:System - "appBarIcons\\people": "\uE125", //  group:Communications - "appBarIcons\\closepane": "\uE126", //  group:Layout - "appBarIcons\\openpane": "\uE127", //  group:Layout - "appBarIcons\\world": "\uE128", //  group:General - "appBarIcons\\flag": "\uE129", //  group:Mail and calendar - "appBarIcons\\previewlink": "\uE12A", //  group:General - "appBarIcons\\globe": "\uE12B", //  group:Communications - "appBarIcons\\trim": "\uE12C", //  group:Editing - "appBarIcons\\attachcamera": "\uE12D", //  group:System - "appBarIcons\\zoomin": "\uE12E", //  group:Layout - "appBarIcons\\bookmarks": "\uE12F", //  group:Editing - "appBarIcons\\document": "\uE130", //  group:File - "appBarIcons\\protecteddocument": "\uE131", //  group:File - "appBarIcons\\page": "\uE132", //  group:Layout - "appBarIcons\\bullets": "\uE133", //  group:Editing - "appBarIcons\\comment": "\uE134", //  group:Communications - "appBarIcons\\mail2": "\uE135", //  group:Mail and calendar - "appBarIcons\\contactinfo": "\uE136", //  group:Communications - "appBarIcons\\hangup": "\uE137", //  group:Communications - "appBarIcons\\viewall": "\uE138", //  group:Data - "appBarIcons\\mappin": "\uE139", //  group:General - "appBarIcons\\phone": "\uE13A", //  group:Communications - "appBarIcons\\videochat": "\uE13B", //  group:Communications - "appBarIcons\\switch": "\uE13C", //  group:Communications - "appBarIcons\\contact": "\uE13D", //  group:Communications - "appBarIcons\\rename": "\uE13E", //  group:File - "appBarIcons\\pin": "\uE141", //  group:System - "appBarIcons\\musicinfo": "\uE142", //  group:Media - "appBarIcons\\go": "\uE143", //  group:General - "appBarIcons\\keyboard": "\uE144", //  group:System - "appBarIcons\\dockleft": "\uE145", //  group:Layout - "appBarIcons\\dockright": "\uE146", //  group:Layout - "appBarIcons\\dockbottom": "\uE147", //  group:Layout - "appBarIcons\\remote": "\uE148", //  group:System - "appBarIcons\\refresh": "\uE149", //  group:Data - "appBarIcons\\rotate": "\uE14A", //  group:Layout - "appBarIcons\\shuffle": "\uE14B", //  group:Media - "appBarIcons\\list": "\uE14C", //  group:Editing - "appBarIcons\\shop": "\uE14D", //  group:General - "appBarIcons\\selectall": "\uE14E", //  group:Data - "appBarIcons\\orientation": "\uE14F", //  group:Layout - "appBarIcons\\import": "\uE150", //  group:Data - "appBarIcons\\importall": "\uE151", //  group:Data - "appBarIcons\\browsephotos": "\uE155", //  group:Media - "appBarIcons\\webcam": "\uE156", //  group:System - "appBarIcons\\pictures": "\uE158", //  group:Media - "appBarIcons\\savelocal": "\uE159", //  group:File - "appBarIcons\\caption": "\uE15A", //  group:Media - "appBarIcons\\stop": "\uE15B", //  group:Media - "appBarIcons\\showresults": "\uE15C", //  group:Data - "appBarIcons\\volume": "\uE15D", //  group:Media - "appBarIcons\\repair": "\uE15E", //  group:System - "appBarIcons\\message": "\uE15F", //  group:Communications - "appBarIcons\\page2": "\uE160", //  group:Layout - "appBarIcons\\calendarday": "\uE161", //  group:Mail and calendar - "appBarIcons\\calendarweek": "\uE162", //  group:Mail and calendar - "appBarIcons\\calendar": "\uE163", //  group:Mail and calendar - "appBarIcons\\characters": "\uE164", //  group:Editing - "appBarIcons\\mailreplyall": "\uE165", //  group:Mail and calendar - "appBarIcons\\read": "\uE166", //  group:Mail and calendar - "appBarIcons\\link": "\uE167", //  group:Communications - "appBarIcons\\accounts": "\uE168", //  group:Communications - "appBarIcons\\showbcc": "\uE169", //  group:Mail and calendar - "appBarIcons\\hidebcc": "\uE16A", //  group:Mail and calendar - "appBarIcons\\cut": "\uE16B", //  group:Editing - "appBarIcons\\attach": "\uE16C", //  group:Mail and calendar - "appBarIcons\\paste": "\uE16D", //  group:Editing - "appBarIcons\\filter": "\uE16E", //  group:Data - "appBarIcons\\copy": "\uE16F", //  group:Editing - "appBarIcons\\emoji2": "\uE170", //  group:Mail and calendar - "appBarIcons\\important": "\uE171", //  group:Mail and calendar - "appBarIcons\\mailreply": "\uE172", //  group:Mail and calendar - "appBarIcons\\slideshow": "\uE173", //  group:Media - "appBarIcons\\sort": "\uE174", //  group:Data - "appBarIcons\\manage": "\uE178", //  group:System - "appBarIcons\\allapps": "\uE179", //  group:System - "appBarIcons\\disconnectdrive": "\uE17A", //  group:System - "appBarIcons\\mapdrive": "\uE17B", //  group:System - "appBarIcons\\newwindow": "\uE17C", //  group:System - "appBarIcons\\openwith": "\uE17D", //  group:System - "appBarIcons\\contactpresence": "\uE181", //  group:Communications - "appBarIcons\\priority": "\uE182", //  group:Mail and calendar - "appBarIcons\\uploadskydrive": "\uE183", //  group:File - "appBarIcons\\gototoday": "\uE184", //  group:Mail and calendar - "appBarIcons\\font": "\uE185", //  group:Editing - "appBarIcons\\fontcolor": "\uE186", //  group:Editing - "appBarIcons\\contact2": "\uE187", //  group:Communications - "appBarIcons\\folder": "\uE188", //  group:File - "appBarIcons\\audio": "\uE189", //  group:Media - "appBarIcons\\placeholder": "\uE18A", //  group:General - "appBarIcons\\view": "\uE18B", //  group:Layout - "appBarIcons\\setlockscreen": "\uE18C", //  group:System - "appBarIcons\\settile": "\uE18D", //  group:System - "appBarIcons\\cc": "\uE190", //  group:Media - "appBarIcons\\stopslideshow": "\uE191", //  group:Media - "appBarIcons\\permissions": "\uE192", //  group:System - "appBarIcons\\highlight": "\uE193", //  group:Editing - "appBarIcons\\disableupdates": "\uE194", //  group:System - "appBarIcons\\unfavorite": "\uE195", //  group:Media - "appBarIcons\\unpin": "\uE196", //  group:System - "appBarIcons\\openlocal": "\uE197", //  group:File - "appBarIcons\\mute": "\uE198", //  group:Media - "appBarIcons\\italic": "\uE199", //  group:Editing - "appBarIcons\\underline": "\uE19A", //  group:Editing - "appBarIcons\\bold": "\uE19B", //  group:Editing - "appBarIcons\\movetofolder": "\uE19C", //  group:File - "appBarIcons\\likedislike": "\uE19D", //  group:Data - "appBarIcons\\dislike": "\uE19E", //  group:Data - "appBarIcons\\like": "\uE19F", //  group:Data - "appBarIcons\\alignright": "\uE1A0", //  group:Editing - "appBarIcons\\aligncenter": "\uE1A1", //  group:Editing - "appBarIcons\\alignleft": "\uE1A2", //  group:Editing - "appBarIcons\\zoom": "\uE1A3", //  group:Layout - "appBarIcons\\zoomout": "\uE1A4", //  group:Layout - "appBarIcons\\openfile": "\uE1A5", //  group:File - "appBarIcons\\otheruser": "\uE1A6", //  group:System - "appBarIcons\\admin": "\uE1A7", //  group:System - "appBarIcons\\street": "\uE1C3", //  group:General - "appBarIcons\\map": "\uE1C4", //  group:General - "appBarIcons\\clearselection": "\uE1C5", //  group:Data - "appBarIcons\\fontdecrease": "\uE1C6", //  group:Editing - "appBarIcons\\fontincrease": "\uE1C7", //  group:Editing - "appBarIcons\\fontsize": "\uE1C8", //  group:Editing - "appBarIcons\\cellphone": "\uE1C9", //  group:Communications - "appBarIcons\\reshare": "\uE1CA", //  group:Communications - "appBarIcons\\tag": "\uE1CB", //  group:Data - "appBarIcons\\repeatone": "\uE1CC", //  group:Media - "appBarIcons\\repeatall": "\uE1CD", //  group:Media - "appBarIcons\\outlinestar": "\uE1CE", //  group:Data - "appBarIcons\\solidstar": "\uE1CF", //  group:Data - "appBarIcons\\calculator": "\uE1D0", //  group:General - "appBarIcons\\directions": "\uE1D1", //  group:General - "appBarIcons\\target": "\uE1D2", //  group:General - "appBarIcons\\library": "\uE1D3", //  group:Media - "appBarIcons\\phonebook": "\uE1D4", //  group:Communications - "appBarIcons\\memo": "\uE1D5", //  group:Communications - "appBarIcons\\microphone": "\uE1D6", //  group:System - "appBarIcons\\postupdate": "\uE1D7", //  group:Communications - "appBarIcons\\backtowindow": "\uE1D8", //  group:Layout - "appBarIcons\\fullscreen": "\uE1D9", //  group:Layout - "appBarIcons\\newfolder": "\uE1DA", //  group:File - "appBarIcons\\calendarreply": "\uE1DB", //  group:Mail and calendar - "appBarIcons\\unsyncfolder": "\uE1DD", //  group:File - "appBarIcons\\reporthacked": "\uE1DE", //  group:Communications - "appBarIcons\\syncfolder": "\uE1DF", //  group:File - "appBarIcons\\blockcontact": "\uE1E0", //  group:Communications - "appBarIcons\\switchapps": "\uE1E1", //  group:System - "appBarIcons\\addfriend": "\uE1E2", //  group:Communications - "appBarIcons\\touchpointer": "\uE1E3", //  group:System - "appBarIcons\\gotostart": "\uE1E4", //  group:System - "appBarIcons\\zerobars": "\uE1E5", //  group:System - "appBarIcons\\onebar": "\uE1E6", //  group:System - "appBarIcons\\twobars": "\uE1E7", //  group:System - "appBarIcons\\threebars": "\uE1E8", //  group:System - "appBarIcons\\fourbars": "\uE1E9" //  group:System -} -); - -}(this)); diff --git a/shared/html/libs/winjs/2.0/js/base.js b/shared/html/libs/winjs/2.0/js/base.js deleted file mode 100644 index 05f1ba6..0000000 --- a/shared/html/libs/winjs/2.0/js/base.js +++ /dev/null @@ -1,17047 +0,0 @@ -/// -/*! - © Microsoft. All rights reserved. - - This library is supported for use in Windows Store apps only. - - Build: 1.0.9600.17018.winblue_gdr.140204-1946 - - Version: Microsoft.WinJS.2.0 -*/ -msWriteProfilerMark("Microsoft.WinJS.2.0 1.0.9600.17018.winblue_gdr.140204-1946 base.js,StartTM"); - -/// -(function baseInit(global, undefined) { - "use strict"; - - function initializeProperties(target, members, prefix) { - var keys = Object.keys(members); - var properties; - var i, len; - for (i = 0, len = keys.length; i < len; i++) { - var key = keys[i]; - var enumerable = key.charCodeAt(0) !== /*_*/95; - var member = members[key]; - if (member && typeof member === 'object') { - if (member.value !== undefined || typeof member.get === 'function' || typeof member.set === 'function') { - if (member.enumerable === undefined) { - member.enumerable = enumerable; - } - if (prefix && member.setName && typeof member.setName === 'function') { - member.setName(prefix + "." + key) - } - properties = properties || {}; - properties[key] = member; - continue; - } - } - if (!enumerable) { - properties = properties || {}; - properties[key] = { value: member, enumerable: enumerable, configurable: true, writable: true } - continue; - } - target[key] = member; - } - if (properties) { - Object.defineProperties(target, properties); - } - } - - (function (rootNamespace) { - - // Create the rootNamespace in the global namespace - if (!global[rootNamespace]) { - global[rootNamespace] = Object.create(Object.prototype); - } - - // Cache the rootNamespace we just created in a local variable - var _rootNamespace = global[rootNamespace]; - if (!_rootNamespace.Namespace) { - _rootNamespace.Namespace = Object.create(Object.prototype); - } - - function defineWithParent(parentNamespace, name, members) { - /// - /// - /// Defines a new namespace with the specified name under the specified parent namespace. - /// - /// - /// The parent namespace. - /// - /// - /// The name of the new namespace. - /// - /// - /// The members of the new namespace. - /// - /// - /// The newly-defined namespace. - /// - /// - var currentNamespace = parentNamespace || {}; - - if (name) { - var namespaceFragments = name.split("."); - for (var i = 0, len = namespaceFragments.length; i < len; i++) { - var namespaceName = namespaceFragments[i]; - if (!currentNamespace[namespaceName]) { - Object.defineProperty(currentNamespace, namespaceName, - { value: {}, writable: false, enumerable: true, configurable: true } - ); - } - currentNamespace = currentNamespace[namespaceName]; - } - } - - if (members) { - initializeProperties(currentNamespace, members, name || ""); - } - - return currentNamespace; - } - - function define(name, members) { - /// - /// - /// Defines a new namespace with the specified name. - /// - /// - /// The name of the namespace. This could be a dot-separated name for nested namespaces. - /// - /// - /// The members of the new namespace. - /// - /// - /// The newly-defined namespace. - /// - /// - return defineWithParent(global, name, members); - } - - var LazyStates = { - uninitialized: 1, - working: 2, - initialized: 3, - }; - - function lazy(f) { - if (typeof f === "string") { - var target = f; - f = function () { - return WinJS.Utilities.getMember(target); - }; - } - var name; - var state = LazyStates.uninitialized; - var result; - return { - setName: function (value) { - name = value; - }, - get: function () { - switch (state) { - case LazyStates.initialized: - return result; - - case LazyStates.uninitialized: - state = LazyStates.working; - try { - msWriteProfilerMark("WinJS.Namespace._lazy:" + name + ",StartTM"); - result = f(); - } finally { - msWriteProfilerMark("WinJS.Namespace._lazy:" + name + ",StopTM"); - state = LazyStates.uninitialized; - } - f = null; - state = LazyStates.initialized; - return result; - - case LazyStates.working: - throw "Illegal: reentrancy on initialization"; - - default: - throw "Illegal"; - } - }, - set: function (value) { - switch (state) { - case LazyStates.working: - throw "Illegal: reentrancy on initialization"; - - default: - state = LazyStates.initialized; - result = value; - break; - } - }, - enumerable: true, - configurable: true, - } - } - - // Establish members of the "WinJS.Namespace" namespace - Object.defineProperties(_rootNamespace.Namespace, { - - defineWithParent: { value: defineWithParent, writable: true, enumerable: true, configurable: true }, - - define: { value: define, writable: true, enumerable: true, configurable: true }, - - _lazy: { value: lazy, writable: true, enumerable: true, configurable: true }, - - }); - - })("WinJS"); - - (function (WinJS) { - - function define(constructor, instanceMembers, staticMembers) { - /// - /// - /// Defines a class using the given constructor and the specified instance members. - /// - /// - /// A constructor function that is used to instantiate this class. - /// - /// - /// The set of instance fields, properties, and methods made available on the class. - /// - /// - /// The set of static fields, properties, and methods made available on the class. - /// - /// - /// The newly-defined class. - /// - /// - constructor = constructor || function () { }; - WinJS.Utilities.markSupportedForProcessing(constructor); - if (instanceMembers) { - initializeProperties(constructor.prototype, instanceMembers); - } - if (staticMembers) { - initializeProperties(constructor, staticMembers); - } - return constructor; - } - - function derive(baseClass, constructor, instanceMembers, staticMembers) { - /// - /// - /// Creates a sub-class based on the supplied baseClass parameter, using prototypal inheritance. - /// - /// - /// The class to inherit from. - /// - /// - /// A constructor function that is used to instantiate this class. - /// - /// - /// The set of instance fields, properties, and methods to be made available on the class. - /// - /// - /// The set of static fields, properties, and methods to be made available on the class. - /// - /// - /// The newly-defined class. - /// - /// - if (baseClass) { - constructor = constructor || function () { }; - var basePrototype = baseClass.prototype; - constructor.prototype = Object.create(basePrototype); - WinJS.Utilities.markSupportedForProcessing(constructor); - Object.defineProperty(constructor.prototype, "constructor", { value: constructor, writable: true, configurable: true, enumerable: true }); - if (instanceMembers) { - initializeProperties(constructor.prototype, instanceMembers); - } - if (staticMembers) { - initializeProperties(constructor, staticMembers); - } - return constructor; - } else { - return define(constructor, instanceMembers, staticMembers); - } - } - - function mix(constructor) { - /// - /// - /// Defines a class using the given constructor and the union of the set of instance members - /// specified by all the mixin objects. The mixin parameter list is of variable length. - /// - /// - /// A constructor function that is used to instantiate this class. - /// - /// - /// The newly-defined class. - /// - /// - constructor = constructor || function () { }; - var i, len; - for (i = 1, len = arguments.length; i < len; i++) { - initializeProperties(constructor.prototype, arguments[i]); - } - return constructor; - } - - // Establish members of "WinJS.Class" namespace - WinJS.Namespace.define("WinJS.Class", { - define: define, - derive: derive, - mix: mix - }); - - })(WinJS); - -})(this); - - -(function baseUtilsInit(global, WinJS) { - "use strict"; - - var hasWinRT = !!global.Windows; - - var strings = { - get notSupportedForProcessing() { return WinJS.Resources._getWinJSString("base/notSupportedForProcessing").value; } - }; - - function nop(v) { - return v; - } - - function getMemberFiltered(name, root, filter) { - return name.split(".").reduce(function (currentNamespace, name) { - if (currentNamespace) { - return filter(currentNamespace[name]); - } - return null; - }, root); - } - - // Establish members of "WinJS.Utilities" namespace - WinJS.Namespace.define("WinJS.Utilities", { - // Used for mocking in tests - _setHasWinRT: { - value: function (value) { - hasWinRT = value; - }, - configurable: false, - writable: false, - enumerable: false - }, - - /// Determine if WinRT is accessible in this script context. - hasWinRT: { - get: function () { return hasWinRT; }, - configurable: false, - enumerable: true - }, - - _getMemberFiltered: getMemberFiltered, - - getMember: function (name, root) { - /// - /// - /// Gets the leaf-level type or namespace specified by the name parameter. - /// - /// - /// The name of the member. - /// - /// - /// The root to start in. Defaults to the global object. - /// - /// - /// The leaf-level type or namespace in the specified parent namespace. - /// - /// - if (!name) { - return null; - } - return getMemberFiltered(name, root || global, nop); - }, - - ready: function (callback, async) { - /// - /// - /// Ensures that the specified function executes only after the DOMContentLoaded event has fired - /// for the current page. - /// - /// A promise that completes after DOMContentLoaded has occurred. - /// - /// A function that executes after DOMContentLoaded has occurred. - /// - /// - /// If true, the callback is executed asynchronously. - /// - /// - return new WinJS.Promise(function (c, e) { - function complete() { - if (callback) { - try { - callback(); - c(); - } - catch (err) { - e(err); - } - } - else { - c(); - } - } - - var readyState = WinJS.Utilities.testReadyState; - if (!readyState) { - if (global.document) { - readyState = document.readyState; - } - else { - readyState = "complete"; - } - } - if (readyState === "complete" || (global.document && document.body !== null)) { - if (async) { - WinJS.Utilities.Scheduler.schedule(function () { - complete(); - }, WinJS.Utilities.Scheduler.Priority.normal, null, "WinJS.Utilities.ready"); - } - else { - complete(); - } - } - else { - global.addEventListener("DOMContentLoaded", complete, false); - } - }); - }, - - /// Determines if strict declarative processing is enabled in this script context. - strictProcessing: { - get: function () { return true; }, - configurable: false, - enumerable: true, - }, - - markSupportedForProcessing: { - value: function (func) { - /// - /// - /// Marks a function as being compatible with declarative processing, such as WinJS.UI.processAll - /// or WinJS.Binding.processAll. - /// - /// - /// The function to be marked as compatible with declarative processing. - /// - /// - /// The input function. - /// - /// - func.supportedForProcessing = true; - return func; - }, - configurable: false, - writable: false, - enumerable: true - }, - - requireSupportedForProcessing: { - value: function (value) { - /// - /// - /// Asserts that the value is compatible with declarative processing, such as WinJS.UI.processAll - /// or WinJS.Binding.processAll. If it is not compatible an exception will be thrown. - /// - /// - /// The value to be tested for compatibility with declarative processing. If the - /// value is a function it must be marked with a property 'supportedForProcessing' - /// with a value of true. - /// - /// - /// The input value. - /// - /// - var supportedForProcessing = true; - - supportedForProcessing = supportedForProcessing && !(value === global); - supportedForProcessing = supportedForProcessing && !(value === global.location); - supportedForProcessing = supportedForProcessing && !(value instanceof HTMLIFrameElement); - supportedForProcessing = supportedForProcessing && !(typeof value === "function" && !value.supportedForProcessing); - - switch (global.frames.length) { - case 0: - break; - - case 1: - supportedForProcessing = supportedForProcessing && !(value === global.frames[0]); - break; - - default: - for (var i = 0, len = global.frames.length; supportedForProcessing && i < len; i++) { - supportedForProcessing = supportedForProcessing && !(value === global.frames[i]); - } - break; - } - - if (supportedForProcessing) { - return value; - } - - throw new WinJS.ErrorFromName("WinJS.Utilities.requireSupportedForProcessing", WinJS.Resources._formatString(strings.notSupportedForProcessing, value)); - }, - configurable: false, - writable: false, - enumerable: true - }, - - _shallowCopy: function _shallowCopy(a) { - // Shallow copy a single object. - return this._mergeAll([a]); - }, - - _merge: function _merge(a, b) { - // Merge 2 objects together into a new object - return this._mergeAll([a, b]); - }, - - _mergeAll: function _mergeAll(list) { - // Merge a list of objects together - var o = {}; - list.forEach(function (part) { - Object.keys(part).forEach(function (k) { - o[k] = part[k]; - }); - }); - return o; - }, - - _getProfilerMarkIdentifier: function (element) { - var profilerMarkIdentifier = ""; - if (element.id) { - profilerMarkIdentifier += " id='" + element.id + "'"; - } - if (element.className) { - profilerMarkIdentifier += " class='" + element.className + "'"; - } - return profilerMarkIdentifier; - } - }); - - WinJS.Namespace.define("WinJS", { - validation: false, - - strictProcessing: { - value: function () { - /// - /// - /// Strict processing is always enforced, this method has no effect. - /// - /// - }, - configurable: false, - writable: false, - enumerable: false - }, - }); -})(this, WinJS); - - -(function logInit() { - "use strict"; - - var spaceR = /\s+/g; - var typeR = /^(error|warn|info|log)$/; - - function format(message, tag, type) { - /// - /// - /// Adds tags and type to a logging message. - /// - /// The message to format. - /// - /// The tag(s) to apply to the message. Separate multiple tags with spaces. - /// - /// The type of the message. - /// The formatted message. - /// - var m = message; - if (typeof (m) === "function") { m = m(); } - - return ((type && typeR.test(type)) ? ("") : (type ? (type + ": ") : "")) + - (tag ? tag.replace(spaceR, ":") + ": " : "") + - m; - } - function defAction(message, tag, type) { - var m = WinJS.Utilities.formatLog(message, tag, type); - console[(type && typeR.test(type)) ? type : "log"](m); - } - function escape(s) { - // \s (whitespace) is used as separator, so don't escape it - return s.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&"); - } - WinJS.Namespace.define("WinJS.Utilities", { - startLog: function (options) { - /// - /// - /// Configures a logger that writes messages containing the specified tags from WinJS.log to console.log. - /// - /// - /// The tags for messages to log. Separate multiple tags with spaces. - /// - /// - /// - /// - /// Configure a logger to write WinJS.log output. - /// - /// - /// May contain .type, .tags, .excludeTags and .action properties. - /// - .type is a required tag. - /// - .excludeTags is a space-separated list of tags, any of which will result in a message not being logged. - /// - .tags is a space-separated list of tags, any of which will result in a message being logged. - /// - .action is a function that, if present, will be called with the log message, tags and type. The default is to log to the console. - /// - /// - options = options || {}; - if (typeof options === "string") { - options = { tags: options }; - } - var el = options.type && new RegExp("^(" + escape(options.type).replace(spaceR, " ").split(" ").join("|") + ")$"); - var not = options.excludeTags && new RegExp("(^|\\s)(" + escape(options.excludeTags).replace(spaceR, " ").split(" ").join("|") + ")(\\s|$)", "i"); - var has = options.tags && new RegExp("(^|\\s)(" + escape(options.tags).replace(spaceR, " ").split(" ").join("|") + ")(\\s|$)", "i"); - var action = options.action || defAction; - - if (!el && !not && !has && !WinJS.log) { - WinJS.log = action; - return; - } - - var result = function (message, tag, type) { - if (!((el && !el.test(type)) // if the expected log level is not satisfied - || (not && not.test(tag)) // if any of the excluded categories exist - || (has && !has.test(tag)))) { // if at least one of the included categories doesn't exist - action(message, tag, type); - } - - result.next && result.next(message, tag, type); - }; - result.next = WinJS.log; - WinJS.log = result; - }, - stopLog: function () { - /// - /// - /// Removes the previously set up logger. - /// - /// - delete WinJS.log; - }, - formatLog: format - }); -})(); - -(function eventsInit(WinJS, undefined) { - "use strict"; - - - function createEventProperty(name) { - var eventPropStateName = "_on" + name + "state"; - - return { - get: function () { - var state = this[eventPropStateName]; - return state && state.userHandler; - }, - set: function (handler) { - var state = this[eventPropStateName]; - if (handler) { - if (!state) { - state = { wrapper: function (evt) { return state.userHandler(evt); }, userHandler: handler }; - Object.defineProperty(this, eventPropStateName, { value: state, enumerable: false, writable:true, configurable: true }); - this.addEventListener(name, state.wrapper, false); - } - state.userHandler = handler; - } else if (state) { - this.removeEventListener(name, state.wrapper, false); - this[eventPropStateName] = null; - } - }, - enumerable: true - } - } - - function createEventProperties(events) { - /// - /// - /// Creates an object that has one property for each name passed to the function. - /// - /// - /// A variable list of property names. - /// - /// - /// The object with the specified properties. The names of the properties are prefixed with 'on'. - /// - /// - var props = {}; - for (var i = 0, len = arguments.length; i < len; i++) { - var name = arguments[i]; - props["on" + name] = createEventProperty(name); - } - return props; - } - - var EventMixinEvent = WinJS.Class.define( - function EventMixinEvent_ctor(type, detail, target) { - this.detail = detail; - this.target = target; - this.timeStamp = Date.now(); - this.type = type; - }, - { - bubbles: { value: false, writable: false }, - cancelable: { value: false, writable: false }, - currentTarget: { - get: function () { return this.target; } - }, - defaultPrevented: { - get: function () { return this._preventDefaultCalled; } - }, - trusted: { value: false, writable: false }, - eventPhase: { value: 0, writable: false }, - target: null, - timeStamp: null, - type: null, - - preventDefault: function () { - this._preventDefaultCalled = true; - }, - stopImmediatePropagation: function () { - this._stopImmediatePropagationCalled = true; - }, - stopPropagation: function () { - } - }, { - supportedForProcessing: false, - } - ); - - var eventMixin = { - _listeners: null, - - addEventListener: function (type, listener, useCapture) { - /// - /// - /// Adds an event listener to the control. - /// - /// - /// The type (name) of the event. - /// - /// - /// The listener to invoke when the event is raised. - /// - /// - /// if true initiates capture, otherwise false. - /// - /// - useCapture = useCapture || false; - this._listeners = this._listeners || {}; - var eventListeners = (this._listeners[type] = this._listeners[type] || []); - for (var i = 0, len = eventListeners.length; i < len; i++) { - var l = eventListeners[i]; - if (l.useCapture === useCapture && l.listener === listener) { - return; - } - } - eventListeners.push({ listener: listener, useCapture: useCapture }); - }, - dispatchEvent: function (type, details) { - /// - /// - /// Raises an event of the specified type and with the specified additional properties. - /// - /// - /// The type (name) of the event. - /// - /// - /// The set of additional properties to be attached to the event object when the event is raised. - /// - /// - /// true if preventDefault was called on the event. - /// - /// - var listeners = this._listeners && this._listeners[type]; - if (listeners) { - var eventValue = new EventMixinEvent(type, details, this); - // Need to copy the array to protect against people unregistering while we are dispatching - listeners = listeners.slice(0, listeners.length); - for (var i = 0, len = listeners.length; i < len && !eventValue._stopImmediatePropagationCalled; i++) { - listeners[i].listener(eventValue); - } - return eventValue.defaultPrevented || false; - } - return false; - }, - removeEventListener: function (type, listener, useCapture) { - /// - /// - /// Removes an event listener from the control. - /// - /// - /// The type (name) of the event. - /// - /// - /// The listener to remove. - /// - /// - /// Specifies whether to initiate capture. - /// - /// - useCapture = useCapture || false; - var listeners = this._listeners && this._listeners[type]; - if (listeners) { - for (var i = 0, len = listeners.length; i < len; i++) { - var l = listeners[i]; - if (l.listener === listener && l.useCapture === useCapture) { - listeners.splice(i, 1); - if (listeners.length === 0) { - delete this._listeners[type]; - } - // Only want to remove one element for each call to removeEventListener - break; - } - } - } - } - }; - - WinJS.Namespace.define("WinJS.Utilities", { - _createEventProperty: createEventProperty, - createEventProperties: createEventProperties, - eventMixin: eventMixin - }); - -})(WinJS); - - -(function resourcesInit(global, WinJS, undefined) { - "use strict"; - - var resourceMap; - var mrtEventHook = false; - var contextChangedET = "contextchanged"; - var resourceContext; - - var ListenerType = WinJS.Class.mix(WinJS.Class.define(null, { /* empty */ }, { supportedForProcessing: false }), WinJS.Utilities.eventMixin); - var listeners = new ListenerType(); - - var strings = { - get malformedFormatStringInput() { return WinJS.Resources._getWinJSString("base/malformedFormatStringInput").value; }, - }; - - WinJS.Namespace.define("WinJS.Resources", { - addEventListener: function (type, listener, useCapture) { - /// - /// - /// Registers an event handler for the specified event. - /// - /// - /// The name of the event to handle. - /// - /// - /// The listener to invoke when the event gets raised. - /// - /// - /// Set to true to register the event handler for the capturing phase; set to false to register for the bubbling phase. - /// - /// - if (WinJS.Utilities.hasWinRT && !mrtEventHook) { - if (type === contextChangedET) { - try { - var resContext = WinJS.Resources._getResourceContext(); - if (resContext) { - resContext.qualifierValues.addEventListener("mapchanged", function (e) { - WinJS.Resources.dispatchEvent(contextChangedET, { qualifier: e.key, changed: e.target[e.key] }); - }, false); - - } else { - // The API can be called in the Background thread (web worker). - Windows.ApplicationModel.Resources.Core.ResourceManager.current.defaultContext.qualifierValues.addEventListener("mapchanged", function (e) { - WinJS.Resources.dispatchEvent(contextChangedET, { qualifier: e.key, changed: e.target[e.key] }); - }, false); - } - mrtEventHook = true; - } catch (e) { - } - } - } - listeners.addEventListener(type, listener, useCapture); - }, - removeEventListener: listeners.removeEventListener.bind(listeners), - dispatchEvent: listeners.dispatchEvent.bind(listeners), - - _formatString: function (string) { - var args = arguments; - if (args.length > 1) { - string = string.replace(/({{)|(}})|{(\d+)}|({)|(})/g, function (unused, left, right, index, illegalLeft, illegalRight) { - if (illegalLeft || illegalRight) { throw WinJS.Resources._formatString(strings.malformedFormatStringInput, illegalLeft || illegalRight); } - return (left && "{") || (right && "}") || args[(index | 0) + 1]; - }); - } - return string; - }, - - _getStringWinRT: function (resourceId) { - if (!resourceMap) { - var mainResourceMap = Windows.ApplicationModel.Resources.Core.ResourceManager.current.mainResourceMap; - try { - resourceMap = mainResourceMap.getSubtree('Resources'); - } - catch (e) { - } - if (!resourceMap) { - resourceMap = mainResourceMap; - } - } - - var stringValue; - var langValue; - var resCandidate; - try { - var resContext = WinJS.Resources._getResourceContext(); - if (resContext) { - resCandidate = resourceMap.getValue(resourceId, resContext); - } else { - resCandidate = resourceMap.getValue(resourceId); - } - - if (resCandidate) { - stringValue = resCandidate.valueAsString; - if (stringValue === undefined) { - stringValue = resCandidate.toString(); - } - } - } - catch (e) { } - - if (!stringValue) { - return { value: resourceId, empty: true }; - } - - try { - langValue = resCandidate.getQualifierValue("Language"); - } - catch (e) { - return { value: stringValue }; - } - - return { value: stringValue, lang: langValue }; - }, - - _getStringJS: function (resourceId) { - var str = global.strings && global.strings[resourceId]; - if (typeof str === "string") { - str = { value: str }; - } - return str || { value: resourceId, empty: true }; - }, - - _getResourceContext: function () { - if (global.document) { - if (!resourceContext) { - resourceContext = Windows.ApplicationModel.Resources.Core.ResourceContext.getForCurrentView(); - } - } - return resourceContext; - } - - }); - - Object.defineProperties(WinJS.Resources, WinJS.Utilities.createEventProperties(contextChangedET)); - - var getStringImpl; - - WinJS.Resources.getString = function (resourceId) { - /// - /// - /// Retrieves the resource string that has the specified resource id. - /// - /// - /// The resource id of the string to retrieve. - /// - /// - /// An object that can contain these properties: - /// - /// value: - /// The value of the requested string. This property is always present. - /// - /// empty: - /// A value that specifies whether the requested string wasn't found. - /// If its true, the string wasn't found. If its false or undefined, - /// the requested string was found. - /// - /// lang: - /// The language of the string, if specified. This property is only present - /// for multi-language resources. - /// - /// - /// - getStringImpl = - getStringImpl || - (WinJS.Utilities.hasWinRT - ? WinJS.Resources._getStringWinRT - : WinJS.Resources._getStringJS); - - return getStringImpl(resourceId); - }; - - -})(this, WinJS); - - -(function promiseInit(global, undefined) { - "use strict"; - - global.Debug && (global.Debug.setNonUserCodeExceptions = true); - - var ListenerType = WinJS.Class.mix(WinJS.Class.define(null, { /*empty*/ }, { supportedForProcessing: false }), WinJS.Utilities.eventMixin); - var promiseEventListeners = new ListenerType(); - // make sure there is a listeners collection so that we can do a more trivial check below - promiseEventListeners._listeners = {}; - var errorET = "error"; - var canceledName = "Canceled"; - var tagWithStack = false; - var tag = { - promise: 0x01, - thenPromise: 0x02, - errorPromise: 0x04, - exceptionPromise: 0x08, - completePromise: 0x10, - }; - tag.all = tag.promise | tag.thenPromise | tag.errorPromise | tag.exceptionPromise | tag.completePromise; - - // - // Global error counter, for each error which enters the system we increment this once and then - // the error number travels with the error as it traverses the tree of potential handlers. - // - // When someone has registered to be told about errors (WinJS.Promise.callonerror) promises - // which are in error will get tagged with a ._errorId field. This tagged field is the - // contract by which nested promises with errors will be identified as chaining for the - // purposes of the callonerror semantics. If a nested promise in error is encountered without - // a ._errorId it will be assumed to be foreign and treated as an interop boundary and - // a new error id will be minted. - // - var error_number = 1; - - // - // The state machine has a interesting hiccup in it with regards to notification, in order - // to flatten out notification and avoid recursion for synchronous completion we have an - // explicit set of *_notify states which are responsible for notifying their entire tree - // of children. They can do this because they know that immediate children are always - // ThenPromise instances and we can therefore reach into their state to access the - // _listeners collection. - // - // So, what happens is that a Promise will be fulfilled through the _completed or _error - // messages at which point it will enter a *_notify state and be responsible for to move - // its children into an (as appropriate) success or error state and also notify that child's - // listeners of the state transition, until leaf notes are reached. - // - - var state_created, // -> working - state_working, // -> error | error_notify | success | success_notify | canceled | waiting - state_waiting, // -> error | error_notify | success | success_notify | waiting_canceled - state_waiting_canceled, // -> error | error_notify | success | success_notify | canceling - state_canceled, // -> error | error_notify | success | success_notify | canceling - state_canceling, // -> error_notify - state_success_notify, // -> success - state_success, // -> . - state_error_notify, // -> error - state_error; // -> . - - // Noop function, used in the various states to indicate that they don't support a given - // message. Named with the somewhat cute name '_' because it reads really well in the states. - - function _() { } - - // Initial state - // - state_created = { - name: "created", - enter: function (promise) { - promise._setState(state_working); - }, - cancel: _, - done: _, - then: _, - _completed: _, - _error: _, - _notify: _, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // Ready state, waiting for a message (completed/error/progress), able to be canceled - // - state_working = { - name: "working", - enter: _, - cancel: function (promise) { - promise._setState(state_canceled); - }, - done: done, - then: then, - _completed: completed, - _error: error, - _notify: _, - _progress: progress, - _setCompleteValue: setCompleteValue, - _setErrorValue: setErrorValue - }; - - // Waiting state, if a promise is completed with a value which is itself a promise - // (has a then() method) it signs up to be informed when that child promise is - // fulfilled at which point it will be fulfilled with that value. - // - state_waiting = { - name: "waiting", - enter: function (promise) { - var waitedUpon = promise._value; - // We can special case our own intermediate promises which are not in a - // terminal state by just pushing this promise as a listener without - // having to create new indirection functions - if (waitedUpon instanceof ThenPromise && - waitedUpon._state !== state_error && - waitedUpon._state !== state_success) { - pushListener(waitedUpon, { promise: promise }); - } else { - var error = function (value) { - if (waitedUpon._errorId) { - promise._chainedError(value, waitedUpon); - } else { - // Because this is an interop boundary we want to indicate that this - // error has been handled by the promise infrastructure before we - // begin a new handling chain. - // - callonerror(promise, value, detailsForHandledError, waitedUpon, error); - promise._error(value); - } - }; - error.handlesOnError = true; - waitedUpon.then( - promise._completed.bind(promise), - error, - promise._progress.bind(promise) - ); - } - }, - cancel: function (promise) { - promise._setState(state_waiting_canceled); - }, - done: done, - then: then, - _completed: completed, - _error: error, - _notify: _, - _progress: progress, - _setCompleteValue: setCompleteValue, - _setErrorValue: setErrorValue - }; - - // Waiting canceled state, when a promise has been in a waiting state and receives a - // request to cancel its pending work it will forward that request to the child promise - // and then waits to be informed of the result. This promise moves itself into the - // canceling state but understands that the child promise may instead push it to a - // different state. - // - state_waiting_canceled = { - name: "waiting_canceled", - enter: function (promise) { - // Initiate a transition to canceling. Triggering a cancel on the promise - // that we are waiting upon may result in a different state transition - // before the state machine pump runs again. - promise._setState(state_canceling); - var waitedUpon = promise._value; - if (waitedUpon.cancel) { - waitedUpon.cancel(); - } - }, - cancel: _, - done: done, - then: then, - _completed: completed, - _error: error, - _notify: _, - _progress: progress, - _setCompleteValue: setCompleteValue, - _setErrorValue: setErrorValue - }; - - // Canceled state, moves to the canceling state and then tells the promise to do - // whatever it might need to do on cancelation. - // - state_canceled = { - name: "canceled", - enter: function (promise) { - // Initiate a transition to canceling. The _cancelAction may change the state - // before the state machine pump runs again. - promise._setState(state_canceling); - promise._cancelAction(); - }, - cancel: _, - done: done, - then: then, - _completed: completed, - _error: error, - _notify: _, - _progress: progress, - _setCompleteValue: setCompleteValue, - _setErrorValue: setErrorValue - }; - - // Canceling state, commits to the promise moving to an error state with an error - // object whose 'name' and 'message' properties contain the string "Canceled" - // - state_canceling = { - name: "canceling", - enter: function (promise) { - var error = new Error(canceledName); - error.name = error.message; - promise._value = error; - promise._setState(state_error_notify); - }, - cancel: _, - done: _, - then: _, - _completed: _, - _error: _, - _notify: _, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // Success notify state, moves a promise to the success state and notifies all children - // - state_success_notify = { - name: "complete_notify", - enter: function (promise) { - promise.done = CompletePromise.prototype.done; - promise.then = CompletePromise.prototype.then; - if (promise._listeners) { - var queue = [promise]; - var p; - while (queue.length) { - p = queue.shift(); - p._state._notify(p, queue); - } - } - promise._setState(state_success); - }, - cancel: _, - done: null, /*error to get here */ - then: null, /*error to get here */ - _completed: _, - _error: _, - _notify: notifySuccess, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // Success state, moves a promise to the success state and does NOT notify any children. - // Some upstream promise is owning the notification pass. - // - state_success = { - name: "success", - enter: function (promise) { - promise.done = CompletePromise.prototype.done; - promise.then = CompletePromise.prototype.then; - promise._cleanupAction(); - }, - cancel: _, - done: null, /*error to get here */ - then: null, /*error to get here */ - _completed: _, - _error: _, - _notify: notifySuccess, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // Error notify state, moves a promise to the error state and notifies all children - // - state_error_notify = { - name: "error_notify", - enter: function (promise) { - promise.done = ErrorPromise.prototype.done; - promise.then = ErrorPromise.prototype.then; - if (promise._listeners) { - var queue = [promise]; - var p; - while (queue.length) { - p = queue.shift(); - p._state._notify(p, queue); - } - } - promise._setState(state_error); - }, - cancel: _, - done: null, /*error to get here*/ - then: null, /*error to get here*/ - _completed: _, - _error: _, - _notify: notifyError, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // Error state, moves a promise to the error state and does NOT notify any children. - // Some upstream promise is owning the notification pass. - // - state_error = { - name: "error", - enter: function (promise) { - promise.done = ErrorPromise.prototype.done; - promise.then = ErrorPromise.prototype.then; - promise._cleanupAction(); - }, - cancel: _, - done: null, /*error to get here*/ - then: null, /*error to get here*/ - _completed: _, - _error: _, - _notify: notifyError, - _progress: _, - _setCompleteValue: _, - _setErrorValue: _ - }; - - // - // The statemachine implementation follows a very particular pattern, the states are specified - // as static stateless bags of functions which are then indirected through the state machine - // instance (a Promise). As such all of the functions on each state have the promise instance - // passed to them explicitly as a parameter and the Promise instance members do a little - // dance where they indirect through the state and insert themselves in the argument list. - // - // We could instead call directly through the promise states however then every caller - // would have to remember to do things like pumping the state machine to catch state transitions. - // - - var PromiseStateMachine = WinJS.Class.define(null, { - _listeners: null, - _nextState: null, - _state: null, - _value: null, - - cancel: function () { - /// - /// - /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't - /// already been fulfilled and cancellation is supported, the promise enters - /// the error state with a value of Error("Canceled"). - /// - /// - this._state.cancel(this); - this._run(); - }, - done: function Promise_done(onComplete, onError, onProgress) { - /// - /// - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// - /// After the handlers have finished executing, this function throws any error that would have been returned - /// from then() as a promise in the error state. - /// - /// - /// The function to be called if the promise is fulfilled successfully with a value. - /// The fulfilled value is passed as the single argument. If the value is null, - /// the fulfilled value is returned. The value returned - /// from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while executing the function, the promise returned - /// by then() moves into the error state. - /// - /// - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function is the fulfilled value of the promise returned by then(). - /// - /// - /// the function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// - /// - this._state.done(this, onComplete, onError, onProgress); - }, - then: function Promise_then(onComplete, onError, onProgress) { - /// - /// - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// - /// - /// The function to be called if the promise is fulfilled successfully with a value. - /// The value is passed as the single argument. If the value is null, the value is returned. - /// The value returned from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while this function is being executed, the promise returned - /// by then() moves into the error state. - /// - /// - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function becomes the fulfilled value of the promise returned by then(). - /// - /// - /// The function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// - /// - /// The promise whose value is the result of executing the complete or - /// error function. - /// - /// - return this._state.then(this, onComplete, onError, onProgress); - }, - - _chainedError: function (value, context) { - var result = this._state._error(this, value, detailsForChainedError, context); - this._run(); - return result; - }, - _completed: function (value) { - var result = this._state._completed(this, value); - this._run(); - return result; - }, - _error: function (value) { - var result = this._state._error(this, value, detailsForError); - this._run(); - return result; - }, - _progress: function (value) { - this._state._progress(this, value); - }, - _setState: function (state) { - this._nextState = state; - }, - _setCompleteValue: function (value) { - this._state._setCompleteValue(this, value); - this._run(); - }, - _setChainedErrorValue: function (value, context) { - var result = this._state._setErrorValue(this, value, detailsForChainedError, context); - this._run(); - return result; - }, - _setExceptionValue: function (value) { - var result = this._state._setErrorValue(this, value, detailsForException); - this._run(); - return result; - }, - _run: function () { - while (this._nextState) { - this._state = this._nextState; - this._nextState = null; - this._state.enter(this); - } - } - }, { - supportedForProcessing: false - }); - - // - // Implementations of shared state machine code. - // - - function completed(promise, value) { - var targetState; - if (value && typeof value === "object" && typeof value.then === "function") { - targetState = state_waiting; - } else { - targetState = state_success_notify; - } - promise._value = value; - promise._setState(targetState); - } - function createErrorDetails(exception, error, promise, id, parent, handler) { - return { - exception: exception, - error: error, - promise: promise, - handler: handler, - id: id, - parent: parent - }; - } - function detailsForHandledError(promise, errorValue, context, handler) { - var exception = context._isException; - var errorId = context._errorId; - return createErrorDetails( - exception ? errorValue : null, - exception ? null : errorValue, - promise, - errorId, - context, - handler - ); - } - function detailsForChainedError(promise, errorValue, context) { - var exception = context._isException; - var errorId = context._errorId; - setErrorInfo(promise, errorId, exception); - return createErrorDetails( - exception ? errorValue : null, - exception ? null : errorValue, - promise, - errorId, - context - ); - } - function detailsForError(promise, errorValue) { - var errorId = ++error_number; - setErrorInfo(promise, errorId); - return createErrorDetails( - null, - errorValue, - promise, - errorId - ); - } - function detailsForException(promise, exceptionValue) { - var errorId = ++error_number; - setErrorInfo(promise, errorId, true); - return createErrorDetails( - exceptionValue, - null, - promise, - errorId - ); - } - function done(promise, onComplete, onError, onProgress) { - var asyncOpID = Debug.msTraceAsyncOperationStarting("WinJS.Promise.done"); - pushListener(promise, { c: onComplete, e: onError, p: onProgress, asyncOpID: asyncOpID }); - } - function error(promise, value, onerrorDetails, context) { - promise._value = value; - callonerror(promise, value, onerrorDetails, context); - promise._setState(state_error_notify); - } - function notifySuccess(promise, queue) { - var value = promise._value; - var listeners = promise._listeners; - if (!listeners) { - return; - } - promise._listeners = null; - var i, len; - for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { - var listener = len === 1 ? listeners : listeners[i]; - var onComplete = listener.c; - var target = listener.promise; - - Debug.msTraceAsyncOperationCompleted(listener.asyncOpID, Debug.MS_ASYNC_OP_STATUS_SUCCESS); - - if (target) { - Debug.msTraceAsyncCallbackStarting(listener.asyncOpID); - try { - target._setCompleteValue(onComplete ? onComplete(value) : value); - } catch (ex) { - target._setExceptionValue(ex); - } finally { - Debug.msTraceAsyncCallbackCompleted(); - } - if (target._state !== state_waiting && target._listeners) { - queue.push(target); - } - } else { - CompletePromise.prototype.done.call(promise, onComplete); - } - } - } - function notifyError(promise, queue) { - var value = promise._value; - var listeners = promise._listeners; - if (!listeners) { - return; - } - promise._listeners = null; - var i, len; - for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { - var listener = len === 1 ? listeners : listeners[i]; - var onError = listener.e; - var target = listener.promise; - - var errorID = (value && value.name === canceledName ? Debug.MS_ASYNC_OP_STATUS_CANCELED : Debug.MS_ASYNC_OP_STATUS_ERROR); - Debug.msTraceAsyncOperationCompleted(listener.asyncOpID, errorID); - - if (target) { - var asyncCallbackStarted = false; - try { - if (onError) { - Debug.msTraceAsyncCallbackStarting(listener.asyncOpID); - asyncCallbackStarted = true; - if (!onError.handlesOnError) { - callonerror(target, value, detailsForHandledError, promise, onError); - } - target._setCompleteValue(onError(value)) - } else { - target._setChainedErrorValue(value, promise); - } - } catch (ex) { - target._setExceptionValue(ex); - } finally { - if (asyncCallbackStarted) { - Debug.msTraceAsyncCallbackCompleted(); - } - } - if (target._state !== state_waiting && target._listeners) { - queue.push(target); - } - } else { - ErrorPromise.prototype.done.call(promise, null, onError); - } - } - } - function callonerror(promise, value, onerrorDetailsGenerator, context, handler) { - if (promiseEventListeners._listeners[errorET]) { - if (value instanceof Error && value.message === canceledName) { - return; - } - promiseEventListeners.dispatchEvent(errorET, onerrorDetailsGenerator(promise, value, context, handler)); - } - } - function progress(promise, value) { - var listeners = promise._listeners; - if (listeners) { - var i, len; - for (i = 0, len = Array.isArray(listeners) ? listeners.length : 1; i < len; i++) { - var listener = len === 1 ? listeners : listeners[i]; - var onProgress = listener.p; - if (onProgress) { - try { onProgress(value); } catch (ex) { } - } - if (!(listener.c || listener.e) && listener.promise) { - listener.promise._progress(value); - } - } - } - } - function pushListener(promise, listener) { - var listeners = promise._listeners; - if (listeners) { - // We may have either a single listener (which will never be wrapped in an array) - // or 2+ listeners (which will be wrapped). Since we are now adding one more listener - // we may have to wrap the single listener before adding the second. - listeners = Array.isArray(listeners) ? listeners : [listeners]; - listeners.push(listener); - } else { - listeners = listener; - } - promise._listeners = listeners; - } - // The difference beween setCompleteValue()/setErrorValue() and complete()/error() is that setXXXValue() moves - // a promise directly to the success/error state without starting another notification pass (because one - // is already ongoing). - function setErrorInfo(promise, errorId, isException) { - promise._isException = isException || false; - promise._errorId = errorId; - } - function setErrorValue(promise, value, onerrorDetails, context) { - promise._value = value; - callonerror(promise, value, onerrorDetails, context); - promise._setState(state_error); - } - function setCompleteValue(promise, value) { - var targetState; - if (value && typeof value === "object" && typeof value.then === "function") { - targetState = state_waiting; - } else { - targetState = state_success; - } - promise._value = value; - promise._setState(targetState); - } - function then(promise, onComplete, onError, onProgress) { - var result = new ThenPromise(promise); - var asyncOpID = Debug.msTraceAsyncOperationStarting("WinJS.Promise.then"); - pushListener(promise, { promise: result, c: onComplete, e: onError, p: onProgress, asyncOpID: asyncOpID }); - return result; - } - - // - // Internal implementation detail promise, ThenPromise is created when a promise needs - // to be returned from a then() method. - // - var ThenPromise = WinJS.Class.derive(PromiseStateMachine, - function (creator) { - - if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.thenPromise))) { - this._stack = WinJS.Promise._getStack(); - } - - this._creator = creator; - this._setState(state_created); - this._run(); - }, { - _creator: null, - - _cancelAction: function () { if (this._creator) { this._creator.cancel(); } }, - _cleanupAction: function () { this._creator = null; } - }, { - supportedForProcessing: false - } - ); - - // - // Slim promise implementations for already completed promises, these are created - // under the hood on synchronous completion paths as well as by WinJS.Promise.wrap - // and WinJS.Promise.wrapError. - // - - var ErrorPromise = WinJS.Class.define( - function ErrorPromise_ctor(value) { - - if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.errorPromise))) { - this._stack = WinJS.Promise._getStack(); - } - - this._value = value; - callonerror(this, value, detailsForError); - }, { - cancel: function () { - /// - /// - /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't - /// already been fulfilled and cancellation is supported, the promise enters - /// the error state with a value of Error("Canceled"). - /// - /// - }, - done: function ErrorPromise_done(unused, onError) { - /// - /// - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// - /// After the handlers have finished executing, this function throws any error that would have been returned - /// from then() as a promise in the error state. - /// - /// - /// The function to be called if the promise is fulfilled successfully with a value. - /// The fulfilled value is passed as the single argument. If the value is null, - /// the fulfilled value is returned. The value returned - /// from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while executing the function, the promise returned - /// by then() moves into the error state. - /// - /// - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function is the fulfilled value of the promise returned by then(). - /// - /// - /// the function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// - /// - var value = this._value; - if (onError) { - try { - if (!onError.handlesOnError) { - callonerror(null, value, detailsForHandledError, this, onError); - } - var result = onError(value); - if (result && typeof result === "object" && typeof result.done === "function") { - // If a promise is returned we need to wait on it. - result.done(); - } - return; - } catch (ex) { - value = ex; - } - } - if (value instanceof Error && value.message === canceledName) { - // suppress cancel - return; - } - // force the exception to be thrown asyncronously to avoid any try/catch blocks - // - WinJS.Utilities.Scheduler.schedule(function () { - throw value; - }, WinJS.Utilities.Scheduler.Priority.normal, null, "WinJS.Promise._throwException"); - }, - then: function ErrorPromise_then(unused, onError) { - /// - /// - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// - /// - /// The function to be called if the promise is fulfilled successfully with a value. - /// The value is passed as the single argument. If the value is null, the value is returned. - /// The value returned from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while this function is being executed, the promise returned - /// by then() moves into the error state. - /// - /// - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function becomes the fulfilled value of the promise returned by then(). - /// - /// - /// The function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// - /// - /// The promise whose value is the result of executing the complete or - /// error function. - /// - /// - - // If the promise is already in a error state and no error handler is provided - // we optimize by simply returning the promise instead of creating a new one. - // - if (!onError) { return this; } - var result; - var value = this._value; - try { - if (!onError.handlesOnError) { - callonerror(null, value, detailsForHandledError, this, onError); - } - result = new CompletePromise(onError(value)); - } catch (ex) { - // If the value throw from the error handler is the same as the value - // provided to the error handler then there is no need for a new promise. - // - if (ex === value) { - result = this; - } else { - result = new ExceptionPromise(ex); - } - } - return result; - } - }, { - supportedForProcessing: false - } - ); - - var ExceptionPromise = WinJS.Class.derive(ErrorPromise, - function ExceptionPromise_ctor(value) { - - if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.exceptionPromise))) { - this._stack = WinJS.Promise._getStack(); - } - - this._value = value; - callonerror(this, value, detailsForException); - }, { - /* empty */ - }, { - supportedForProcessing: false - } - ); - - var CompletePromise = WinJS.Class.define( - function CompletePromise_ctor(value) { - - if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.completePromise))) { - this._stack = WinJS.Promise._getStack(); - } - - if (value && typeof value === "object" && typeof value.then === "function") { - var result = new ThenPromise(null); - result._setCompleteValue(value); - return result; - } - this._value = value; - }, { - cancel: function () { - /// - /// - /// Attempts to cancel the fulfillment of a promised value. If the promise hasn't - /// already been fulfilled and cancellation is supported, the promise enters - /// the error state with a value of Error("Canceled"). - /// - /// - }, - done: function CompletePromise_done(onComplete) { - /// - /// - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// - /// After the handlers have finished executing, this function throws any error that would have been returned - /// from then() as a promise in the error state. - /// - /// - /// The function to be called if the promise is fulfilled successfully with a value. - /// The fulfilled value is passed as the single argument. If the value is null, - /// the fulfilled value is returned. The value returned - /// from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while executing the function, the promise returned - /// by then() moves into the error state. - /// - /// - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function is the fulfilled value of the promise returned by then(). - /// - /// - /// the function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// - /// - if (!onComplete) { return; } - try { - var result = onComplete(this._value); - if (result && typeof result === "object" && typeof result.done === "function") { - result.done(); - } - } catch (ex) { - // force the exception to be thrown asynchronously to avoid any try/catch blocks - WinJS.Utilities.Scheduler.schedule(function () { - throw ex; - }, WinJS.Utilities.Scheduler.Priority.normal, null, "WinJS.Promise._throwException"); - } - }, - then: function CompletePromise_then(onComplete) { - /// - /// - /// Allows you to specify the work to be done on the fulfillment of the promised value, - /// the error handling to be performed if the promise fails to fulfill - /// a value, and the handling of progress notifications along the way. - /// - /// - /// The function to be called if the promise is fulfilled successfully with a value. - /// The value is passed as the single argument. If the value is null, the value is returned. - /// The value returned from the function becomes the fulfilled value of the promise returned by - /// then(). If an exception is thrown while this function is being executed, the promise returned - /// by then() moves into the error state. - /// - /// - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. If it is null, the error is forwarded. - /// The value returned from the function becomes the fulfilled value of the promise returned by then(). - /// - /// - /// The function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// - /// - /// The promise whose value is the result of executing the complete or - /// error function. - /// - /// - try { - // If the value returned from the completion handler is the same as the value - // provided to the completion handler then there is no need for a new promise. - // - var newValue = onComplete ? onComplete(this._value) : this._value; - return newValue === this._value ? this : new CompletePromise(newValue); - } catch (ex) { - return new ExceptionPromise(ex); - } - } - }, { - supportedForProcessing: false - } - ); - - // - // Promise is the user-creatable WinJS.Promise object. - // - - function timeout(timeoutMS) { - var id; - return new WinJS.Promise( - function (c) { - if (timeoutMS) { - id = setTimeout(c, timeoutMS); - } else { - setImmediate(c); - } - }, - function () { - if (id) { - clearTimeout(id); - } - } - ); - } - - function timeoutWithPromise(timeout, promise) { - var cancelPromise = function () { promise.cancel(); } - var cancelTimeout = function () { timeout.cancel(); } - timeout.then(cancelPromise); - promise.then(cancelTimeout, cancelTimeout); - return promise; - } - - var staticCanceledPromise; - - var Promise = WinJS.Class.derive(PromiseStateMachine, - function Promise_ctor(init, oncancel) { - /// - /// - /// A promise provides a mechanism to schedule work to be done on a value that - /// has not yet been computed. It is a convenient abstraction for managing - /// interactions with asynchronous APIs. - /// - /// - /// The function that is called during construction of the promise. The function - /// is given three arguments (complete, error, progress). Inside this function - /// you should add event listeners for the notifications supported by this value. - /// - /// - /// The function to call if a consumer of this promise wants - /// to cancel its undone work. Promises are not required to - /// support cancellation. - /// - /// - - if (tagWithStack && (tagWithStack === true || (tagWithStack & tag.promise))) { - this._stack = WinJS.Promise._getStack(); - } - - this._oncancel = oncancel; - this._setState(state_created); - this._run(); - - try { - var complete = this._completed.bind(this); - var error = this._error.bind(this); - var progress = this._progress.bind(this); - init(complete, error, progress); - } catch (ex) { - this._setExceptionValue(ex); - } - }, { - _oncancel: null, - - _cancelAction: function () { - if (this._oncancel) { - try { this._oncancel(); } catch (ex) { } - } - }, - _cleanupAction: function () { this._oncancel = null; } - }, { - - addEventListener: function Promise_addEventListener(eventType, listener, capture) { - /// - /// - /// Adds an event listener to the control. - /// - /// - /// The type (name) of the event. - /// - /// - /// The listener to invoke when the event is raised. - /// - /// - /// Specifies whether or not to initiate capture. - /// - /// - promiseEventListeners.addEventListener(eventType, listener, capture); - }, - any: function Promise_any(values) { - /// - /// - /// Returns a promise that is fulfilled when one of the input promises - /// has been fulfilled. - /// - /// - /// An array that contains promise objects or objects whose property - /// values include promise objects. - /// - /// - /// A promise that on fulfillment yields the value of the input (complete or error). - /// - /// - return new Promise( - function (complete, error, progress) { - var keys = Object.keys(values); - var errors = Array.isArray(values) ? [] : {}; - if (keys.length === 0) { - complete(); - } - var canceled = 0; - keys.forEach(function (key) { - Promise.as(values[key]).then( - function () { complete({ key: key, value: values[key] }); }, - function (e) { - if (e instanceof Error && e.name === canceledName) { - if ((++canceled) === keys.length) { - complete(WinJS.Promise.cancel); - } - return; - } - error({ key: key, value: values[key] }); - } - ); - }); - }, - function () { - var keys = Object.keys(values); - keys.forEach(function (key) { - var promise = Promise.as(values[key]); - if (typeof promise.cancel === "function") { - promise.cancel(); - } - }); - } - ); - }, - as: function Promise_as(value) { - /// - /// - /// Returns a promise. If the object is already a promise it is returned; - /// otherwise the object is wrapped in a promise. - /// - /// - /// The value to be treated as a promise. - /// - /// - /// A promise. - /// - /// - if (value && typeof value === "object" && typeof value.then === "function") { - return value; - } - return new CompletePromise(value); - }, - /// - /// Canceled promise value, can be returned from a promise completion handler - /// to indicate cancelation of the promise chain. - /// - cancel: { - get: function () { - return (staticCanceledPromise = staticCanceledPromise || new ErrorPromise(new WinJS.ErrorFromName(canceledName))); - } - }, - dispatchEvent: function Promise_dispatchEvent(eventType, details) { - /// - /// - /// Raises an event of the specified type and properties. - /// - /// - /// The type (name) of the event. - /// - /// - /// The set of additional properties to be attached to the event object. - /// - /// - /// Specifies whether preventDefault was called on the event. - /// - /// - return promiseEventListeners.dispatchEvent(eventType, details); - }, - is: function Promise_is(value) { - /// - /// - /// Determines whether a value fulfills the promise contract. - /// - /// - /// A value that may be a promise. - /// - /// - /// true if the specified value is a promise, otherwise false. - /// - /// - return value && typeof value === "object" && typeof value.then === "function"; - }, - join: function Promise_join(values) { - /// - /// - /// Creates a promise that is fulfilled when all the values are fulfilled. - /// - /// - /// An object whose fields contain values, some of which may be promises. - /// - /// - /// A promise whose value is an object with the same field names as those of the object in the values parameter, where - /// each field value is the fulfilled value of a promise. - /// - /// - return new Promise( - function (complete, error, progress) { - var keys = Object.keys(values); - var errors = Array.isArray(values) ? [] : {}; - var results = Array.isArray(values) ? [] : {}; - var undefineds = 0; - var pending = keys.length; - var argDone = function (key) { - if ((--pending) === 0) { - var errorCount = Object.keys(errors).length; - if (errorCount === 0) { - complete(results); - } else { - var canceledCount = 0; - keys.forEach(function (key) { - var e = errors[key]; - if (e instanceof Error && e.name === canceledName) { - canceledCount++; - } - }); - if (canceledCount === errorCount) { - complete(WinJS.Promise.cancel); - } else { - error(errors); - } - } - } else { - progress({ Key: key, Done: true }); - } - }; - keys.forEach(function (key) { - var value = values[key]; - if (value === undefined) { - undefineds++; - } else { - Promise.then(value, - function (value) { results[key] = value; argDone(key); }, - function (value) { errors[key] = value; argDone(key); } - ); - } - }); - pending -= undefineds; - if (pending === 0) { - complete(results); - return; - } - }, - function () { - Object.keys(values).forEach(function (key) { - var promise = Promise.as(values[key]); - if (typeof promise.cancel === "function") { - promise.cancel(); - } - }); - } - ); - }, - removeEventListener: function Promise_removeEventListener(eventType, listener, capture) { - /// - /// - /// Removes an event listener from the control. - /// - /// - /// The type (name) of the event. - /// - /// - /// The listener to remove. - /// - /// - /// Specifies whether or not to initiate capture. - /// - /// - promiseEventListeners.removeEventListener(eventType, listener, capture); - }, - supportedForProcessing: false, - then: function Promise_then(value, onComplete, onError, onProgress) { - /// - /// - /// A static version of the promise instance method then(). - /// - /// - /// the value to be treated as a promise. - /// - /// - /// The function to be called if the promise is fulfilled with a value. - /// If it is null, the promise simply - /// returns the value. The value is passed as the single argument. - /// - /// - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. - /// - /// - /// The function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// - /// - /// A promise whose value is the result of executing the provided complete function. - /// - /// - return Promise.as(value).then(onComplete, onError, onProgress); - }, - thenEach: function Promise_thenEach(values, onComplete, onError, onProgress) { - /// - /// - /// Performs an operation on all the input promises and returns a promise - /// that has the shape of the input and contains the result of the operation - /// that has been performed on each input. - /// - /// - /// A set of values (which could be either an array or an object) of which some or all are promises. - /// - /// - /// The function to be called if the promise is fulfilled with a value. - /// If the value is null, the promise returns the value. - /// The value is passed as the single argument. - /// - /// - /// The function to be called if the promise is fulfilled with an error. The error - /// is passed as the single argument. - /// - /// - /// The function to be called if the promise reports progress. Data about the progress - /// is passed as the single argument. Promises are not required to support - /// progress. - /// - /// - /// A promise that is the result of calling Promise.join on the values parameter. - /// - /// - var result = Array.isArray(values) ? [] : {}; - Object.keys(values).forEach(function (key) { - result[key] = Promise.as(values[key]).then(onComplete, onError, onProgress); - }); - return Promise.join(result); - }, - timeout: function Promise_timeout(time, promise) { - /// - /// - /// Creates a promise that is fulfilled after a timeout. - /// - /// - /// The timeout period in milliseconds. If this value is zero or not specified - /// setImmediate is called, otherwise setTimeout is called. - /// - /// - /// A promise that will be canceled if it doesn't complete before the - /// timeout has expired. - /// - /// - /// A promise that is completed asynchronously after the specified timeout. - /// - /// - var to = timeout(time); - return promise ? timeoutWithPromise(to, promise) : to; - }, - wrap: function Promise_wrap(value) { - /// - /// - /// Wraps a non-promise value in a promise. You can use this function if you need - /// to pass a value to a function that requires a promise. - /// - /// - /// Some non-promise value to be wrapped in a promise. - /// - /// - /// A promise that is successfully fulfilled with the specified value - /// - /// - return new CompletePromise(value); - }, - wrapError: function Promise_wrapError(error) { - /// - /// - /// Wraps a non-promise error value in a promise. You can use this function if you need - /// to pass an error to a function that requires a promise. - /// - /// - /// A non-promise error value to be wrapped in a promise. - /// - /// - /// A promise that is in an error state with the specified value. - /// - /// - return new ErrorPromise(error); - }, - - _veryExpensiveTagWithStack: { - get: function () { return tagWithStack; }, - set: function (value) { tagWithStack = value; } - }, - _veryExpensiveTagWithStack_tag: tag, - _getStack: function () { - if (Debug.debuggerEnabled) { - try { throw new Error(); } catch (e) { return e.stack; } - } - }, - - _cancelBlocker: function Promise__cancelBlocker(input) { - // - // Returns a promise which on cancelation will still result in downstream cancelation while - // protecting the promise 'input' from being canceled which has the effect of allowing - // 'input' to be shared amoung various consumers. - // - if (!Promise.is(input)) { - return Promise.wrap(input); - } - var complete; - var error; - var output = new WinJS.Promise( - function (c, e) { - complete = c; - error = e; - }, - function () { - complete = null; - error = null; - } - ); - input.then( - function (v) { complete && complete(v); }, - function (e) { error && error(e); } - ); - return output; - }, - - } - ); - Object.defineProperties(Promise, WinJS.Utilities.createEventProperties(errorET)); - - var SignalPromise = WinJS.Class.derive(PromiseStateMachine, - function (cancel) { - this._oncancel = cancel; - this._setState(state_created); - this._run(); - }, { - _cancelAction: function () { this._oncancel && this._oncancel(); }, - _cleanupAction: function () { this._oncancel = null; } - }, { - supportedForProcessing: false - } - ); - - var Signal = WinJS.Class.define( - function Signal_ctor(oncancel) { - this._promise = new SignalPromise(oncancel); - }, { - promise: { - get: function () { return this._promise; } - }, - - cancel: function Signal_cancel() { - this._promise.cancel(); - }, - complete: function Signal_complete(value) { - this._promise._completed(value); - }, - error: function Signal_error(value) { - this._promise._error(value); - }, - progress: function Signal_progress(value) { - this._promise._progress(value); - } - }, { - supportedForProcessing: false, - } - ); - - // Publish WinJS.Promise - // - WinJS.Namespace.define("WinJS", { - Promise: Promise, - _Signal: Signal - }); - -}(this)); - -(function linkedListMixinInit(global, undefined) { - "use strict"; - - function linkedListMixin(name) { - var mixin = {}; - var PREV = "_prev" + name; - var NEXT = "_next" + name; - mixin["_remove" + name] = function () { - // Assumes we always have a static head and tail. - // - var prev = this[PREV]; - var next = this[NEXT]; - // PREV <-> NEXT - // - next && (next[PREV] = prev); - prev && (prev[NEXT] = next); - // null <- this -> null - // - this[PREV] = null; - this[NEXT] = null; - }; - mixin["_insert" + name + "Before"] = function (node) { - var prev = this[PREV]; - // PREV -> node -> this - // - prev && (prev[NEXT] = node); - node[NEXT] = this; - // PREV <- node <- this - // - node[PREV] = prev; - this[PREV] = node; - - return node; - }; - mixin["_insert" + name + "After"] = function (node) { - var next = this[NEXT]; - // this -> node -> NEXT - // - this[NEXT] = node; - node[NEXT] = next; - // this <- node <- NEXT - // - node[PREV] = this; - next && (next[PREV] = node); - - return node; - }; - return mixin; - } - - WinJS.Namespace.define("WinJS.Utilities", { - - _linkedListMixin: linkedListMixin - - }); - -}(this)); - -(function schedulerInit(global, undefined) { - "use strict"; - - var Promise = WinJS.Promise; - var linkedListMixin = WinJS.Utilities._linkedListMixin; - - var strings = { - get jobInfoIsNoLongerValid() { return WinJS.Resources._getWinJSString("base/jobInfoIsNoLongerValid").value; } - }; - - // - // Profiler mark helpers - // - // markerType must be one of the following: info, StartTM, StopTM - // - - function profilerMarkArgs(arg0, arg1, arg2) { - if (arg2 !== undefined) { - return "(" + arg0 + ";" + arg1 + ";" + arg2 + ")"; - } else if (arg1 !== undefined) { - return "(" + arg0 + ";" + arg1 + ")"; - } else if (arg0 !== undefined) { - return "(" + arg0 + ")"; - } else { - return ""; - } - } - - function schedulerProfilerMark(operation, markerType, arg0, arg1) { - msWriteProfilerMark( - "WinJS.Scheduler:" + operation + - profilerMarkArgs(arg0, arg1) + - "," + markerType - ); - } - - function jobProfilerMark(job, operation, markerType, arg0, arg1) { - var argProvided = job.name || arg0 !== undefined || arg1 !== undefined; - - msWriteProfilerMark( - "WinJS.Scheduler:" + operation + ":" + job.id + - (argProvided ? profilerMarkArgs(job.name, arg0, arg1) : "") + - "," + markerType - ); - } - - // - // Job type. This cannot be instantiated by developers and is instead handed back by the scheduler - // schedule method. Its public interface is what is used when interacting with a job. - // - - var JobNode = WinJS.Class.define(function (id, work, priority, context, name, asyncOpID) { - this._id = id; - this._work = work; - this._context = context; - this._name = name; - this._asyncOpID = asyncOpID; - this._setPriority(priority); - this._setState(state_created); - jobProfilerMark(this, "job-scheduled", "info"); - }, { - - /// - /// Gets a value that indicates whether the job has completed. This value is true if job has run to completion - /// and false if it hasn't yet run or was canceled. - /// - completed: { - get: function () { return !!this._state.completed; } - }, - - /// - /// Gets the unique identifier for this job. - /// - id: { - get: function () { return this._id; } - }, - - /// - /// Gets or sets a string that specifies the diagnostic name for this job. - /// - name: { - get: function () { return this._name; }, - set: function (value) { this._name = value; } - }, - - /// - /// Gets an owner token for the job. You can use this owner token�s cancelAll method to cancel related jobs. - /// - owner: { - get: function () { return this._owner; }, - set: function (value) { - this._owner && this._owner._remove(this); - this._owner = value; - this._owner && this._owner._add(this); - } - }, - - /// - /// Gets or sets the priority at which this job is executed by the scheduler. - /// - priority: { - get: function () { return this._priority; }, - set: function (value) { - value = clampPriority(value); - this._state.setPriority(this, value); - } - }, - - cancel: function () { - /// - /// Cancels the job. - /// - this._state.cancel(this); - }, - - pause: function () { - /// - /// Pauses the job. - /// - this._state.pause(this); - }, - - resume: function () { - /// - /// Resumes the job if it's been paused. - /// - this._state.resume(this); - }, - - _execute: function (shouldYield) { - this._state.execute(this, shouldYield); - }, - - _executeDone: function (result) { - return this._state.executeDone(this, result); - }, - - _blockedDone: function (result) { - return this._state.blockedDone(this, result); - }, - - _setPriority: function (value) { - if (+this._priority === this._priority && this._priority !== value) { - jobProfilerMark(this, "job-priority-changed", "info", - markerFromPriority(this._priority).name, - markerFromPriority(value).name); - } - this._priority = value; - }, - - _setState: function (state, arg0, arg1) { - if (this._state) { - WinJS.log && WinJS.log("Transitioning job (" + this.id + ") from: " + this._state.name + " to: " + state.name, "winjs scheduler", "log"); - } - this._state = state; - this._state.enter(this, arg0, arg1); - }, - - }); - WinJS.Class.mix(JobNode, linkedListMixin("Job")); - - var YieldPolicy = { - complete: 1, - continue: 2, - block: 3, - }; - - // - // JobInfo object is passed to a work item when it is executed and allows the work to ask whether it - // should cooperatively yield and in that event provide a continuation work function to run the - // next time this job is scheduled. The JobInfo object additionally allows access to the job itself - // and the ability to provide a Promise for a future continuation work function in order to have - // jobs easily block on async work. - // - - var JobInfo = WinJS.Class.define(function (shouldYield, job) { - this._job = job; - this._result = null; - this._yieldPolicy = YieldPolicy.complete; - this._shouldYield = shouldYield; - }, { - - /// - /// The job instance for which the work is currently being executed. - /// - job: { - get: function () { - this._throwIfDisabled(); - return this._job; - } - }, - - /// - /// A boolean which will become true when the work item is requested to cooperatively yield by the scheduler. - /// - shouldYield: { - get: function () { - this._throwIfDisabled(); - return this._shouldYield(); - } - }, - - setPromise: function (promise) { - /// - /// - /// Called when the work item is blocked on asynchronous work. - /// The scheduler waits for the specified Promise to complete before rescheduling the job. - /// - /// - /// A Promise value which, when completed, provides a work item function to be re-scheduled. - /// - /// - this._throwIfDisabled(); - this._result = promise; - this._yieldPolicy = YieldPolicy.block; - }, - - setWork: function (work) { - /// - /// - /// Called when the work item is cooperatively yielding to the scheduler and has more work to complete in the future. - /// Use this method to schedule additonal work for when the work item is about to yield. - /// - /// - /// The work function which will be re-scheduled. - /// - /// - this._throwIfDisabled(); - this._result = work; - this._yieldPolicy = YieldPolicy.continue; - }, - - _disablePublicApi: function () { - // _disablePublicApi should be called as soon as the job yields. This - // says that the job info object should no longer be used by the - // job and if the job tries to use it, job info will throw. - // - this._publicApiDisabled = true; - }, - - _throwIfDisabled: function () { - if (this._publicApiDisabled) { - throw new WinJS.ErrorFromName("WinJS.Utilities.Scheduler.JobInfoIsNoLongerValid", strings.jobInfoIsNoLongerValid); - } - } - - }); - - // - // Owner type. Made available to developers through the createOwnerToken method. - // Allows cancelation of jobs in bulk. - // - - var OwnerToken = WinJS.Class.define(function OwnerToken_ctor() { - this._jobs = {}; - }, { - cancelAll: function OwnerToken_cancelAll() { - /// - /// - /// Cancels all jobs that are associated with this owner token. - /// - /// - var jobs = this._jobs, - jobIds = Object.keys(jobs); - this._jobs = {}; - - for (var i = 0, len = jobIds.length; i < len; i++) { - jobs[jobIds[i]].cancel(); - } - }, - - _add: function OwnerToken_add(job) { - this._jobs[job.id] = job; - }, - - _remove: function OwnerToken_remove(job) { - delete this._jobs[job.id]; - } - }); - - function _() { - // Noop function, used in the various states to indicate that they don't support a given - // message. Named with the somewhat cute name '_' because it reads really well in the states. - // - return false; - } - function illegal(job) { - throw "Illegal call by job(" + job.id + ") in state: " + this.name; - } - - // - // Scheduler job state machine. - // - // A job normally goes through a lifecycle which is created -> scheduled -> running -> complete. The - // Scheduler decides when to transition a job from scheduled to running based on its policies and - // the other work which is scheduled. - // - // Additionally there are various operations which can be performed on a job which will change its - // state like: cancel, pause, resume and setting the job's priority. - // - // Additionally when in the running state a job may either cooperatively yield, or block. - // - // The job state machine accounts for these various states and interactions. - // - - var State = WinJS.Class.define(function (name) { - this.name = name; - this.enter = illegal; - this.execute = illegal; - this.executeDone = illegal; - this.blockedDone = illegal; - this.cancel = illegal; - this.pause = illegal; - this.resume = illegal; - this.setPriority = illegal; - }); - - var state_created = new State("created"), // -> scheduled - state_scheduled = new State("scheduled"), // -> running | canceled | paused - state_paused = new State("paused"), // -> canceled | scheduled - state_canceled = new State("canceled"), // -> . - state_running = new State("running"), // -> cooperative_yield | blocked | complete | running_canceled | running_paused - state_running_paused = new State("running_paused"), // -> cooperative_yield_paused | blocked_paused | complete | running_canceled | running_resumed - state_running_resumed = new State("running_resumed"), // -> cooperative_yield | blocked | complete | running_canceled | running_paused - state_running_canceled = new State("running_canceled"), // -> canceled | running_canceled_blocked - state_running_canceled_blocked = new State("running_canceled_blocked"), // -> canceled - state_cooperative_yield = new State("cooperative_yield"), // -> scheduled - state_cooperative_yield_paused = new State("cooperative_yield_paused"), // -> paused - state_blocked = new State("blocked"), // -> blocked_waiting - state_blocked_waiting = new State("blocked_waiting"), // -> cooperative_yield | complete | blocked_canceled | blocked_paused_waiting - state_blocked_paused = new State("blocked_paused"), // -> blocked_paused_waiting - state_blocked_paused_waiting = new State("blocked_paused_waiting"), // -> cooperative_yield_paused | complete | blocked_canceled | blocked_waiting - state_blocked_canceled = new State("blocked_canceled"), // -> canceled - state_complete = new State("complete"); // -> . - - // A given state may include implementations for the following operations: - // - // - enter(job, arg0, arg1) - // - execute(job, shouldYield) - // - executeDone(job, result) --> next state - // - blockedDone(job, result, initialPriority) - // - cancel(job) - // - pause(job) - // - resume(job) - // - setPriority(job, priority) - // - // Any functions which are not implemented are illegal in that state. - // Any functions which have an implementation of _ are a nop in that state. - // - - // Helper which yields a function that transitions to the specified state - // - function setState(state) { - return function (job, arg0, arg1) { - job._setState(state, arg0, arg1); - }; - } - - // Helper which sets the priority of a job. - // - function changePriority(job, priority) { - job._setPriority(priority); - } - - // Created - // - state_created.enter = function (job) { - addJobAtTailOfPriority(job, job.priority); - job._setState(state_scheduled); - }; - - // Scheduled - // - state_scheduled.enter = function (job) { - startRunning(); - }; - state_scheduled.execute = setState(state_running); - state_scheduled.cancel = setState(state_canceled); - state_scheduled.pause = setState(state_paused); - state_scheduled.resume = _; - state_scheduled.setPriority = function (job, priority) { - if (job.priority !== priority) { - job._setPriority(priority); - job.pause(); - job.resume(); - } - }; - - // Paused - // - state_paused.enter = function (job) { - jobProfilerMark(job, "job-paused", "info"); - job._removeJob(); - }; - state_paused.cancel = setState(state_canceled); - state_paused.pause = _; - state_paused.resume = function (job) { - jobProfilerMark(job, "job-resumed", "info"); - addJobAtTailOfPriority(job, job.priority); - job._setState(state_scheduled); - }; - state_paused.setPriority = changePriority; - - // Canceled - // - state_canceled.enter = function (job) { - jobProfilerMark(job, "job-canceled", "info"); - Debug.msTraceAsyncOperationCompleted(job._asyncOpID, Debug.MS_ASYNC_OP_STATUS_CANCELED) - job._removeJob(); - job._work = null; - job._context = null; - job.owner = null; - }; - state_canceled.cancel = _; - state_canceled.pause = _; - state_canceled.resume = _; - state_canceled.setPriority = _; - - // Running - // - state_running.enter = function (job, shouldYield) { - // Remove the job from the list in case it throws an exception, this means in the - // yield case we have to add it back. - // - job._removeJob(); - - var priority = job.priority; - var work = job._work; - var context = job._context; - - // Null out the work and context so they aren't leaked if the job throws an exception. - // - job._work = null; - job._context = null; - - var jobInfo = new JobInfo(shouldYield, job); - - Debug.msTraceAsyncCallbackStarting(job._asyncOpID); - try { - MSApp.execAtPriority(function () { - work.call(context, jobInfo); - }, toWwaPriority(priority)); - } finally { - Debug.msTraceAsyncCallbackCompleted(); - jobInfo._disablePublicApi(); - } - - // Restore the context in case it is needed due to yielding or blocking. - // - job._context = context; - - var targetState = job._executeDone(jobInfo._yieldPolicy); - - job._setState(targetState, jobInfo._result, priority); - }; - state_running.executeDone = function (job, yieldPolicy) { - switch (yieldPolicy) { - case YieldPolicy.complete: - return state_complete; - case YieldPolicy.continue: - return state_cooperative_yield; - case YieldPolicy.block: - return state_blocked; - } - }; - state_running.cancel = function (job) { - // Interaction with the singleton scheduler. The act of canceling a job pokes the scheduler - // and tells it to start asking the job to yield. - // - immediateYield = true; - job._setState(state_running_canceled); - }; - state_running.pause = function (job) { - // Interaction with the singleton scheduler. The act of pausing a job pokes the scheduler - // and tells it to start asking the job to yield. - // - immediateYield = true; - job._setState(state_running_paused); - }; - state_running.resume = _; - state_running.setPriority = changePriority; - - // Running paused - // - state_running_paused.enter = _; - state_running_paused.executeDone = function (job, yieldPolicy) { - switch (yieldPolicy) { - case YieldPolicy.complete: - return state_complete; - case YieldPolicy.continue: - return state_cooperative_yield_paused; - case YieldPolicy.block: - return state_blocked_paused; - } - }; - state_running_paused.cancel = setState(state_running_canceled); - state_running_paused.pause = _; - state_running_paused.resume = setState(state_running_resumed); - state_running_paused.setPriority = changePriority; - - // Running resumed - // - state_running_resumed.enter = _; - state_running_resumed.executeDone = function (job, yieldPolicy) { - switch (yieldPolicy) { - case YieldPolicy.complete: - return state_complete; - case YieldPolicy.continue: - return state_cooperative_yield; - case YieldPolicy.block: - return state_blocked; - } - }; - state_running_resumed.cancel = setState(state_running_canceled); - state_running_resumed.pause = setState(state_running_paused); - state_running_resumed.resume = _; - state_running_resumed.setPriority = changePriority; - - // Running canceled - // - state_running_canceled.enter = _; - state_running_canceled.executeDone = function (job, yieldPolicy) { - switch (yieldPolicy) { - case YieldPolicy.complete: - case YieldPolicy.continue: - return state_canceled; - case YieldPolicy.block: - return state_running_canceled_blocked; - } - }; - state_running_canceled.cancel = _; - state_running_canceled.pause = _; - state_running_canceled.resume = _; - state_running_canceled.setPriority = _; - - // Running canceled -> blocked - // - state_running_canceled_blocked.enter = function (job, work) { - work.cancel(); - job._setState(state_canceled); - }; - - // Cooperative yield - // - state_cooperative_yield.enter = function (job, work, initialPriority) { - jobProfilerMark(job, "job-yielded", "info"); - if (initialPriority === job.priority) { - addJobAtHeadOfPriority(job, job.priority); - } else { - addJobAtTailOfPriority(job, job.priority); - } - job._work = work; - job._setState(state_scheduled); - }; - - // Cooperative yield paused - // - state_cooperative_yield_paused.enter = function (job, work) { - jobProfilerMark(job, "job-yielded", "info"); - job._work = work; - job._setState(state_paused); - }; - - // Blocked - // - state_blocked.enter = function (job, work, initialPriority) { - jobProfilerMark(job, "job-blocked", "StartTM"); - job._work = work; - job._setState(state_blocked_waiting); - - // Sign up for a completion from the provided promise, after the completion occurs - // transition from the current state at the completion time to the target state - // depending on the completion value. - // - work.done( - function (newWork) { - jobProfilerMark(job, "job-blocked", "StopTM"); - var targetState = job._blockedDone(newWork); - job._setState(targetState, newWork, initialPriority); - }, - function (error) { - if (!(error && error.name === "Canceled")) { - jobProfilerMark(job, "job-error", "info"); - } - jobProfilerMark(job, "job-blocked", "StopTM"); - job._setState(state_canceled); - return Promise.wrapError(error); - } - ); - }; - - // Blocked waiting - // - state_blocked_waiting.enter = _; - state_blocked_waiting.blockedDone = function (job, result) { - if (typeof result === "function") { - return state_cooperative_yield; - } else { - return state_complete; - } - }; - state_blocked_waiting.cancel = setState(state_blocked_canceled); - state_blocked_waiting.pause = setState(state_blocked_paused_waiting); - state_blocked_waiting.resume = _; - state_blocked_waiting.setPriority = changePriority; - - // Blocked paused - // - state_blocked_paused.enter = function (job, work, initialPriority) { - jobProfilerMark(job, "job-blocked", "StartTM"); - job._work = work; - job._setState(state_blocked_paused_waiting); - - // Sign up for a completion from the provided promise, after the completion occurs - // transition from the current state at the completion time to the target state - // depending on the completion value. - // - work.done( - function (newWork) { - jobProfilerMark(job, "job-blocked", "StopTM"); - var targetState = job._blockedDone(newWork); - job._setState(targetState, newWork, initialPriority); - }, - function (error) { - if (!(error && error.name === "Canceled")) { - jobProfilerMark(job, "job-error", "info"); - } - jobProfilerMark(job, "job-blocked", "StopTM"); - job._setState(state_canceled); - return Promise.wrapError(error); - } - ); - }; - - // Blocked paused waiting - // - state_blocked_paused_waiting.enter = _; - state_blocked_paused_waiting.blockedDone = function (job, result) { - if (typeof result === "function") { - return state_cooperative_yield_paused; - } else { - return state_complete; - } - }; - state_blocked_paused_waiting.cancel = setState(state_blocked_canceled); - state_blocked_paused_waiting.pause = _; - state_blocked_paused_waiting.resume = setState(state_blocked_waiting); - state_blocked_paused_waiting.setPriority = changePriority; - - // Blocked canceled - // - state_blocked_canceled.enter = function (job) { - // Cancel the outstanding promise and then eventually it will complete, presumably with a 'canceled' - // error at which point we will transition to the canceled state. - // - job._work.cancel(); - job._work = null; - }; - state_blocked_canceled.blockedDone = function (job, result) { - return state_canceled; - }; - state_blocked_canceled.cancel = _; - state_blocked_canceled.pause = _; - state_blocked_canceled.resume = _; - state_blocked_canceled.setPriority = _; - - // Complete - // - state_complete.completed = true; - state_complete.enter = function (job) { - Debug.msTraceAsyncOperationCompleted(job._asyncOpID, Debug.MS_ASYNC_OP_STATUS_SUCCESS); - job._work = null; - job._context = null; - job.owner = null; - jobProfilerMark(job, "job-completed", "info"); - }; - state_complete.cancel = _; - state_complete.pause = _; - state_complete.resume = _; - state_complete.setPriority = _; - - // Private Priority marker node in the Job list. The marker nodes are linked both into the job - // list and a separate marker list. This is used so that jobs can be easily added into a given - // priority level by simply traversing to the next marker in the list and inserting before it. - // - // Markers may either be "static" or "dynamic". Static markers are the set of things which are - // named and are always in the list, they may exist with or without jobs at their priority - // level. Dynamic markers are added as needed. - // - // @NOTE: Dynamic markers are NYI - // - var MarkerNode = WinJS.Class.define(function (priority, name) { - this.priority = priority; - this.name = name; - }, { - - // NYI - // - //dynamic: { - // get: function () { return !this.name; } - //}, - - }); - WinJS.Class.mix(MarkerNode, linkedListMixin("Job"), linkedListMixin("Marker")); - - // - // Scheduler state - // - - // Unique ID per job. - // - var globalJobId = 0; - - // Unique ID per drain request. - var globalDrainId = 0; - - // Priority is: -15 ... 0 ... 15 where that maps to: 'min' ... 'normal' ... 'max' - // - var MIN_PRIORITY = -15; - var MAX_PRIORITY = 15; - - // Named priorities - // - var Priority = { - max: 15, - high: 13, - aboveNormal: 9, - normal: 0, - belowNormal: -9, - idle: -13, - min: -15, - }; - - // Definition of the priorities, named have static markers. - // - var priorities = [ - new MarkerNode(15, "max"), // Priority.max - new MarkerNode(14, "14"), - new MarkerNode(13, "high"), // Priority.high - new MarkerNode(12, "12"), - new MarkerNode(11, "11"), - new MarkerNode(10, "10"), - new MarkerNode(9, "aboveNormal"), // Priority.aboveNormal - new MarkerNode(8, "8"), - new MarkerNode(7, "7"), - new MarkerNode(6, "6"), - new MarkerNode(5, "5"), - new MarkerNode(4, "4"), - new MarkerNode(3, "3"), - new MarkerNode(2, "2"), - new MarkerNode(1, "1"), - new MarkerNode(0, "normal"), // Priority.normal - new MarkerNode(-1, "-1"), - new MarkerNode(-2, "-2"), - new MarkerNode(-3, "-3"), - new MarkerNode(-4, "-4"), - new MarkerNode(-5, "-5"), - new MarkerNode(-6, "-6"), - new MarkerNode(-7, "-7"), - new MarkerNode(-8, "-8"), - new MarkerNode(-9, "belowNormal"), // Priority.belowNormal - new MarkerNode(-10, "-10"), - new MarkerNode(-11, "-11"), - new MarkerNode(-12, "-12"), - new MarkerNode(-13, "idle"), // Priority.idle - new MarkerNode(-14, "-14"), - new MarkerNode(-15, "min"), // Priority.min - new MarkerNode(-16, "") - ]; - - function dumpList(type, reverse) { - function dumpMarker(marker, pos) { - WinJS.log && WinJS.log(pos + ": MARKER: " + marker.name, "winjs scheduler", "log"); - } - function dumpJob(job, pos) { - WinJS.log && WinJS.log(pos + ": JOB(" + job.id + "): state: " + (job._state ? job._state.name : "") + (job.name ? ", name: " + job.name : ""), "winjs scheduler", "log"); - } - WinJS.log && WinJS.log("highWaterMark: " + highWaterMark, "winjs scheduler", "log"); - var pos = 0; - var head = reverse ? priorities[priorities.length - 1] : priorities[0]; - var current = head; - do { - if (current instanceof MarkerNode) { - dumpMarker(current, pos); - } - if (current instanceof JobNode) { - dumpJob(current, pos); - } - pos++; - current = reverse ? current["_prev" + type] : current["_next" + type]; - } while (current); - } - - function retrieveState() { - /// - /// - /// Returns a string representation of the scheduler's state for diagnostic - /// purposes. The jobs and drain requests are displayed in the order in which - /// they are currently expected to be processed. The current job and drain - /// request are marked by an asterisk. - /// - /// - var output = ""; - - function logJob(job, isRunning) { - output += - " " + (isRunning ? "*" : " ") + - "id: " + job.id + - ", priority: " + markerFromPriority(job.priority).name + - (job.name ? ", name: " + job.name : "") + - "\n"; - } - - output += "Jobs:\n"; - var current = markerFromPriority(highWaterMark); - var jobCount = 0; - if (runningJob) { - logJob(runningJob, true); - jobCount++; - } - while (current.priority >= Priority.min) { - if (current instanceof JobNode) { - logJob(current, false); - jobCount++; - } - current = current._nextJob; - } - if (jobCount === 0) { - output += " None\n"; - } - - output += "Drain requests:\n"; - for (var i = 0, len = drainQueue.length; i < len; i++) { - output += - " " + (i === 0 ? "*" : " ") + - "priority: " + markerFromPriority(drainQueue[i].priority).name + - ", name: " + drainQueue[i].name + - "\n"; - } - if (drainQueue.length === 0) { - output += " None\n"; - } - - return output; - } - - function isEmpty() { - var current = priorities[0]; - do { - if (current instanceof JobNode) { - return false; - } - current = current._nextJob; - } while (current); - - return true; - } - - // The WWA priority at which the pump is currently scheduled on the WWA scheduler. - // null when the pump is not scheduled. - // - var scheduledWwaPriority = null; - - // Whether the scheduler pump is currently on the stack - // - var pumping; - // What priority is currently being pumped - // - var pumpingPriority; - - // A reference to the job object that is currently running. - // null when no job is running. - // - var runningJob = null; - - // Whether we are using the WWA scheduler. - // - var usingWwaScheduler = !!(global.MSApp && global.MSApp.execAtPriority); - - // Queue of drain listeners - // - var drainQueue = []; - - // Bit indicating that we should yield immediately - // - var immediateYield; - - // time slice for scheduler - // - var TIME_SLICE = 30; - - // high-water-mark is maintained any time priorities are adjusted, new jobs are - // added or the scheduler pumps itself down through a priority marker. The goal - // of the high-water-mark is to be a fast check as to whether a job may exist - // at a higher priority level than we are currently at. It may be wrong but it - // may only be wrong by being higher than the current highest priority job, not - // lower as that would cause the system to pump things out of order. - // - var highWaterMark = Priority.min; - - // - // Initialize the scheduler - // - - // Wire up the markers - // - priorities.reduce(function (prev, current) { - if (prev) { - prev._insertJobAfter(current); - prev._insertMarkerAfter(current); - } - return current; - }) - - // - // Draining mechanism - // - // For each active drain request, there is a unique drain listener in the - // drainQueue. Requests are processed in FIFO order. The scheduler is in - // drain mode precisely when the drainQueue is non-empty. - // - - // Returns priority of the current drain request - // - function currentDrainPriority() { - return drainQueue.length === 0 ? null : drainQueue[0].priority; - } - - function drainStarting(listener) { - schedulerProfilerMark("drain", "StartTM", listener.name, markerFromPriority(listener.priority).name); - } - function drainStopping(listener, canceled) { - if (canceled) { - schedulerProfilerMark("drain-canceled", "info", listener.name, markerFromPriority(listener.priority).name); - } - schedulerProfilerMark("drain", "StopTM", listener.name, markerFromPriority(listener.priority).name); - } - - function addDrainListener(priority, complete, name) { - drainQueue.push({ priority: priority, complete: complete, name: name }); - if (drainQueue.length === 1) { - drainStarting(drainQueue[0]); - if (priority > highWaterMark) { - highWaterMark = priority; - immediateYield = true; - } - } - } - - function removeDrainListener(complete, canceled) { - var i, - len = drainQueue.length; - - for (i = 0; i < len; i++) { - if (drainQueue[i].complete === complete) { - if (i === 0) { - drainStopping(drainQueue[0], canceled); - drainQueue[1] && drainStarting(drainQueue[1]); - } - drainQueue.splice(i, 1); - break; - } - } - } - - // Notifies and removes the current drain listener - // - function notifyCurrentDrainListener() { - var listener = drainQueue.shift(); - - if (listener) { - drainStopping(listener); - drainQueue[0] && drainStarting(drainQueue[0]); - listener.complete(); - } - } - - // Notifies all drain listeners which are at a priority > highWaterMark. - // Returns whether or not any drain listeners were notified. This - // function sets pumpingPriority and reads highWaterMark. Note that - // it may call into user code which may call back into the scheduler. - // - function notifyDrainListeners() { - var notifiedSomebody = false; - if (!!drainQueue.length) { - // As we exhaust priority levels, notify the appropriate drain listeners. - // - var drainPriority = currentDrainPriority(); - while (+drainPriority === drainPriority && drainPriority > highWaterMark) { - pumpingPriority = drainPriority; - notifyCurrentDrainListener(); - notifiedSomebody = true; - drainPriority = currentDrainPriority(); - } - } - return notifiedSomebody; - } - - // - // Interfacing with the WWA Scheduler - // - - // Stubs for the parts of the WWA scheduler APIs that we use. These stubs are - // used in contexts where the WWA scheduler is not available. - // - var MSAppStubs = { - execAsyncAtPriority: function (callback, priority) { - // If it's a high priority callback then we additionally schedule using setTimeout(0) - // - if (priority === MSApp.HIGH) { - setTimeout(callback, 0); - } - // We always schedule using setImmediate - // - setImmediate(callback); - }, - - execAtPriority: function (callback, priority) { - return callback(); - }, - - getCurrentPriority: function () { - return MSAppStubs.NORMAL; - }, - - isTaskScheduledAtPriorityOrHigher: function (priority) { - return false; - }, - - HIGH: "high", - NORMAL: "normal", - IDLE: "idle" - }; - - var MSApp = (usingWwaScheduler ? global.MSApp : MSAppStubs); - - function toWwaPriority(winjsPriority) { - if (winjsPriority >= Priority.aboveNormal + 1) { return MSApp.HIGH; } - if (winjsPriority >= Priority.belowNormal) { return MSApp.NORMAL; } - return MSApp.IDLE; - } - - var wwaPriorityToInt = {}; - wwaPriorityToInt[MSApp.IDLE] = 1; - wwaPriorityToInt[MSApp.NORMAL] = 2; - wwaPriorityToInt[MSApp.HIGH] = 3; - - function isEqualOrHigherWwaPriority(priority1, priority2) { - return wwaPriorityToInt[priority1] >= wwaPriorityToInt[priority2]; - } - - function isHigherWwaPriority(priority1, priority2) { - return wwaPriorityToInt[priority1] > wwaPriorityToInt[priority2]; - } - - function wwaTaskScheduledAtPriorityHigherThan(wwaPriority) { - switch (wwaPriority) { - case MSApp.HIGH: - return false; - case MSApp.NORMAL: - return MSApp.isTaskScheduledAtPriorityOrHigher(MSApp.HIGH); - case MSApp.IDLE: - return MSApp.isTaskScheduledAtPriorityOrHigher(MSApp.NORMAL); - } - } - - // - // Mechanism for the scheduler - // - - function addJobAtHeadOfPriority(node, priority) { - var marker = markerFromPriority(priority); - if (marker.priority > highWaterMark) { - highWaterMark = marker.priority; - immediateYield = true; - } - marker._insertJobAfter(node); - } - - function addJobAtTailOfPriority(node, priority) { - var marker = markerFromPriority(priority); - if (marker.priority > highWaterMark) { - highWaterMark = marker.priority; - immediateYield = true; - } - marker._nextMarker._insertJobBefore(node); - } - - function clampPriority(priority) { - priority = priority | 0; - priority = Math.max(priority, MIN_PRIORITY); - priority = Math.min(priority, MAX_PRIORITY); - return priority; - } - - function markerFromPriority(priority) { - priority = clampPriority(priority); - - // The priority skip list is from high -> idle, add the offset and then make it positive. - // - return priorities[-1 * (priority - MAX_PRIORITY)]; - } - - // Performance.now is not defined in web workers. - // - var now = (global.performance && performance.now.bind(performance)) || Date.now.bind(Date); - - // Main scheduler pump. - // - function run(scheduled) { - pumping = true; - schedulerProfilerMark("timeslice", "StartTM"); - var didWork; - var ranJobSuccessfully = true; - var current; - - // Reset per-run state - // - immediateYield = false; - - try { - var start = now(); - var end = start + TIME_SLICE; - var lastLoggedPriority; - var yieldForPriorityBoundary = false; - - // Yielding policy - // - // @TODO, should we have a different scheduler policy when the debugger is attached. Today if you - // break in user code we will generally yield immediately after that job due to the fact that any - // breakpoint will take longer than TIME_SLICE to process. - // - var timesliceExhausted = false; - var shouldYield = function () { - timesliceExhausted = false; - if (immediateYield) { return true; } - if (wwaTaskScheduledAtPriorityHigherThan(toWwaPriority(highWaterMark))) { return true; } - if (!!drainQueue.length) { return false; } - if (now() > end) { - timesliceExhausted = true; - return true; - } - return false; - }; - - // Run until we run out of jobs or decide it is time to yield - // - while (highWaterMark >= Priority.min && !shouldYield() && !yieldForPriorityBoundary) { - - didWork = false; - current = markerFromPriority(highWaterMark)._nextJob; - do { - // Record the priority currently being pumped - // - pumpingPriority = current.priority; - - if (current instanceof JobNode) { - if (lastLoggedPriority !== current.priority) { - if (+lastLoggedPriority === lastLoggedPriority) { - schedulerProfilerMark("priority", "StopTM", markerFromPriority(lastLoggedPriority).name); - } - schedulerProfilerMark("priority", "StartTM", markerFromPriority(current.priority).name); - lastLoggedPriority = current.priority; - } - - // Important that we update this state before calling execute because the - // job may throw an exception and we don't want to stall the queue. - // - didWork = true; - ranJobSuccessfully = false; - runningJob = current; - jobProfilerMark(runningJob, "job-running", "StartTM", markerFromPriority(pumpingPriority).name); - current._execute(shouldYield); - jobProfilerMark(runningJob, "job-running", "StopTM", markerFromPriority(pumpingPriority).name); - runningJob = null; - ranJobSuccessfully = true; - } else { - // As we pass marker nodes update our high water mark. It's important to do - // this before notifying drain listeners because they may schedule new jobs - // which will affect the highWaterMark. - // - var wwaPrevHighWaterMark = toWwaPriority(highWaterMark); - highWaterMark = current.priority; - - didWork = notifyDrainListeners(); - - var wwaHighWaterMark = toWwaPriority(highWaterMark); - if (isHigherWwaPriority(wwaPrevHighWaterMark, wwaHighWaterMark) && - (!usingWwaScheduler || MSApp.isTaskScheduledAtPriorityOrHigher(wwaHighWaterMark))) { - // Timeslice is moving to a lower WWA priority and the host - // has equally or more important work to do. Time to yield. - // - yieldForPriorityBoundary = true; - } - } - - current = current._nextJob; - - // When didWork is true we exit the loop because: - // - We've called into user code which may have modified the - // scheduler's queue. We need to restart at the high water mark. - // - We need to check if it's time for the scheduler to yield. - // - } while (current && !didWork && !yieldForPriorityBoundary && !wwaTaskScheduledAtPriorityHigherThan(toWwaPriority(highWaterMark))); - - // Reset per-item state - // - immediateYield = false; - - } - - } finally { - runningJob = null; - - // If a job was started and did not run to completion due to an exception - // we should transition it to a terminal state. - // - if (!ranJobSuccessfully) { - jobProfilerMark(current, "job-error", "info"); - jobProfilerMark(current, "job-running", "StopTM", markerFromPriority(pumpingPriority).name); - current.cancel(); - } - - if (+lastLoggedPriority === lastLoggedPriority) { - schedulerProfilerMark("priority", "StopTM", markerFromPriority(lastLoggedPriority).name); - } - // Update high water mark to be the priority of the highest priority job. - // - var foundAJob = false; - while (highWaterMark >= Priority.min && !foundAJob) { - - didWork = false; - current = markerFromPriority(highWaterMark)._nextJob; - do { - - if (current instanceof JobNode) { - // We found a job. High water mark is now set to the priority - // of this job. - // - foundAJob = true; - } else { - // As we pass marker nodes update our high water mark. It's important to do - // this before notifying drain listeners because they may schedule new jobs - // which will affect the highWaterMark. - // - highWaterMark = current.priority; - - didWork = notifyDrainListeners(); - } - - current = current._nextJob; - - // When didWork is true we exit the loop because: - // - We've called into user code which may have modified the - // scheduler's queue. We need to restart at the high water mark. - // - } while (current && !didWork && !foundAJob); - } - - var reasonForYielding; - if (!ranJobSuccessfully) { - reasonForYielding = "job error"; - } else if (timesliceExhausted) { - reasonForYielding = "timeslice exhausted"; - } else if (highWaterMark < Priority.min) { - reasonForYielding = "jobs exhausted"; - } else if (yieldForPriorityBoundary) { - reasonForYielding = "reached WWA priority boundary"; - } else { - reasonForYielding = "WWA host work"; - } - - // If this was a scheduled call to the pump, then the pump is no longer - // scheduled to be called and we should clear its scheduled priority. - // - if (scheduled) { - scheduledWwaPriority = null; - } - - // If the high water mark has not reached the end of the queue then - // we re-queue in order to see if there are more jobs to run. - // - pumping = false; - if (highWaterMark >= Priority.min) { - startRunning(); - } - schedulerProfilerMark("yielding", "info", reasonForYielding); - schedulerProfilerMark("timeslice", "StopTM"); - } - } - - // When we schedule the pump we assign it a version. When we start executing one we check - // to see what the max executed version is. If we have superseded it then we skip the call. - // - var scheduledVersion = 0; - var executedVersion = 0; - - function startRunning(priority) { - if (+priority !== priority) { - priority = highWaterMark; - } - var priorityWwa = toWwaPriority(priority); - - // Don't schedule the pump while pumping. The pump will be scheduled - // immediately before yielding if necessary. - // - if (pumping) { - return; - } - - // If the pump is already scheduled at priority or higher, then there - // is no need to schedule the pump again. - // However, when we're not using the WWA scheduler, we fallback to immediate/timeout - // which do not have a notion of priority. In this case, if the pump is scheduled, - // there is no need to schedule another pump. - // - if (scheduledWwaPriority && (!usingWwaScheduler || isEqualOrHigherWwaPriority(scheduledWwaPriority, priorityWwa))) { - return; - } - var current = ++scheduledVersion; - var runner = function () { - if (executedVersion < current) { - executedVersion = scheduledVersion; - run(true); - } - }; - - MSApp.execAsyncAtPriority(runner, priorityWwa); - scheduledWwaPriority = priorityWwa; - } - - function requestDrain(priority, name) { - /// - /// - /// Runs jobs in the scheduler without timeslicing until all jobs at the - /// specified priority and higher have executed. - /// - /// - /// The priority to which the scheduler should drain. The default is Priority.min, which drains all jobs in the queue. - /// - /// - /// An optional description of the drain request for diagnostics. - /// - /// - /// A promise which completes when the drain has finished. Canceling this - /// promise cancels the drain request. This promise will never enter an error state. - /// - /// - - var id = globalDrainId++; - if (name === undefined) { - name = "Drain Request " + id; - } - priority = (+priority === priority) ? priority : Priority.min; - priority = clampPriority(priority); - - var complete; - var promise = new Promise(function (c) { - complete = c; - addDrainListener(priority, complete, name); - }, function () { - removeDrainListener(complete, true); - }); - - if (!pumping) { - startRunning(); - } - - return promise; - } - - function execHigh(callback) { - /// - /// - /// Runs the specified callback in a high priority context. - /// - /// - /// The callback to run in a high priority context. - /// - /// - /// The return value of the callback. - /// - /// - - return MSApp.execAtPriority(callback, MSApp.HIGH); - } - - function createOwnerToken() { - /// - /// - /// Creates and returns a new owner token which can be set to the owner property of one or more jobs. - /// It can then be used to cancel all jobs it "owns". - /// - /// - /// The new owner token. You can use this token to control jobs that it owns. - /// - /// - - return new OwnerToken(); - } - - function schedule(work, priority, thisArg, name) { - /// - /// - /// Schedules the specified function to execute asynchronously. - /// - /// - /// A function that represents the work item to be scheduled. When called the work item will receive as its first argument - /// a JobInfo object which allows the work item to ask the scheduler if it should yield cooperatively and if so allows the - /// work item to either provide a function to be run as a continuation or a WinJS.Promise which will when complete - /// provide a function to run as a continuation. - /// - /// - /// The priority at which to schedule the work item. The default value is Priority.normal. - /// - /// - /// A 'this' instance to be bound into the work item. The default value is null. - /// - /// - /// A description of the work item for diagnostics. The default value is an empty string. - /// - /// - /// The Job instance which represents this work item. - /// - /// - - priority = priority || Priority.normal; - thisArg = thisArg || null; - var jobId = ++globalJobId; - var asyncOpID = Debug.msTraceAsyncOperationStarting("WinJS.Utilities.Scheduler.schedule: " + jobId + profilerMarkArgs(name)); - name = name || ""; - return new JobNode(jobId, work, priority, thisArg, name, asyncOpID); - } - - function getCurrentPriority() { - if (pumping) { - return pumpingPriority; - } else { - switch (MSApp.getCurrentPriority()) { - case MSApp.HIGH: return Priority.high; - case MSApp.NORMAL: return Priority.normal; - case MSApp.IDLE: return Priority.idle; - } - } - } - - function makeSchedulePromise(priority) { - return function (promiseValue, jobName) { - /// - /// - /// Schedules a job to complete a returned Promise. - /// There are four versions of this method for different commonly used priorities: schedulePromiseHigh, - /// schedulePromiseAboveNormal, schedulePromiseNormal, schedulePromiseBelowNormal, - /// and schedulePromiseIdle. - /// Example usage which shows how to - /// ensure that the last link in a promise chain is run on the scheduler at high priority: - /// asyncOp().then(Scheduler.schedulePromiseHigh).then(function (valueOfAsyncOp) { }); - /// - /// - /// The value with which the returned promise will complete. - /// - /// - /// A string that describes the job for diagnostic purposes. - /// - /// - /// A promise which completes within a job of the desired priority. - /// - /// - var job; - return new WinJS.Promise( - function (c) { - job = schedule(function schedulePromise() { - c(promiseValue); - }, priority, null, jobName); - }, - function () { - job.cancel(); - } - ); - }; - } - - WinJS.Namespace.define("WinJS.Utilities.Scheduler", { - - Priority: Priority, - - schedule: schedule, - - createOwnerToken: createOwnerToken, - - execHigh: execHigh, - - requestDrain: requestDrain, - - /// - /// Gets the current priority at which the caller is executing. - /// - currentPriority: { - get: getCurrentPriority - }, - - // Promise helpers - // - schedulePromiseHigh: makeSchedulePromise(Priority.high), - schedulePromiseAboveNormal: makeSchedulePromise(Priority.aboveNormal), - schedulePromiseNormal: makeSchedulePromise(Priority.normal), - schedulePromiseBelowNormal: makeSchedulePromise(Priority.belowNormal), - schedulePromiseIdle: makeSchedulePromise(Priority.idle), - - retrieveState: retrieveState, - - _JobNode: JobNode, - - _JobInfo: JobInfo, - - _OwnerToken: OwnerToken, - - _dumpList: dumpList, - - _isEmpty: { - get: isEmpty - }, - - // The properties below are used for testing. - // - - _usingWwaScheduler: { - get: function () { - return usingWwaScheduler; - }, - set: function (value) { - usingWwaScheduler = value; - MSApp = (usingWwaScheduler ? global.MSApp : MSAppStubs); - } - }, - - _MSApp: { - get: function () { - return MSApp; - }, - set: function (value) { - MSApp = value; - } - }, - - _TIME_SLICE: TIME_SLICE - - }); - -}(this)); - -(function errorsInit(global, WinJS) { - "use strict"; - - - WinJS.Namespace.define("WinJS", { - // ErrorFromName establishes a simple pattern for returning error codes. - // - ErrorFromName: WinJS.Class.derive(Error, function (name, message) { - /// - /// - /// Creates an Error object with the specified name and message properties. - /// - /// The name of this error. The name is meant to be consumed programmatically and should not be localized. - /// The message for this error. The message is meant to be consumed by humans and should be localized. - /// Error instance with .name and .message properties populated - /// - this.name = name; - this.message = message || name; - }, { - /* empty */ - }, { - supportedForProcessing: false, - }) - }); - -})(this, WinJS); - - -(function xhrInit() { - "use strict"; - - var Scheduler = WinJS.Utilities.Scheduler; - - function schedule(f, arg, priority) { - Scheduler.schedule(function () { - f(arg); - }, priority, null, "WinJS.xhr"); - } - - function noop() { - } - - WinJS.Namespace.define("WinJS", { - xhr: function (options) { - /// - /// - /// Wraps calls to XMLHttpRequest in a promise. - /// - /// - /// The options that are applied to the XMLHttpRequest object. They are: type, - /// url, user, password, headers, responseType, data, and customRequestInitializer. - /// - /// - /// A promise that returns the XMLHttpRequest object when it completes. - /// - /// - var req; - return new WinJS.Promise( - function (c, e, p) { - /// - var priority = Scheduler.currentPriority; - req = new XMLHttpRequest(); - req.onreadystatechange = function () { - if (req._canceled) { - req.onreadystatechange = noop; - return; - } - - if (req.readyState === 4) { - if (req.status >= 200 && req.status < 300) { - schedule(c, req, priority); - } else { - schedule(e, req, priority); - } - req.onreadystatechange = noop; - } else { - schedule(p, req, priority); - } - }; - - req.open( - options.type || "GET", - options.url, - // Promise based XHR does not support sync. - // - true, - options.user, - options.password - ); - req.responseType = options.responseType || ""; - - Object.keys(options.headers || {}).forEach(function (k) { - req.setRequestHeader(k, options.headers[k]); - }); - - if (options.customRequestInitializer) { - options.customRequestInitializer(req); - } - - if (options.data === undefined) { - req.send(); - } else { - req.send(options.data); - } - }, - function () { - req.onreadystatechange = noop; - req._canceled = true; - req.abort(); - } - ); - } - }); - -})(); - - -(function safeHTMLInit(global, undefined) { - "use strict"; - - - var setInnerHTML, - setInnerHTMLUnsafe, - setOuterHTML, - setOuterHTMLUnsafe, - insertAdjacentHTML, - insertAdjacentHTMLUnsafe; - - var strings = { - get nonStaticHTML() { return WinJS.Resources._getWinJSString("base/nonStaticHTML").value; }, - }; - - setInnerHTML = setInnerHTMLUnsafe = function (element, text) { - /// - /// - /// Sets the innerHTML property of the specified element to the specified text. - /// - /// - /// The element on which the innerHTML property is to be set. - /// - /// - /// The value to be set to the innerHTML property. - /// - /// - element.innerHTML = text; - }; - setOuterHTML = setOuterHTMLUnsafe = function (element, text) { - /// - /// - /// Sets the outerHTML property of the specified element to the specified text. - /// - /// - /// The element on which the outerHTML property is to be set. - /// - /// - /// The value to be set to the outerHTML property. - /// - /// - element.outerHTML = text; - }; - insertAdjacentHTML = insertAdjacentHTMLUnsafe = function (element, position, text) { - /// - /// - /// Calls insertAdjacentHTML on the specified element. - /// - /// - /// The element on which insertAdjacentHTML is to be called. - /// - /// - /// The position relative to the element at which to insert the HTML. - /// - /// - /// The value to be provided to insertAdjacentHTML. - /// - /// - element.insertAdjacentHTML(position, text); - }; - - var msApp = global.MSApp; - if (msApp) { - setInnerHTMLUnsafe = function (element, text) { - /// - /// - /// Sets the innerHTML property of the specified element to the specified text. - /// - /// - /// The element on which the innerHTML property is to be set. - /// - /// - /// The value to be set to the innerHTML property. - /// - /// - msApp.execUnsafeLocalFunction(function () { - element.innerHTML = text; - }); - }; - setOuterHTMLUnsafe = function (element, text) { - /// - /// - /// Sets the outerHTML property of the specified element to the specified text - /// in the context of msWWA.execUnsafeLocalFunction. - /// - /// - /// The element on which the outerHTML property is to be set. - /// - /// - /// The value to be set to the outerHTML property. - /// - /// - msApp.execUnsafeLocalFunction(function () { - element.outerHTML = text; - }); - }; - insertAdjacentHTMLUnsafe = function (element, position, text) { - /// - /// - /// Calls insertAdjacentHTML on the specified element in the context - /// of msWWA.execUnsafeLocalFunction. - /// - /// - /// The element on which insertAdjacentHTML is to be called. - /// - /// - /// The position relative to the element at which to insert the HTML. - /// - /// - /// Value to be provided to insertAdjacentHTML. - /// - /// - msApp.execUnsafeLocalFunction(function () { - element.insertAdjacentHTML(position, text); - }); - }; - } - else if (global.msIsStaticHTML) { - var check = function (str) { - if (!global.msIsStaticHTML(str)) { - throw new WinJS.ErrorFromName("WinJS.Utitilies.NonStaticHTML", strings.nonStaticHTML); - } - } - // If we ever get isStaticHTML we can attempt to recreate the behavior we have in the local - // compartment, in the mean-time all we can do is sanitize the input. - // - setInnerHTML = function (element, text) { - /// - /// - /// Sets the innerHTML property of a element to the specified text - /// if it passes a msIsStaticHTML check. - /// - /// - /// The element on which the innerHTML property is to be set. - /// - /// - /// The value to be set to the innerHTML property. - /// - /// - check(text); - element.innerHTML = text; - }; - setOuterHTML = function (element, text) { - /// - /// - /// Sets the outerHTML property of a element to the specified text - /// if it passes a msIsStaticHTML check. - /// - /// - /// The element on which the outerHTML property is to be set. - /// - /// - /// The value to be set to the outerHTML property. - /// - /// - check(text); - element.outerHTML = text; - }; - insertAdjacentHTML = function (element, position, text) { - /// - /// - /// Calls insertAdjacentHTML on the element if it passes - /// a msIsStaticHTML check. - /// - /// - /// The element on which insertAdjacentHTML is to be called. - /// - /// - /// The position relative to the element at which to insert the HTML. - /// - /// - /// The value to be provided to insertAdjacentHTML. - /// - /// - check(text); - element.insertAdjacentHTML(position, text); - }; - } - - WinJS.Namespace.define("WinJS.Utilities", { - setInnerHTML: setInnerHTML, - setInnerHTMLUnsafe: setInnerHTMLUnsafe, - setOuterHTML: setOuterHTML, - setOuterHTMLUnsafe: setOuterHTMLUnsafe, - insertAdjacentHTML: insertAdjacentHTML, - insertAdjacentHTMLUnsafe: insertAdjacentHTMLUnsafe - }); - -}(this)); - -(function getWinJSStringInit() { - "use strict"; - - var appxVersion = "Microsoft.WinJS.2.0"; - var developerPrefix = "Developer."; - if (appxVersion.indexOf(developerPrefix) === 0) { - appxVersion = appxVersion.substring(developerPrefix.length); - } - - WinJS.Namespace.define("WinJS.Resources", { - _getWinJSString: function (id) { - return WinJS.Resources.getString("ms-resource://" + appxVersion + "/" + id); - } - }); -}(this)); -(function () { - "use strict"; - WinJS.Namespace.define("WinJS.Utilities", { - - markDisposable: function (element, disposeImpl) { - /// - /// - /// Adds the specified dispose implementation to the specified element and marks it as disposable. - /// - /// - /// The element to mark as disposable. - /// - /// - /// The function containing the element-specific dispose logic that will be called by the dispose function. - /// - /// - var disposed = false; - WinJS.Utilities.addClass(element, "win-disposable"); - - var disposable = element.winControl || element; - disposable.dispose = function () { - if (disposed) { - return; - } - - disposed = true; - WinJS.Utilities.disposeSubTree(element); - if (disposeImpl) { - disposeImpl(); - } - }; - }, - - disposeSubTree: function (element) { - /// - /// - /// Disposes all first-generation disposable elements that are descendents of the specified element. - /// The specified element itself is not disposed. - /// - /// - /// The root element whose sub-tree is to be disposed. - /// - /// - if (!element) { - return; - } - - msWriteProfilerMark("WinJS.Utilities.disposeSubTree,StartTM"); - var query = element.querySelectorAll(".win-disposable"); - - var index = 0; - var length = query.length; - while (index < length) { - var disposable = query[index]; - if (disposable.winControl && disposable.winControl.dispose) { - disposable.winControl.dispose(); - } - if (disposable.dispose) { - disposable.dispose(); - } - - // Skip over disposable's descendants since they are this disposable's responsibility to clean up. - index += disposable.querySelectorAll(".win-disposable").length + 1; - } - msWriteProfilerMark("WinJS.Utilities.disposeSubTree,StopTM"); - }, - - _disposeElement: function (element) { - // This helper should only be used for supporting dispose scenarios predating the dispose pattern. - // The specified element should be well enough defined so we don't have to check whether it - // a) has a disposable winControl, - // b) is disposable itself, - // or has disposable descendants in which case either a) or b) must have been true when designed correctly. - if (!element) { - return; - } - - var disposed = false; - if (element.winControl && element.winControl.dispose) { - element.winControl.dispose(); - disposed = true; - } - if (element.dispose) { - element.dispose(); - disposed = true; - } - - if (!disposed) { - WinJS.Utilities.disposeSubTree(element); - } - } - }); -})(); - -(function controlInit(global, WinJS, undefined) { - "use strict"; - - // not supported in WebWorker - if (!global.document) { - return; - } - - function setOptions(control, options) { - /// - /// - /// Adds the set of declaratively specified options (properties and events) to the specified control. - /// If name of the options property begins with "on", the property value is a function and the control - /// supports addEventListener. The setOptions method calls the addEventListener method on the control. - /// - /// - /// The control on which the properties and events are to be applied. - /// - /// - /// The set of options that are specified declaratively. - /// - /// - _setOptions(control, options); - }; - - function _setOptions(control, options, eventsOnly) { - if (typeof options === "object") { - var keys = Object.keys(options); - for (var i = 0, len = keys.length; i < len; i++) { - var key = keys[i]; - var value = options[key]; - if (key.length > 2) { - var ch1 = key[0]; - var ch2 = key[1]; - if ((ch1 === 'o' || ch1 === 'O') && (ch2 === 'n' || ch2 === 'N')) { - if (typeof value === "function") { - if (control.addEventListener) { - control.addEventListener(key.substr(2), value); - continue; - } - } - } - } - - if (!eventsOnly) { - control[key] = value; - } - } - } - }; - - WinJS.Namespace.define("WinJS.UI", { - DOMEventMixin: WinJS.Namespace._lazy(function () { - return { - _domElement: null, - - addEventListener: function (type, listener, useCapture) { - /// - /// - /// Adds an event listener to the control. - /// - /// - /// The type (name) of the event. - /// - /// - /// The listener to invoke when the event gets raised. - /// - /// - /// true to initiate capture; otherwise, false. - /// - /// - (this.element || this._domElement).addEventListener(type, listener, useCapture || false); - }, - dispatchEvent: function (type, eventProperties) { - /// - /// - /// Raises an event of the specified type, adding the specified additional properties. - /// - /// - /// The type (name) of the event. - /// - /// - /// The set of additional properties to be attached to the event object when the event is raised. - /// - /// - /// true if preventDefault was called on the event, otherwise false. - /// - /// - var eventValue = document.createEvent("Event"); - eventValue.initEvent(type, false, false); - eventValue.detail = eventProperties; - if (typeof eventProperties === "object") { - Object.keys(eventProperties).forEach(function (key) { - eventValue[key] = eventProperties[key]; - }); - } - return (this.element || this._domElement).dispatchEvent(eventValue); - }, - removeEventListener: function (type, listener, useCapture) { - /// - /// - /// Removes an event listener from the control. - /// - /// - /// The type (name) of the event. - /// - /// - /// The listener to remove. - /// - /// - /// true to initiate capture; otherwise, false. - /// - /// - (this.element || this._domElement).removeEventListener(type, listener, useCapture || false); - } - }; - }), - - setOptions: setOptions, - - _setOptions: _setOptions - }); - -})(this, WinJS); - - -(function declarativeControlsInit(global, WinJS, undefined) { - "use strict"; - - // not supported in WebWorker - if (!global.document) { - return; - } - - var strings = { - get errorActivatingControl() { return WinJS.Resources._getWinJSString("base/errorActivatingControl").value; }, - }; - - var markSupportedForProcessing = WinJS.Utilities.markSupportedForProcessing; - var requireSupportedForProcessing = WinJS.Utilities.requireSupportedForProcessing; - var processedAllCalled = false; - - function createSelect(element) { - var result = function select(selector) { - /// - /// - /// Walks the DOM tree from the given element to the root of the document, whenever - /// a selector scope is encountered select performs a lookup within that scope for - /// the given selector string. The first matching element is returned. - /// - /// The selector string. - /// The target element, if found. - /// - var current = element; - var selected; - while (current) { - if (current.msParentSelectorScope) { - var scope = current.parentNode; - if (scope) { - selected = scope.msMatchesSelector(selector) ? scope : scope.querySelector(selector); - if (selected) { - break; - } - } - } - current = current.parentNode; - } - - return selected || document.querySelector(selector); - } - return markSupportedForProcessing(result); - } - - function activate(element, Handler) { - return new WinJS.Promise(function activate2(complete, error) { - try { - var options; - var optionsAttribute = element.getAttribute("data-win-options"); - if (optionsAttribute) { - options = WinJS.UI.optionsParser(optionsAttribute, global, { - select: createSelect(element) - }); - } - - var ctl; - var count = 1; - - // handler is required to call complete if it takes that parameter - // - if (Handler.length > 2) { - count++; - } - var checkComplete = function checkComplete() { - count--; - if (count === 0) { - element.winControl = element.winControl || ctl; - complete(ctl); - } - }; - - // async exceptions from the handler get dropped on the floor... - // - ctl = new Handler(element, options, checkComplete); - checkComplete(); - } - catch (err) { - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.errorActivatingControl, err && err.message), "winjs controls", "error"); - error(err); - } - }); - }; - - function processAllImpl(rootElement, skipRootElement) { - return new WinJS.Promise(function processAllImpl2(complete, error) { - msWriteProfilerMark("WinJS.UI:processAll,StartTM"); - rootElement = rootElement || document.body; - var pending = 0; - var selector = "[data-win-control]"; - var allElements = rootElement.querySelectorAll(selector); - var elements = []; - if (!skipRootElement && getControlHandler(rootElement)) { - elements.push(rootElement); - } - for (var i = 0, len = allElements.length; i < len; i++) { - elements.push(allElements[i]); - } - - // bail early if there is nothing to process - // - if (elements.length === 0) { - msWriteProfilerMark("WinJS.UI:processAll,StopTM"); - complete(rootElement); - return; - } - - var checkAllComplete = function () { - pending = pending - 1; - if (pending < 0) { - msWriteProfilerMark("WinJS.UI:processAll,StopTM"); - complete(rootElement); - } - } - - // First go through and determine which elements to activate - // - var controls = new Array(elements.length); - for (var i = 0, len = elements.length; i < len; i++) { - var element = elements[i]; - var control; - var instance = element.winControl; - if (instance) { - control = instance.constructor; - // already activated, don't need to add to controls array - } - else { - controls[i] = control = getControlHandler(element); - } - if (control && control.isDeclarativeControlContainer) { - i += element.querySelectorAll(selector).length; - } - } - - // Now go through and activate those - // - msWriteProfilerMark("WinJS.UI:processAllActivateControls,StartTM"); - for (var i = 0, len = elements.length; i < len; i++) { - var ctl = controls[i]; - var element = elements[i]; - if (ctl && !element.winControl) { - pending++; - activate(element, ctl).then(checkAllComplete, function (e) { - msWriteProfilerMark("WinJS.UI:processAll,StopTM"); - error(e); - }); - - if (ctl.isDeclarativeControlContainer && typeof ctl.isDeclarativeControlContainer === "function") { - var idcc = requireSupportedForProcessing(ctl.isDeclarativeControlContainer); - idcc(element.winControl, WinJS.UI.processAll); - } - } - } - msWriteProfilerMark("WinJS.UI:processAllActivateControls,StopTM"); - - checkAllComplete(); - }); - }; - - function getControlHandler(element) { - if (element.getAttribute) { - var evaluator = element.getAttribute("data-win-control"); - if (evaluator) { - return WinJS.Utilities._getMemberFiltered(evaluator.trim(), global, requireSupportedForProcessing); - } - } - }; - - WinJS.Namespace.define("WinJS.UI", { - - scopedSelect: function (selector, element) { - /// - /// - /// Walks the DOM tree from the given element to the root of the document, whenever - /// a selector scope is encountered select performs a lookup within that scope for - /// the given selector string. The first matching element is returned. - /// - /// The selector string. - /// The target element, if found. - /// - return createSelect(element)(selector); - }, - - processAll: function (rootElement, skipRoot) { - /// - /// - /// Applies declarative control binding to all elements, starting at the specified root element. - /// - /// - /// The element at which to start applying the binding. If this parameter is not specified, the binding is applied to the entire document. - /// - /// - /// If true, the elements to be bound skip the specified root element and include only the children. - /// - /// - /// A promise that is fulfilled when binding has been applied to all the controls. - /// - /// - if (!processedAllCalled) { - return WinJS.Utilities.ready().then(function () { - processedAllCalled = true; - return processAllImpl(rootElement, skipRoot); - }); - } - else { - return processAllImpl(rootElement, skipRoot); - } - }, - - process: function (element) { - /// - /// - /// Applies declarative control binding to the specified element. - /// - /// - /// The element to bind. - /// - /// - /// A promise that is fulfilled after the control is activated. The value of the - /// promise is the control that is attached to element. - /// - /// - - if (element && element.winControl) { - return WinJS.Promise.as(element.winControl); - } - var handler = getControlHandler(element); - if (!handler) { - return WinJS.Promise.as(); // undefined, no handler - } - else { - return activate(element, handler); - } - } - }); -})(this, WinJS); - -(function elementListUtilities(global, WinJS, undefined) { - "use strict"; - - // not supported in WebWorker - if (!global.document) { - return; - } - - WinJS.Namespace.define("WinJS.Utilities", { - QueryCollection: WinJS.Class.derive(Array, function (items) { - /// - /// - /// Represents the result of a query selector, and provides - /// various operations that perform actions over the elements of - /// the collection. - /// - /// - /// The items resulting from the query. - /// - /// - if (items) { - this.include(items); - } - }, { - forEach: function (callbackFn, thisArg) { - /// - /// - /// Performs an action on each item in the QueryCollection - /// - /// - /// Action to perform on each item. - /// - /// - /// Argument to bind to callbackFn - /// - /// - /// Returns the QueryCollection - /// - /// - Array.prototype.forEach.apply(this, [callbackFn, thisArg]); - return this; - }, - get: function (index) { - /// - /// - /// Gets an item from the QueryCollection. - /// - /// - /// The index of the item to return. - /// - /// - /// A single item from the collection. - /// - /// - return this[index]; - }, - setAttribute: function (name, value) { - /// - /// - /// Sets an attribute value on all the items in the collection. - /// - /// - /// The name of the attribute to be set. - /// - /// - /// The value of the attribute to be set. - /// - /// - /// This QueryCollection object. - /// - /// - this.forEach(function (item) { - item.setAttribute(name, value); - }); - return this; - }, - getAttribute: function (name) { - /// - /// - /// Gets an attribute value from the first element in the collection. - /// - /// - /// The name of the attribute. - /// - /// - /// The value of the attribute. - /// - /// - if (this.length > 0) { - return this[0].getAttribute(name); - } - }, - addClass: function (name) { - /// - /// - /// Adds the specified class to all the elements in the collection. - /// - /// - /// The name of the class to add. - /// - /// - /// This QueryCollection object. - /// - /// - this.forEach(function (item) { - WinJS.Utilities.addClass(item, name); - }); - return this; - }, - hasClass: function (name) { - /// - /// - /// Determines whether the specified class exists on the first element of the collection. - /// - /// - /// The name of the class. - /// - /// - /// true if the element has the specified class; otherwise, false. - /// - /// - if (this.length > 0) { - return WinJS.Utilities.hasClass(this[0], name); - } - return false; - }, - removeClass: function (name) { - /// - /// - /// Removes the specified class from all the elements in the collection. - /// - /// - /// The name of the class to be removed. - /// - /// - /// This QueryCollection object. - /// - /// - this.forEach(function (item) { - WinJS.Utilities.removeClass(item, name); - }); - return this; - }, - toggleClass: function (name) { - /// > - /// - /// Toggles (adds or removes) the specified class on all the elements in the collection. - /// If the class is present, it is removed; if it is absent, it is added. - /// - /// - /// The name of the class to be toggled. - /// - /// - /// This QueryCollection object. - /// - /// - this.forEach(function (item) { - WinJS.Utilities.toggleClass(item, name); - }); - return this; - }, - listen: function (eventType, listener, capture) { - /// - /// - /// Registers the listener for the specified event on all the elements in the collection. - /// - /// - /// The name of the event. - /// - /// - /// The event handler function to be called when the event occurs. - /// - /// - /// true if capture == true is to be passed to addEventListener; otherwise, false. - /// - /// - /// This QueryCollection object. - /// - /// - this.forEach(function (item) { - item.addEventListener(eventType, listener, capture); - }); - return this; - }, - removeEventListener: function (eventType, listener, capture) { - /// - /// - /// Unregisters the listener for the specified event on all the elements in the collection. - /// - /// - /// The name of the event. - /// - /// - /// The event handler function. - /// - /// - /// true if capture == true; otherwise, false. - /// - /// - /// This QueryCollection object. - /// - /// - this.forEach(function (item) { - item.removeEventListener(eventType, listener, capture); - }); - return this; - }, - setStyle: function (name, value) { - /// - /// - /// Sets the specified style property for all the elements in the collection. - /// - /// - /// The name of the style property. - /// - /// - /// The value for the property. - /// - /// - /// This QueryCollection object. - /// - /// - this.forEach(function (item) { - item.style[name] = value; - }); - return this; - }, - clearStyle: function (name) { - /// - /// - /// Clears the specified style property for all the elements in the collection. - /// - /// - /// The name of the style property to be cleared. - /// - /// - /// This QueryCollection object. - /// - /// - this.forEach(function (item) { - item.style[name] = ""; - }); - return this; - }, - query: function (query) { - /// - /// - /// Executes a query selector on all the elements in the collection - /// and aggregates the result into a QueryCollection. - /// - /// - /// The query selector string. - /// - /// - /// A QueryCollection object containing the aggregate results of - /// executing the query on all the elements in the collection. - /// - /// - var newCollection = new WinJS.Utilities.QueryCollection(); - this.forEach(function (item) { - newCollection.include(item.querySelectorAll(query)); - }); - return newCollection; - }, - include: function (items) { - /// - /// - /// Adds a set of items to this QueryCollection. - /// - /// - /// The items to add to the QueryCollection. This may be an - /// array-like object, a document fragment, or a single item. - /// - /// - if (typeof items.length === "number") { - for (var i = 0; i < items.length; i++) { - this.push(items[i]); - } - } else if (items.DOCUMENT_FRAGMENT_NODE && items.nodeType === items.DOCUMENT_FRAGMENT_NODE) { - this.include(items.childNodes); - } else { - this.push(items); - } - }, - control: function (Ctor, options) { - /// - /// - /// Creates controls that are attached to the elements in this QueryCollection. - /// - /// - /// A constructor function that is used to create controls to attach to the elements. - /// - /// - /// The options passed to the newly-created controls. - /// - /// - /// This QueryCollection object. - /// - /// - /// - /// - /// Configures the controls that are attached to the elements in this QueryCollection. - /// - /// - /// The options passed to the controls. - /// - /// - /// This QueryCollection object. - /// - /// - - if (Ctor && typeof (Ctor) === "function") { - this.forEach(function (element) { - element.winControl = new Ctor(element, options); - }); - } else { - options = Ctor; - this.forEach(function (element) { - WinJS.UI.process(element).done(function (control) { - control && WinJS.UI.setOptions(control, options); - }) - }); - } - return this; - } - }, { - supportedForProcessing: false, - }), - - query: function (query, element) { - /// - /// - /// Executes a query selector on the specified element or the entire document. - /// - /// - /// The query selector to be executed. - /// - /// - /// The element on which to execute the query. If this parameter is not specified, the - /// query is executed on the entire document. - /// - /// - /// The QueryCollection that contains the results of the query. - /// - /// - return new WinJS.Utilities.QueryCollection((element || document).querySelectorAll(query)); - }, - - id: function (id) { - /// - /// - /// Looks up an element by ID and wraps the result in a QueryCollection. - /// - /// - /// The ID of the element. - /// - /// - /// A QueryCollection that contains the element, if it is found. - /// - /// - var e = document.getElementById(id); - return new WinJS.Utilities.QueryCollection(e ? [e] : []); - }, - - children: function (element) { - /// - /// - /// Creates a QueryCollection that contains the children of the specified parent element. - /// - /// - /// The parent element. - /// - /// - /// The QueryCollection that contains the children of the element. - /// - /// - return new WinJS.Utilities.QueryCollection(element.children); - } - }); - -})(this, WinJS); - -(function elementUtilities(global, WinJS, undefined) { - "use strict"; - - // not supported in WebWorker - if (!global.document) { - return; - } - - function removeEmpties(arr) { - var len = arr.length; - for (var i = len - 1; i >= 0; i--) { - if (!arr[i]) { - arr.splice(i, 1); - len--; - } - } - return len; - } - - function getClassName(e) { - var name = e.className || ""; - if (typeof (name) == "string") { - return name; - } - else { - return name.baseVal || ""; - } - }; - function setClassName(e, value) { - // SVG elements (which use e.className.baseVal) are never undefined, - // so this logic makes the comparison a bit more compact. - // - var name = e.className || ""; - if (typeof (name) == "string") { - e.className = value; - } - else { - e.className.baseVal = value; - } - return e; - }; - function getDimension(element, property) { - return WinJS.Utilities.convertToPixels(element, window.getComputedStyle(element, null)[property]); - } - - WinJS.Namespace.define("WinJS.Utilities", { - _dataKey: "_msDataKey", - _pixelsRE: /^-?\d+(px)?$/i, - _numberRE: /^-?\d+/i, - - /// - /// Defines a set of keyboard values. - /// - Key: { - /// - /// BACKSPACE key. - /// - backspace: 8, - - /// - /// TAB key. - /// - tab: 9, - - /// - /// ENTER key. - /// - enter: 13, - - /// - /// Shift key. - /// - shift: 16, - - /// - /// CTRL key. - /// - ctrl: 17, - - /// - /// ALT key - /// - alt: 18, - - /// - /// Pause key. - /// - pause: 19, - - /// - /// CAPS LOCK key. - /// - capsLock: 20, - - /// - /// ESCAPE key. - /// - escape: 27, - - /// - /// SPACE key. - /// - space: 32, - - /// - /// PAGE UP key. - /// - pageUp: 33, - - /// - /// PAGE DOWN key. - /// - pageDown: 34, - - /// - /// END key. - /// - end: 35, - - /// - /// HOME key. - /// - home: 36, - - /// - /// Left arrow key. - /// - leftArrow: 37, - - /// - /// Up arrow key. - /// - upArrow: 38, - - /// - /// Right arrow key. - /// - rightArrow: 39, - - /// - /// Down arrow key. - /// - downArrow: 40, - - /// - /// INSERT key. - /// - insert: 45, - - /// - /// DELETE key. - /// - deleteKey: 46, - - /// - /// Number 0 key. - /// - num0: 48, - - /// - /// Number 1 key. - /// - num1: 49, - - /// - /// Number 2 key. - /// - num2: 50, - - /// - /// Number 3 key. - /// - num3: 51, - - /// - /// Number 4 key. - /// - num4: 52, - - /// - /// Number 5 key. - /// - num5: 53, - - /// - /// Number 6 key. - /// - num6: 54, - - /// - /// Number 7 key. - /// - num7: 55, - - /// - /// Number 8 key. - /// - num8: 56, - - /// - /// Number 9 key. - /// - num9: 57, - - /// - /// A key. - /// - a: 65, - - /// - /// B key. - /// - b: 66, - - /// - /// C key. - /// - c: 67, - - /// - /// D key. - /// - d: 68, - - /// - /// E key. - /// - e: 69, - - /// - /// F key. - /// - f: 70, - - /// - /// G key. - /// - g: 71, - - /// - /// H key. - /// - h: 72, - - /// - /// I key. - /// - i: 73, - - /// - /// J key. - /// - j: 74, - - /// - /// K key. - /// - k: 75, - - /// - /// L key. - /// - l: 76, - - /// - /// M key. - /// - m: 77, - - /// - /// N key. - /// - n: 78, - - /// - /// O key. - /// - o: 79, - - /// - /// P key. - /// - p: 80, - - /// - /// Q key. - /// - q: 81, - - /// - /// R key. - /// - r: 82, - - /// - /// S key. - /// - s: 83, - - /// - /// T key. - /// - t: 84, - - /// - /// U key. - /// - u: 85, - - /// - /// V key. - /// - v: 86, - - /// - /// W key. - /// - w: 87, - - /// - /// X key. - /// - x: 88, - - /// - /// Y key. - /// - y: 89, - - /// - /// Z key. - /// - z: 90, - - /// - /// Left Windows key. - /// - leftWindows: 91, - - /// - /// Right Windows key. - /// - rightWindows: 92, - - /// - /// Menu key. - /// - menu: 93, - - /// - /// Number pad 0 key. - /// - numPad0: 96, - - /// - /// Number pad 1 key. - /// - numPad1: 97, - - /// - /// Number pad 2 key. - /// - numPad2: 98, - - /// - /// Number pad 3 key. - /// - numPad3: 99, - - /// - /// Number pad 4 key. - /// - numPad4: 100, - - /// - /// Number pad 5 key. - /// - numPad5: 101, - - /// - /// Number pad 6 key. - /// - numPad6: 102, - - /// - /// Number pad 7 key. - /// - numPad7: 103, - - /// - /// Number pad 8 key. - /// - numPad8: 104, - - /// - /// Number pad 9 key. - /// - numPad9: 105, - - /// - /// Multiplication key. - /// - multiply: 106, - - /// - /// Addition key. - /// - add: 107, - - /// - /// Subtraction key. - /// - subtract: 109, - - /// - /// Decimal point key. - /// - decimalPoint: 110, - - /// - /// Division key. - /// - divide: 111, - - /// - /// F1 key. - /// - F1: 112, - - /// - /// F2 key. - /// - F2: 113, - - /// - /// F3 key. - /// - F3: 114, - - /// - /// F4 key. - /// - F4: 115, - - /// - /// F5 key. - /// - F5: 116, - - /// - /// F6 key. - /// - F6: 117, - - /// - /// F7 key. - /// - F7: 118, - - /// - /// F8 key. - /// - F8: 119, - - /// - /// F9 key. - /// - F9: 120, - - /// - /// F10 key. - /// - F10: 121, - - /// - /// F11 key. - /// - F11: 122, - - /// - /// F12 key. - /// - F12: 123, - - /// - /// NUMBER LOCK key. - /// - numLock: 144, - - /// - /// SCROLL LOCK key. - /// - scrollLock: 145, - - /// - /// Browser back key. - /// - browserBack: 166, - - /// - /// Browser forward key. - /// - browserForward: 167, - - /// - /// SEMICOLON key. - /// - semicolon: 186, - - /// - /// EQUAL key. - /// - equal: 187, - - /// - /// COMMA key. - /// - comma: 188, - - /// - /// DASH key. - /// - dash: 189, - - /// - /// PERIOD key. - /// - period: 190, - - /// - /// FORWARD SLASH key. - /// - forwardSlash: 191, - - /// - /// Accent grave key. - /// - graveAccent: 192, - - /// - /// OPEN BRACKET key. - /// - openBracket: 219, - - /// - /// BACKSLASH key. - /// - backSlash: 220, - - /// - /// CLOSE BRACKET key. - /// - closeBracket: 221, - - /// - /// SINGLE QUOTE key. - /// - singleQuote: 222 - }, - - data: function (element) { - /// - /// - /// Gets the data value associated with the specified element. - /// - /// - /// The element. - /// - /// - /// The value associated with the element. - /// - /// - if (!element[WinJS.Utilities._dataKey]) { - element[WinJS.Utilities._dataKey] = {}; - } - return element[WinJS.Utilities._dataKey]; - }, - - hasClass: function (e, name) { - /// - /// - /// Determines whether the specified element has the specified class. - /// - /// - /// The element. - /// - /// - /// The name of the class. - /// - /// - /// true if the specified element contains the specified class; otherwise, false. - /// - /// - - if(e.classList) { - return e.classList.contains(name); - } else { - var className = getClassName(e); - var names = className.trim().split(" "); - var l = names.length; - for (var i = 0; i < l; i++) { - if (names[i] == name) { - return true; - } - } - return false; - } - }, - - addClass: function (e, name) { - /// - /// - /// Adds the specified class(es) to the specified element. Multiple classes can be added using space delimited names. - /// - /// - /// The element to which to add the class. - /// - /// - /// The name of the class to add, multiple classes can be added using space delimited names - /// - /// - /// The element. - /// - /// - if(e.classList) { - // Fastpath: adding a single class, no need to string split the argument - if(name.indexOf(" ") < 0) { - e.classList.add(name); - } else { - var namesToAdd = name.split(" "); - removeEmpties(namesToAdd); - - for (var i = 0, len = namesToAdd.length; i < len; i++) { - e.classList.add(namesToAdd[i]); - } - } - return e; - } else { - var className = getClassName(e); - var names = className.split(" "); - var l = removeEmpties(names); - var toAdd; - - // we have a fast path for the common case of a single name in the class name - // - if (name.indexOf(" ") >= 0) { - var namesToAdd = name.split(" "); - removeEmpties(namesToAdd); - for (var i = 0; i < l; i++) { - var found = namesToAdd.indexOf(names[i]) - if (found >= 0) { - namesToAdd.splice(found, 1); - } - } - if (namesToAdd.length > 0) { - toAdd = namesToAdd.join(" "); - } - } - else { - var saw = false; - for (var i = 0; i < l; i++) { - if (names[i] === name) { - saw = true; - break; - } - } - if (!saw) { toAdd = name; } - - } - if (toAdd) { - if (l > 0 && names[0].length > 0) { - setClassName(e, className + " " + toAdd); - } - else { - setClassName(e, toAdd); - } - } - return e; - } - }, - - removeClass: function (e, name) { - /// - /// - /// Removes the specified class from the specified element. - /// - /// - /// The element from which to remove the class. - /// - /// - /// The name of the class to remove. - /// - /// - /// The element. - /// - /// - if(e.classList) { - - // Fastpath: Nothing to remove - if(e.classList.length === 0) { - return e; - } - var namesToRemove = name.split(" "); - removeEmpties(namesToRemove); - - for (var i = 0, len = namesToRemove.length; i < len; i++) { - e.classList.remove(namesToRemove[i]); - } - return e; - } else { - var original = getClassName(e); - var namesToRemove; - var namesToRemoveLen; - - if (name.indexOf(" ") >= 0) { - namesToRemove = name.split(" "); - namesToRemoveLen = removeEmpties(namesToRemove); - } - else { - // early out for the case where you ask to remove a single - // name and that name isn't found. - // - if (original.indexOf(name) < 0) { - return e; - } - namesToRemove = [name]; - namesToRemoveLen = 1; - } - var removed; - var names = original.split(" "); - var namesLen = removeEmpties(names); - - for (var i = namesLen - 1; i >= 0; i--) { - if (namesToRemove.indexOf(names[i]) >= 0) { - names.splice(i, 1); - removed = true; - } - } - - if (removed) { - setClassName(e, names.join(" ")); - } - return e; - } - }, - - toggleClass: function (e, name) { - /// - /// - /// Toggles (adds or removes) the specified class on the specified element. - /// If the class is present, it is removed; if it is absent, it is added. - /// - /// - /// The element on which to toggle the class. - /// - /// - /// The name of the class to toggle. - /// - /// - /// The element. - /// - /// - if(e.classList) { - e.classList.toggle(name); - return e; - } else { - var className = getClassName(e); - var names = className.trim().split(" "); - var l = names.length; - var found = false; - for (var i = 0; i < l; i++) { - if (names[i] == name) { - found = true; - } - } - if (!found) { - if (l > 0 && names[0].length > 0) { - setClassName(e, className + " " + name); - } - else { - setClassName(e, className + name); - } - } - else { - setClassName(e, names.reduce(function (r, e) { - if (e == name) { - return r; - } - else if (r && r.length > 0) { - return r + " " + e; - } - else { - return e; - } - }, "")); - } - return e; - } - }, - - getRelativeLeft: function (element, parent) { - /// - /// - /// Gets the left coordinate of the specified element relative to the specified parent. - /// - /// - /// The element. - /// - /// - /// The parent element. - /// - /// - /// The relative left coordinate. - /// - /// - if (!element) { - return 0; - } - - var left = element.offsetLeft; - var e = element.parentNode; - while (e) { - left -= e.offsetLeft; - - if (e === parent) - break; - e = e.parentNode; - } - - return left; - }, - - getRelativeTop: function (element, parent) { - /// - /// - /// Gets the top coordinate of the element relative to the specified parent. - /// - /// - /// The element. - /// - /// - /// The parent element. - /// - /// - /// The relative top coordinate. - /// - /// - if (!element) { - return 0; - } - - var top = element.offsetTop; - var e = element.parentNode; - while (e) { - top -= e.offsetTop; - - if (e === parent) - break; - e = e.parentNode; - } - - return top; - }, - - empty: function (element) { - /// - /// - /// Removes all the child nodes from the specified element. - /// - /// - /// The element. - /// - /// - /// The element. - /// - /// - if (element.childNodes && element.childNodes.length > 0) { - for (var i = element.childNodes.length - 1; i >= 0; i--) { - element.removeChild(element.childNodes.item(i)); - } - } - return element; - }, - - _isDOMElement: function (element) { - return element && - typeof element === "object" && - typeof element.tagName === "string"; - }, - - getContentWidth: function (element) { - /// - /// - /// Gets the width of the content of the specified element. The content width does not include borders or padding. - /// - /// - /// The element. - /// - /// - /// The content width of the element. - /// - /// - var border = getDimension(element, "borderLeftWidth") + getDimension(element, "borderRightWidth"), - padding = getDimension(element, "paddingLeft") + getDimension(element, "paddingRight"); - return element.offsetWidth - border - padding; - }, - - getTotalWidth: function (element) { - /// - /// - /// Gets the width of the element, including margins. - /// - /// - /// The element. - /// - /// - /// The width of the element including margins. - /// - /// - var margin = getDimension(element, "marginLeft") + getDimension(element, "marginRight"); - return element.offsetWidth + margin; - }, - - getContentHeight: function (element) { - /// - /// - /// Gets the height of the content of the specified element. The content height does not include borders or padding. - /// - /// - /// The element. - /// - /// - /// The content height of the element. - /// - /// - var border = getDimension(element, "borderTopWidth") + getDimension(element, "borderBottomWidth"), - padding = getDimension(element, "paddingTop") + getDimension(element, "paddingBottom"); - return element.offsetHeight - border - padding; - }, - - getTotalHeight: function (element) { - /// - /// - /// Gets the height of the element, including its margins. - /// - /// - /// The element. - /// - /// - /// The height of the element including margins. - /// - /// - var margin = getDimension(element, "marginTop") + getDimension(element, "marginBottom"); - return element.offsetHeight + margin; - }, - - getPosition: function (element) { - /// - /// - /// Gets the position of the specified element. - /// - /// - /// The element. - /// - /// - /// An object that contains the left, top, width and height properties of the element. - /// - /// - var fromElement = element, - offsetParent = element.offsetParent, - top = element.offsetTop, - left = element.offsetLeft; - - while ((element = element.parentNode) && - element !== document.body && - element !== document.documentElement) { - top -= element.scrollTop; - var dir = document.defaultView.getComputedStyle(element, null).direction; - left -= dir !== "rtl" ? element.scrollLeft : -element.scrollLeft; - - if (element === offsetParent) { - top += element.offsetTop; - left += element.offsetLeft; - offsetParent = element.offsetParent; - } - } - - return { - left: left, - top: top, - width: fromElement.offsetWidth, - height: fromElement.offsetHeight - }; - }, - - convertToPixels: function (element, value) { - /// - /// - /// Converts a CSS positioning string for the specified element to pixels. - /// - /// - /// The element. - /// - /// - /// The CSS positioning string. - /// - /// - /// The number of pixels. - /// - /// - if (!this._pixelsRE.test(value) && this._numberRE.test(value)) { - var previousValue = element.style.left; - - element.style.left = value; - value = element.style.pixelLeft; - - element.style.left = previousValue; - - return value; - } else { - return parseInt(value, 10) || 0; - } - }, - - eventWithinElement: function (element, event) { - /// - /// - /// Determines whether the specified event occurred within the specified element. - /// - /// - /// The element. - /// - /// - /// The event. - /// - /// - /// true if the event occurred within the element; otherwise, false. - /// - /// - var related = event.relatedTarget; - if (related && related !== element) { - return element.contains(related); - } - - return false; - } - }); -})(this, WinJS); - -(function fragmentControlInit(global) { - "use strict"; - - // not supported in WebWorker - if (!global.document) { - return; - } - - function abs(uri) { - var a = document.createElement("a"); - a.href = uri; - return a.href.toLowerCase(); - } - var viewMap = {}; - - function selfhost(uri) { - return document.location.href.toLowerCase() === uri.toLowerCase(); - } - - WinJS.Namespace.define("WinJS.UI.Pages", { - _mixin: { - dispose: function () { - /// - /// - /// Disposes this Page. - /// - /// - if (this._disposed) { - return; - } - - this._disposed = true; - WinJS.Utilities.disposeSubTree(this.element); - this.element = null; - }, - load: function (uri) { - /// - /// - /// Creates a copy of the DOM elements from the specified URI. In order for this override - /// to be used, the page that contains the load override needs to be defined by calling - /// WinJS.UI.Pages.define() before WinJS.UI.Pages.render() is called. - /// - /// - /// The URI from which to copy the DOM elements. - /// - /// - /// A promise whose fulfilled value is the set of unparented DOM elements, if asynchronous processing is necessary. If not, returns nothing. - /// - /// - if (!this.selfhost) { - return WinJS.UI.Fragments.renderCopy(abs(uri)); - } - }, - init: function (element, options) { - /// - /// - /// Initializes the control before the content of the control is set. - /// Use the processed method for any initialization that should be done after the content - /// of the control has been set. - /// - /// - /// The DOM element that will contain all the content for the page. - /// - /// - /// The options passed to the constructor of the page. - /// - /// - /// A promise that is fulfilled when initialization is complete, if asynchronous processing is necessary. If not, returns nothing. - /// - /// - }, - processed: function (element, options) { - /// - /// - /// Initializes the control after the content of the control is set. - /// - /// - /// The DOM element that will contain all the content for the page. - /// - /// - /// The options that are to be passed to the constructor of the page. - /// - /// - /// A promise that is fulfilled when initialization is complete, if asynchronous processing is necessary. If not, returns nothing. - /// - /// - }, - render: function (element, options, loadResult) { - /// - /// - /// Renders the control, typically by adding the elements specified in the loadResult parameter to the specified element. - /// - /// - /// The DOM element that will contain all the content for the page. - /// - /// - /// The options passed into the constructor of the page. - /// - /// - /// The elements returned from the load method. - /// - /// - /// A promise that is fulfilled when rendering is complete, if asynchronous processing is necessary. If not, returns nothing. - /// - /// - if (!this.selfhost) { - element.appendChild(loadResult); - } - return element; - }, - ready: function (element, options) { - /// - /// - /// Called after all initialization and rendering is complete. At this - /// time the element is ready for use. - /// - /// - /// The DOM element that contains all the content for the page. - /// - /// - /// The options passed into the constructor of the page - /// - /// - }, - error: function (err) { - /// - /// - /// Called if any error occurs during the processing of the page. - /// - /// - /// The error that occurred. - /// - /// - /// Nothing if the error was handled, or an error promise if the error was not handled. - /// - /// - return WinJS.Promise.wrapError(err); - } - }, - define: function (uri, members) { - /// - /// - /// Creates a new page control from the specified URI that contains the specified members. - /// Multiple calls to this method for the same URI are allowed, and all members will be - /// merged. - /// - /// - /// The URI for the content that defines the page. - /// - /// - /// Additional members that the control will have. - /// - /// - /// A constructor function that creates the page. - /// - /// - uri = abs(uri); - - var base = viewMap[uri.toLowerCase()]; - if (!base) { - base = WinJS.Class.define( - // This needs to follow the WinJS.UI.processAll "async constructor" - // pattern to interop nicely in the "Views.Control" use case. - // - function PageControl_ctor(element, options, complete, parentedPromise) { - var that = this; - this._disposed = false; - this.element = element = element || document.createElement("div"); - WinJS.Utilities.addClass(element, "win-disposable"); - element.msSourceLocation = uri; - this.uri = uri; - this.selfhost = selfhost(uri); - element.winControl = this; - WinJS.Utilities.addClass(element, "pagecontrol"); - - var profilerMarkIdentifier = " uri='" + uri + "'" + WinJS.Utilities._getProfilerMarkIdentifier(this.element); - - msWriteProfilerMark("WinJS.UI.Pages:createPage" + profilerMarkIdentifier + ",StartTM"); - - var load = WinJS.Promise.wrap(). - then(function Pages_load() { return that.load(uri); }); - - var renderCalled = load.then(function Pages_init(loadResult) { - return WinJS.Promise.join({ - loadResult: loadResult, - initResult: that.init(element, options) - }); - }).then(function Pages_render(result) { - return that.render(element, options, result.loadResult); - }); - - this.elementReady = renderCalled.then(function () { return element; }); - - this.renderComplete = renderCalled. - then(function Pages_processAll(f) { - return WinJS.UI.processAll(f).then(function () { return f; }); - }).then(function Pages_processed(f) { - return that.processed(element, options); - }).then(function () { - return that; - }); - - var callComplete = function () { - complete && complete(that); - msWriteProfilerMark("WinJS.UI.Pages:createPage" + profilerMarkIdentifier + ",StopTM"); - }; - - // promises guarantee order, so this will be called prior to ready path below - // - this.renderComplete.then(callComplete, callComplete); - - this.renderComplete.then(function () { - return parentedPromise; - }).then(function Pages_ready() { - that.ready(element, options); - }).then( - null, - function Pages_error(err) { - return that.error(err); - } - ); - }, - WinJS.UI.Pages._mixin - ); - base = WinJS.Class.mix(base, WinJS.UI.DOMEventMixin); - viewMap[uri.toLowerCase()] = base; - } - - // Lazily mix in the members, allowing for multiple definitions of "define" to augment - // the shared definition of the member. - // - if (members) { - base = WinJS.Class.mix(base, members); - } - - if (selfhost(uri)) { - WinJS.Utilities.ready(function () { - WinJS.UI.Pages.render(uri, document.body); - }); - } - - return base; - }, - - get: function (uri) { - /// - /// - /// Gets an already-defined page control for the specified URI, or creates a new one. - /// - /// - /// The URI for the content that defines the page. - /// - /// - /// A constructor function that creates the page. - /// - /// - uri = abs(uri); - var ctor = viewMap[uri.toLowerCase()]; - if (!ctor) { - ctor = WinJS.UI.Pages.define(uri); - } - return ctor; - }, - - _remove: function (uri) { - uri = abs(uri); - WinJS.UI.Fragments.clearCache(uri); - delete viewMap[uri] - }, - - render: function (uri, element, options, parentedPromise) { - /// - /// - /// Creates a page control from the specified URI inside - /// the specified element with the specified options. - /// - /// - /// The URI for the content that defines the page. - /// - /// - /// The element to populate with the page. - /// - /// - /// The options for configuring the page. - /// - /// - /// A promise that is fulfilled when the specified element is parented to the final document. - /// - /// - /// A promise that is fulfilled when the page is done rendering - /// - /// - var Ctor = WinJS.UI.Pages.get(uri); - var control = new Ctor(element, options, null, parentedPromise); - return control.renderComplete; - } - }); - - WinJS.Namespace.define("WinJS.UI", { - /// - /// Enables you to include an HTML page dynamically. - /// - /// HtmlControl - /// - /// - /// ]]> - /// - /// - HtmlControl: WinJS.Class.define(function HtmlControl_ctor(element, options, complete) { - /// - /// - /// Initializes a new instance of HtmlControl to define a new page control. - /// - /// - /// The element that hosts the HtmlControl. - /// - /// - /// The options for configuring the page. The uri option is required in order to specify the source - /// document for the content of the page. - /// - /// - WinJS.UI.Pages.render(options.uri, element, options). - then(complete, function () { complete(); }); - }) - }); -})(this); -(function fragmentLoaderInit(global, WinJS, undefined) { - "use strict"; - - var strings = { - get invalidFragmentUri() { return WinJS.Resources._getWinJSString("base/invalidFragmentUri").value; }, - }; - - // not supported in WebWorker - if (!global.document) { - return; - } - - var forEach = function (arrayLikeValue, action) { - for (var i = 0, l = arrayLikeValue.length; i < l; i++) { - action(arrayLikeValue[i], i); - } - }; - var head = document.head || document.getElementsByTagName("head")[0]; - var scripts = {}; - var styles = {}; - var links = {}; - var initialized = false; - var cacheStore = {}; - var uniqueId = 1; - - function addScript(scriptTag, fragmentHref, position, lastNonInlineScriptPromise) { - // We synthesize a name for inline scripts because today we put the - // inline scripts in the same processing pipeline as src scripts. If - // we seperated inline scripts into their own logic, we could simplify - // this somewhat. - // - var src = scriptTag.src; - var inline = !src; - if (inline) { - src = fragmentHref + "script[" + position + "]"; - } - src = src.toLowerCase(); - - if (!(src in scripts)) { - var promise = null; - - scripts[src] = true; - var n = document.createElement("script"); - if (scriptTag.language) { - n.setAttribute("language", "javascript"); - } - n.setAttribute("type", scriptTag.type); - n.setAttribute("async", "false"); - if (scriptTag.id) { - n.setAttribute("id", scriptTag.id); - } - if (inline) { - var text = scriptTag.text; - promise = lastNonInlineScriptPromise.then(function () { - n.text = text; - }).then(null, function () { - // eat error - }); - } - else { - promise = new WinJS.Promise(function (c) { - n.onload = n.onerror = function () { - c(); - }; - n.setAttribute("src", scriptTag.src); - }); - } - head.appendChild(n); - - return { - promise: promise, - inline: inline, - }; - } - }; - - function addStyle(styleTag, fragmentHref, position) { - var src = (fragmentHref + "script[" + position + "]").toLowerCase(); - if (!(src in styles)) { - styles[src] = true; - head.appendChild(styleTag.cloneNode(true)); - } - }; - - function addLink(styleTag) { - var src = styleTag.href.toLowerCase(); - if (!(src in links)) { - links[src] = true; - var n = styleTag.cloneNode(false); - n.href = styleTag.href; - head.appendChild(n); - } - }; - - function getStateRecord(href, removeFromCache) { - if (typeof href === "string") { - return loadFromCache(href, removeFromCache); - } - else { - var state = { - docfrag: WinJS.Utilities.data(href).docFragment - }; - if (!state.docfrag) { - var fragment = document.createDocumentFragment(); - while (href.childNodes.length > 0) { - fragment.appendChild(href.childNodes[0]); - }; - state.docfrag = WinJS.Utilities.data(href).docFragment = fragment; - href.setAttribute("data-win-hasfragment", ""); - } - if (removeFromCache) { - clearCache(href); - } - return WinJS.Promise.as(state); - } - } - function createEntry(state, href) { - return WinJS.UI.Fragments._populateDocument(state, href). - then(function () { - if (state.document) { - return processDocument(href, state); - } - else { - return state; - } - }). - then(WinJS.UI.Fragments._cleanupDocument). - then(function () { - return state; - }); - } - - function loadFromCache(href, removeFromCache) { - var fragmentId = href.toLowerCase(); - var state = cacheStore[fragmentId]; - - if (state) { - if (removeFromCache) { - delete cacheStore[fragmentId]; - } - if (state.promise) { - return state.promise; - } - else { - return WinJS.Promise.as(state); - } - } - else { - state = {}; - if (!removeFromCache) { - cacheStore[fragmentId] = state; - } - var result = state.promise = createEntry(state, href); - state.promise.then(function () { delete state.promise; }); - return result; - } - } - - function processDocument(href, state) { - // Once the control's static state has been loaded in the temporary iframe, - // this method spelunks the iframe's document to retrieve all relevant information. Also, - // this performs any needed fixups on the DOM (like adjusting relative URLs). - - var cd = state.document; - var b = cd.body; - var sp = []; - - forEach(cd.querySelectorAll('link[rel="stylesheet"], link[type="text/css"]'), addLink); - forEach(cd.getElementsByTagName('style'), function (e, i) { addStyle(e, href, i); }); - - // In DOCMODE 11 IE moved to the standards based script loading behavior of - // having out-of-line script elements which are dynamically added to the DOM - // asynchronously load. This raises two problems for our fragment loader, - // - // 1) out-of-line scripts need to execute in order - // - // 2) so do in-line scripts. - // - // In order to mitigate this behavior we do two things: - // - // A) We mark all scripts with the attribute async='false' which makes - // out-of-line scripts respect DOM append order for execution when they - // are eventually retrieved - // - // B) We chain the setting of in-line script element's 'text' property - // on the completion of the previous out-of-line script's execution. - // This relies on the fact that the out-of-line script elements will - // synchronously run their onload handler immediately after executing - // thus assuring that the in-line script will run before the next - // trailing out-of-line script. - // - var lastNonInlineScriptPromise = WinJS.Promise.as(); - forEach(cd.getElementsByTagName('script'), function (e, i) { - var result = addScript(e, href, i, lastNonInlineScriptPromise); - if (result) { - if (!result.inline) { - lastNonInlineScriptPromise = result.promise; - } - sp.push(result.promise); - } - }); - - forEach(b.getElementsByTagName('img'), function (e) { e.src = e.src; }); - forEach(b.getElementsByTagName('a'), function (e) { - // for # only anchor tags, we don't update the href - // - if (e.href !== "") { - var href = e.getAttribute("href"); - if (href && href[0] != "#") { - e.href = e.href; - } - } - }); - - // strip inline scripts from the body, they got copied to the - // host document with the rest of the scripts above... - // - var localScripts = b.getElementsByTagName("script"); - while (localScripts.length > 0) { - var s = localScripts[0]; - s.parentNode.removeChild(s); - } - - return WinJS.Promise.join(sp).then(function () { - // Create the docfrag which is just the body children - // - var fragment = document.createDocumentFragment(); - var imported = document.importNode(cd.body, true); - while (imported.childNodes.length > 0) { - fragment.appendChild(imported.childNodes[0]); - } - state.docfrag = fragment; - - return state; - }); - }; - - function initialize() { - if (initialized) { return; } - - initialized = true; - - forEach(head.querySelectorAll("script"), function (e) { - scripts[e.src.toLowerCase()] = true; - }); - - - forEach(head.querySelectorAll('link[rel="stylesheet"], link[type="text/css"]'), function (e) { - links[e.href.toLowerCase()] = true; - }); - }; - - function renderCopy(href, target) { - /// - /// - /// Copies the contents of the specified URI into the specified element. - /// - /// - /// The URI that contains the fragment to copy. - /// - /// - /// The element to which the fragment is appended. - /// - /// - /// A promise that is fulfilled when the fragment has been loaded. - /// If a target element is not specified, the copied fragment is the - /// completed value. - /// - /// - - return renderImpl(href, target, true); - }; - - function renderImpl(href, target, copy) { - var profilerMarkIdentifier = (href instanceof HTMLElement ? WinJS.Utilities._getProfilerMarkIdentifier(href) : " href='" + href + "'") + "[" + (++uniqueId) + "]"; - msWriteProfilerMark("WinJS.UI.Fragments:render" + profilerMarkIdentifier + ",StartTM"); - - initialize(); - return getStateRecord(href, !copy).then(function (state) { - var frag = state.docfrag; - if (copy) { - frag = frag.cloneNode(true); - } - - var child = frag.firstChild; - while (child) { - if (child.nodeType === 1 /*Element node*/) { - child.msParentSelectorScope = true; - } - child = child.nextSibling; - } - - var retVal; - if (target) { - target.appendChild(frag); - retVal = target; - } - else { - retVal = frag; - } - msWriteProfilerMark("WinJS.UI.Fragments:render" + profilerMarkIdentifier + ",StopTM"); - return retVal; - }); - }; - - function render(href, target) { - /// - /// - /// Copies the contents of the specified URI into the specified element. - /// - /// - /// The URI that contains the fragment to copy. - /// - /// - /// The element to which the fragment is appended. - /// - /// - /// A promise that is fulfilled when the fragment has been loaded. - /// If a target element is not specified, the copied fragment is the - /// completed value. - /// - /// - - return renderImpl(href, target, false); - }; - - function cache(href) { - /// - /// - /// Starts loading the fragment at the specified location. The returned promise completes - /// when the fragment is ready to be copied. - /// - /// - /// The URI that contains the fragment to be copied. - /// - /// - /// A promise that is fulfilled when the fragment has been prepared for copying. - /// - /// - initialize(); - return getStateRecord(href).then(function (state) { return state.docfrag; }); - }; - - function clearCache(href) { - /// - /// - /// Removes any cached information about the specified fragment. This method does not unload any scripts - /// or styles that are referenced by the fragment. - /// - /// - /// The URI that contains the fragment to be cleared. If no URI is provided, the entire contents of the cache are cleared. - /// - /// - - if (!href) { - cacheStore = {}; - } - else if (typeof (href) == "string") { - delete cacheStore[href.toLowerCase()]; - } - else { - delete WinJS.Utilities.data(href).docFragment; - href.removeAttribute("data-win-hasfragment"); - } - }; - - function forceLocal(uri) { - if (WinJS.Utilities.hasWinRT) { - // we force the URI to be cannonicalized and made absolute by IE - // - var a = document.createElement("a"); - a.href = uri; - - var absolute = a.href; - - // WinRT Uri class doesn't provide URI construction, but can crack the URI - // appart to let us reliably discover the scheme. - // - var wuri = new Windows.Foundation.Uri(absolute); - - // Only "ms-appx" (local package content) are allowed when running in the local - // context. Both strings are known to be safe to compare in any culture (including Turkish). - // - var scheme = wuri.schemeName; - if (scheme !== "ms-appx") { - - throw new WinJS.ErrorFromName("WinJS.UI.Fragments.InvalidUri", strings.invalidFragmentUri); - } - - return absolute; - } - return uri; - } - - WinJS.Namespace.define("WinJS.UI.Fragments", { - renderCopy: renderCopy, - render: render, - cache: cache, - clearCache: clearCache, - _cacheStore: { get: function () { return cacheStore; } }, - _forceLocal: forceLocal - }); -})(this, WinJS); - -(function fragmentLoader2Init(global) { - "use strict"; - - // not supported in WebWorker - if (!global.document) { - return; - } - - function cleanupDocumentIFrame(state) { - // This is to work around a weird bug where removing the - // IFrame from the DOM triggers DOMContentLoaded a second time. - var temp = state.iframe; - if (temp) { - temp.contentDocument.removeEventListener("DOMContentLoaded", state.domContentLoaded, false); - temp.parentNode.removeChild(temp); - delete state.document; - delete state.iframe; - delete state.domContentLoaded; - } - }; - - function populateDocumentIFrame(state, href) { - return new WinJS.Promise(function (c, e, p) { - var temp = document.createElement('iframe'); - temp.src = href; - temp.style.display = 'none'; - - state.domContentLoaded = function () { - state.document = temp.contentDocument; - state.iframe = temp; - c(); - }; - - document.body.appendChild(temp); - temp.contentWindow.onerror = function (e) { - // It's OK to swallow these as they will occur in the main document - // - return true; - }; - temp.contentDocument.addEventListener("DOMContentLoaded", state.domContentLoaded, false); - }); - }; - - function cleanupDocumentXHR(state) { - if (state.document) { - delete state.document; - } - return WinJS.Promise.as(); - }; - - function populateDocumentXHR(state, href) { - // Because we later use "setInnerHTMLUnsafe" ("Unsafe" is the magic word here), we - // want to force the href to only support local package content when running - // in the local context. When running in the web context, this will be a no-op. - // - href = WinJS.UI.Fragments._forceLocal(href); - - var htmlDoc = document.implementation.createHTMLDocument("frag"); - var base = htmlDoc.createElement("base"); - htmlDoc.head.appendChild(base); - var anchor = htmlDoc.createElement("a"); - htmlDoc.body.appendChild(anchor); - base.href = document.location.href; // Initialize base URL to primary document URL - anchor.setAttribute("href", href); // Resolve the relative path to an absolute path - base.href = anchor.href; // Update the base URL to be the resolved absolute path - // 'anchor' is no longer needed at this point and will be removed by the innerHTML call - state.document = htmlDoc; - return WinJS.xhr({ url: href }).then(function (req) { - WinJS.Utilities.setInnerHTMLUnsafe(htmlDoc.documentElement, req.responseText); - htmlDoc.head.appendChild(base); - }); - }; - - if (global.MSApp) { - WinJS.Namespace.define("WinJS.UI.Fragments", { - _populateDocument: populateDocumentXHR, - _cleanupDocument: cleanupDocumentXHR - }); - } - else { - WinJS.Namespace.define("WinJS.UI.Fragments", { - _populateDocument: populateDocumentIFrame, - _cleanupDocument: cleanupDocumentIFrame - }); - } -})(this); - -(function optionsLexerInit(global, undefined) { - "use strict"; - - /* - -Lexical grammar is defined in ECMA-262-5, section 7. - -Lexical productions used in this grammar defined in ECMA-262-5: - -Production Section --------------------------------- -Identifier 7.6 -NullLiteral 7.8.1 -BooleanLiteral 7.8.2 -NumberLiteral 7.8.3 -StringLiteral 7.8.4 - -*/ - - WinJS.Namespace.define("WinJS.UI", { - _optionsLexer: WinJS.Namespace._lazy(function () { - - var tokenType = { - leftBrace: 1, // { - rightBrace: 2, // } - leftBracket: 3, // [ - rightBracket: 4, // ] - separator: 5, // ECMA-262-5, 7.2 - colon: 6, // : - semicolon: 7, // ; - comma: 8, // , - dot: 9, // . - nullLiteral: 10, // ECMA-262-5, 7.8.1 (null) - trueLiteral: 11, // ECMA-262-5, 7.8.2 (true) - falseLiteral: 12, // ECMA-262-5, 7.8.2 (false) - numberLiteral: 13, // ECMA-262-5, 7.8.3 - stringLiteral: 14, // ECMA-262-5, 7.8.4 - identifier: 15, // ECMA-262-5, 7.6 - reservedWord: 16, - thisKeyword: 17, - leftParentheses: 18, // ( - rightParentheses: 19, // ) - eof: 20, - error: 21 - }; - // debugging - this costs something like 20% - // - //Object.keys(tokenType).forEach(function (key) { - // tokenType[key] = key.toString(); - //}); - var tokens = { - leftBrace: { type: tokenType.leftBrace, length: 1 }, - rightBrace: { type: tokenType.rightBrace, length: 1 }, - leftBracket: { type: tokenType.leftBracket, length: 1 }, - rightBracket: { type: tokenType.rightBracket, length: 1 }, - colon: { type: tokenType.colon, length: 1 }, - semicolon: { type: tokenType.semicolon, length: 1 }, - comma: { type: tokenType.comma, length: 1 }, - dot: { type: tokenType.dot, length: 1 }, - nullLiteral: { type: tokenType.nullLiteral, length: 4, value: null, keyword: true }, - trueLiteral: { type: tokenType.trueLiteral, length: 4, value: true, keyword: true }, - falseLiteral: { type: tokenType.falseLiteral, length: 5, value: false, keyword: true }, - thisKeyword: { type: tokenType.thisKeyword, length: 4, value: "this", keyword: true }, - leftParentheses: { type: tokenType.leftParentheses, length: 1 }, - rightParentheses: { type: tokenType.rightParentheses, length: 1 }, - eof: { type: tokenType.eof, length: 0 } - }; - - function reservedWord(word) { - return { type: tokenType.reservedWord, value: word, length: word.length, keyword: true }; - } - function reservedWordLookup(identifier) { - // Moving from a simple object literal lookup for reserved words to this - // switch was worth a non-trivial performance increase (5-7%) as this path - // gets taken for any identifier. - // - switch (identifier.charCodeAt(0)) { - case /*b*/98: - switch (identifier) { - case 'break': - return reservedWord(identifier); - } - break; - - case /*c*/99: - switch (identifier) { - case 'case': - case 'catch': - case 'class': - case 'const': - case 'continue': - return reservedWord(identifier); - } - break; - - case /*d*/100: - switch (identifier) { - case 'debugger': - case 'default': - case 'delete': - case 'do': - return reservedWord(identifier); - } - break; - - case /*e*/101: - switch (identifier) { - case 'else': - case 'enum': - case 'export': - case 'extends': - return reservedWord(identifier); - } - break; - - case /*f*/102: - switch (identifier) { - case 'false': - return tokens.falseLiteral; - - case 'finally': - case 'for': - case 'function': - return reservedWord(identifier); - } - - break; - case /*i*/105: - switch (identifier) { - case 'if': - case 'import': - case 'in': - case 'instanceof': - return reservedWord(identifier); - } - break; - - case /*n*/110: - switch (identifier) { - case 'null': - return tokens.nullLiteral; - - case 'new': - return reservedWord(identifier); - } - break; - - case /*r*/114: - switch (identifier) { - case 'return': - return reservedWord(identifier); - } - break; - - case /*s*/115: - switch (identifier) { - case 'super': - case 'switch': - return reservedWord(identifier); - } - break; - - case /*t*/116: - switch (identifier) { - case 'true': - return tokens.trueLiteral; - - case 'this': - return tokens.thisKeyword; - - case 'throw': - case 'try': - case 'typeof': - return reservedWord(identifier); - } - break; - - case /*v*/118: - switch (identifier) { - case 'var': - case 'void': - return reservedWord(identifier); - } - break; - - case /*w*/119: - switch (identifier) { - case 'while': - case 'with': - return reservedWord(identifier); - } - break; - } - return; - } - - var lexer = (function () { - function isIdentifierStartCharacter(code, text, offset, limit) { - // The ES5 spec decalares that identifiers consist of a bunch of unicode classes, without - // WinRT support for determining unicode class membership we are looking at 2500+ lines of - // javascript code to encode the relevant class tables. Instead we look for everything - // which is legal and < 0x7f, we exclude whitespace and line terminators, and then accept - // everything > 0x7f. - // - // Here's the ES5 production: - // - // Lu | Ll | Lt | Lm | Lo | Nl - // $ - // _ - // \ UnicodeEscapeSequence - // - switch (code) { - case (code >= /*a*/97 && code <= /*z*/122) && code: - case (code >= /*A*/65 && code <= /*Z*/90) && code: - case /*$*/36: - case /*_*/95: - return true; - - case isWhitespace(code) && code: - case isLineTerminator(code) && code: - return false; - - case (code > 0x7f) && code: - return true; - - case /*\*/92: - if (offset + 4 < limit) { - if (text.charCodeAt(offset) === /*u*/117 && - isHexDigit(text.charCodeAt(offset + 1)) && - isHexDigit(text.charCodeAt(offset + 2)) && - isHexDigit(text.charCodeAt(offset + 3)) && - isHexDigit(text.charCodeAt(offset + 4))) { - return true; - } - } - return false; - - default: - return false; - } - } - /* - // Hand-inlined into readIdentifierPart - function isIdentifierPartCharacter(code) { - // See comment in isIdentifierStartCharacter. - // - // Mn | Mc | Nd | Pc - // | - // - switch (code) { - case isIdentifierStartCharacter(code) && code: - case isDecimalDigit(code) && code: - return true; - - default: - return false; - } - } - */ - function readIdentifierPart(text, offset, limit) { - var hasEscape = false; - while (offset < limit) { - var code = text.charCodeAt(offset); - switch (code) { - //case isIdentifierStartCharacter(code) && code: - case (code >= /*a*/97 && code <= /*z*/122) && code: - case (code >= /*A*/65 && code <= /*Z*/90) && code: - case /*$*/36: - case /*_*/95: - break; - - case isWhitespace(code) && code: - case isLineTerminator(code) && code: - return hasEscape ? -offset : offset; - - case (code > 0x7f) && code: - break; - - //case isDecimalDigit(code) && code: - case (code >= /*0*/48 && code <= /*9*/57) && code: - break; - - case /*\*/92: - if (offset + 5 < limit) { - if (text.charCodeAt(offset + 1) === /*u*/117 && - isHexDigit(text.charCodeAt(offset + 2)) && - isHexDigit(text.charCodeAt(offset + 3)) && - isHexDigit(text.charCodeAt(offset + 4)) && - isHexDigit(text.charCodeAt(offset + 5))) { - offset += 5; - hasEscape = true; - break; - } - } - return hasEscape ? -offset : offset; - - default: - return hasEscape ? -offset : offset; - } - offset++; - } - return hasEscape ? -offset : offset; - } - function readIdentifierToken(text, offset, limit) { - var startOffset = offset; - offset = readIdentifierPart(text, offset, limit); - var hasEscape = false; - if (offset < 0) { - offset = -offset; - hasEscape = true; - } - var identifier = text.substr(startOffset, offset - startOffset); - if (hasEscape) { - identifier = "" + JSON.parse('"' + identifier + '"'); - } - var wordToken = reservedWordLookup(identifier); - if (wordToken) { - return wordToken; - } - return { - type: tokenType.identifier, - length: offset - startOffset, - value: identifier - }; - } - function isHexDigit(code) { - switch (code) { - case (code >= /*0*/48 && code <= /*9*/57) && code: - case (code >= /*a*/97 && code <= /*f*/102) && code: - case (code >= /*A*/65 && code <= /*F*/70) && code: - return true; - - default: - return false; - } - } - function readHexIntegerLiteral(text, offset, limit) { - while (offset < limit && isHexDigit(text.charCodeAt(offset))) { - offset++; - } - return offset; - } - function isDecimalDigit(code) { - switch (code) { - case (code >= /*0*/48 && code <= /*9*/57) && code: - return true; - - default: - return false; - } - } - function readDecimalDigits(text, offset, limit) { - while (offset < limit && isDecimalDigit(text.charCodeAt(offset))) { - offset++; - } - return offset; - } - function readDecimalLiteral(text, offset, limit) { - offset = readDecimalDigits(text, offset, limit); - if (offset < limit && text.charCodeAt(offset) === /*.*/46 && offset + 1 < limit && isDecimalDigit(text.charCodeAt(offset + 1))) { - offset = readDecimalDigits(text, offset + 2, limit); - } - if (offset < limit) { - var code = text.charCodeAt(offset); - if (code === /*e*/101 || code === /*E*/69) { - var tempOffset = offset + 1; - if (tempOffset < limit) { - code = text.charCodeAt(tempOffset); - if (code === /*+*/43 || code === /*-*/45) { - tempOffset++; - } - offset = readDecimalDigits(text, tempOffset, limit); - } - } - } - return offset; - } - function readDecimalLiteralToken(text, start, offset, limit) { - var offset = readDecimalLiteral(text, offset, limit); - var length = offset - start; - return { - type: tokenType.numberLiteral, - length: length, - value: +text.substr(start, length) - }; - } - function isLineTerminator(code) { - switch (code) { - case 0x000A: // line feed - case 0x000D: // carriage return - case 0x2028: // line separator - case 0x2029: // paragraph separator - return true; - - default: - return false; - } - } - function readStringLiteralToken(text, offset, limit) { - var startOffset = offset; - var quoteCharCode = text.charCodeAt(offset); - var hasEscape = false; - offset++; - while (offset < limit && !isLineTerminator(text.charCodeAt(offset))) { - if (offset + 1 < limit && text.charCodeAt(offset) === /*\*/92) { - hasEscape = true; - - switch (text.charCodeAt(offset + 1)) { - case quoteCharCode: - case 0x005C: // \ - case 0x000A: // line feed - case 0x2028: // line separator - case 0x2029: // paragraph separator - offset += 2; - continue; - break; - - case 0x000D: // carriage return - if (offset + 2 < limit && text.charCodeAt(offset + 2) === 0x000A) { - // Skip \r\n - offset += 3; - } else { - offset += 2; - } - continue; - break; - } - } - offset++; - if (text.charCodeAt(offset - 1) === quoteCharCode) { - break; - } - } - var length = offset - startOffset; - // If we don't have a terminating quote go through the escape path. - hasEscape = hasEscape || length === 1 || text.charCodeAt(offset - 1) !== quoteCharCode; - var stringValue; - if (hasEscape) { - stringValue = eval(text.substr(startOffset, length)); - } else { - stringValue = text.substr(startOffset + 1, length - 2); - } - return { - type: tokenType.stringLiteral, - length: length, - value: stringValue - }; - } - function isWhitespace(code) { - switch (code) { - case 0x0009: // tab - case 0x000B: // vertical tab - case 0x000C: // form feed - case 0x0020: // space - case 0x00A0: // no-breaking space - case 0xFEFF: // BOM - return true; - - // There are no category Zs between 0x00A0 and 0x1680. - // - case (code < 0x1680) && code: - return false; - - // Unicode category Zs - // - case 0x1680: - case 0x180e: - case (code >= 0x2000 && code <= 0x200a) && code: - case 0x202f: - case 0x205f: - case 0x3000: - return true; - - default: - return false; - } - } - // Hand-inlined isWhitespace. - function readWhitespace(text, offset, limit) { - while (offset < limit) { - var code = text.charCodeAt(offset); - switch (code) { - case 0x0009: // tab - case 0x000B: // vertical tab - case 0x000C: // form feed - case 0x0020: // space - case 0x00A0: // no-breaking space - case 0xFEFF: // BOM - break; - - // There are no category Zs between 0x00A0 and 0x1680. - // - case (code < 0x1680) && code: - return offset; - - // Unicode category Zs - // - case 0x1680: - case 0x180e: - case (code >= 0x2000 && code <= 0x200a) && code: - case 0x202f: - case 0x205f: - case 0x3000: - break; - - default: - return offset; - } - offset++; - } - return offset; - } - function lex(result, text, offset, limit) { - while (offset < limit) { - var startOffset = offset; - var code = text.charCodeAt(offset++); - var type = undefined; - var token = undefined; - switch (code) { - case isWhitespace(code) && code: - case isLineTerminator(code) && code: - offset = readWhitespace(text, offset, limit); - token = { type: tokenType.separator, length: offset - startOffset }; - // don't include whitespace in the token stream. - continue; - break; - - case /*"*/34: - case /*'*/39: - token = readStringLiteralToken(text, offset - 1, limit); - break; - - case /*(*/40: - token = tokens.leftParentheses; - break; - - case /*)*/41: - token = tokens.rightParentheses; - break; - - case /*+*/43: - case /*-*/45: - if (offset < limit) { - var afterSign = text.charCodeAt(offset); - if (afterSign === /*.*/46) { - var signOffset = offset + 1; - if (signOffset < limit && isDecimalDigit(text.charCodeAt(signOffset))) { - token = readDecimalLiteralToken(text, startOffset, signOffset, limit); - break; - } - } else if (isDecimalDigit(afterSign)) { - token = readDecimalLiteralToken(text, startOffset, offset, limit); - break; - } - } - token = { type: tokenType.error, length: offset - startOffset, value: text.substring(startOffset, offset) }; - break; - - case /*,*/44: - token = tokens.comma; - break; - - case /*.*/46: - token = tokens.dot; - if (offset < limit && isDecimalDigit(text.charCodeAt(offset))) { - token = readDecimalLiteralToken(text, startOffset, offset, limit); - } - break; - - case /*0*/48: - var ch2 = (offset < limit ? text.charCodeAt(offset) : 0); - if (ch2 === /*x*/120 || ch2 === /*X*/88) { - var hexOffset = readHexIntegerLiteral(text, offset + 1, limit); - token = { - type: tokenType.numberLiteral, - length: hexOffset - startOffset, - value: +text.substr(startOffset, hexOffset - startOffset) - }; - } else { - token = readDecimalLiteralToken(text, startOffset, offset, limit); - } - break; - - case (code >= /*1*/49 && code <= /*9*/57) && code: - token = readDecimalLiteralToken(text, startOffset, offset, limit); - break; - - case /*:*/58: - token = tokens.colon; - break; - - case /*;*/59: - token = tokens.semicolon; - break; - - case /*[*/91: - token = tokens.leftBracket; - break; - - case /*]*/93: - token = tokens.rightBracket; - break; - - case /*{*/123: - token = tokens.leftBrace; - break; - - case /*}*/125: - token = tokens.rightBrace; - break; - - default: - if (isIdentifierStartCharacter(code, text, offset, limit)) { - token = readIdentifierToken(text, offset - 1, limit); - break; - } - token = { type: tokenType.error, length: offset - startOffset, value: text.substring(startOffset, offset) }; - break; - } - - offset += (token.length - 1); - result.push(token); - } - } - return function (text) { - var result = []; - lex(result, text, 0, text.length); - result.push(tokens.eof); - return result; - }; - })(); - lexer.tokenType = tokenType; - return lexer; - }) - }); -})(this); -(function optionsParserInit(global, undefined) { - "use strict"; - - var strings = { - get invalidOptionsRecord() { return WinJS.Resources._getWinJSString("base/invalidOptionsRecord").value; }, - get unexpectedTokenExpectedToken() { return WinJS.Resources._getWinJSString("base/unexpectedTokenExpectedToken").value; }, - get unexpectedTokenExpectedTokens() { return WinJS.Resources._getWinJSString("base/unexpectedTokenExpectedTokens").value; }, - get unexpectedTokenGeneric() { return WinJS.Resources._getWinJSString("base/unexpectedTokenGeneric").value; }, - }; - - /* - Notation is described in ECMA-262-5 (ECMAScript Language Specification, 5th edition) section 5. - - Lexical grammar is defined in ECMA-262-5, section 7. - - Lexical productions used in this grammar defined in ECMA-262-5: - - Production Section - -------------------------------- - Identifier 7.6 - NullLiteral 7.8.1 - BooleanLiteral 7.8.2 - NumberLiteral 7.8.3 - StringLiteral 7.8.4 - - Syntactic grammar for the value of the data-win-options attribute. - - OptionsLiteral: - ObjectLiteral - - ObjectLiteral: - { } - { ObjectProperties } - { ObjectProperties , } - - ObjectProperties: - ObjectProperty - ObjectProperties, ObjectProperty - - ObjectProperty: - PropertyName : Value - - PropertyName: (from ECMA-262-6, 11.1.5) - StringLiteral - NumberLiteral - Identifier - - ArrayLiteral: - [ ] - [ Elision ] - [ ArrayElements ] - [ ArrayElements , ] - [ ArrayElements , Elision ] - - ArrayElements: - Value - Elision Value - ArrayElements , Value - ArrayElements , Elision Value - - Elision: - , - Elision , - - Value: - NullLiteral - NumberLiteral - BooleanLiteral - StringLiteral - ArrayLiteral - ObjectLiteral - IdentifierExpression - ObjectQueryExpression - - AccessExpression: - [ Value ] - . Identifier - - AccessExpressions: - AccessExpression - AccessExpressions AccessExpression - - IdentifierExpression: - Identifier - Identifier AccessExpressions - - ObjectQueryExpression: - Identifier ( StringLiteral ) - Identifier ( StringLiteral ) AccessExpressions - - - NOTE: We have factored the above grammar to allow the infrastructure to be used - by the BindingInterpreter as well. The BaseInterpreter does NOT provide an - implementation of _evaluateValue(), this is expected to be provided by the - derived class since right now the two have different grammars for Value - - AccessExpression: - [ Value ] - . Identifier - - AccessExpressions: - AccessExpression - AccessExpressions AccessExpression - - Identifier: - Identifier (from ECMA-262-6, 7.6) - - IdentifierExpression: - Identifier - Identifier AccessExpressions - - Value: - *** Provided by concrete interpreter *** - -*/ - - function illegal() { - throw "Illegal"; - } - - var imports = WinJS.Namespace.defineWithParent(null, null, { - lexer: WinJS.Namespace._lazy("WinJS.UI._optionsLexer"), - tokenType: WinJS.Namespace._lazy("WinJS.UI._optionsLexer.tokenType"), - }); - - var requireSupportedForProcessing = WinJS.Utilities.requireSupportedForProcessing; - - function tokenTypeName(type) { - var keys = Object.keys(imports.tokenType); - for (var i = 0, len = keys.length; i < len; i++) { - if (type === imports.tokenType[keys[i]]) { - return keys[i]; - } - } - return ""; - } - - var local = WinJS.Namespace.defineWithParent(null, null, { - - BaseInterpreter: WinJS.Namespace._lazy(function () { - return WinJS.Class.define(null, { - _error: function (message) { - throw new WinJS.ErrorFromName("WinJS.UI.ParseError", message); - }, - _currentOffset: function () { - var l = this._tokens.length; - var p = this._pos; - var offset = 0; - for (var i = 0; i < p; i++) { - offset += this._tokens[i].length; - } - return offset; - }, - _evaluateAccessExpression: function (value) { - switch (this._current.type) { - case imports.tokenType.dot: - this._read(); - switch (this._current.type) { - case imports.tokenType.identifier: - case this._current.keyword && this._current.type: - var id = this._current.value; - this._read(); - return value[id]; - - default: - this._unexpectedToken(imports.tokenType.identifier, imports.tokenType.reservedWord); - break; - } - return; - - case imports.tokenType.leftBracket: - this._read(); - var index = this._evaluateValue(); - this._read(imports.tokenType.rightBracket); - return value[index]; - - // default: is unreachable because all the callers are conditional on - // the next token being either a . or { - // - } - }, - _evaluateAccessExpressions: function (value) { - while (true) { - switch (this._current.type) { - case imports.tokenType.dot: - case imports.tokenType.leftBracket: - value = this._evaluateAccessExpression(value); - break; - - default: - return value; - } - } - }, - _evaluateIdentifier: function (nested, value) { - var id = this._readIdentifier(); - value = nested ? value[id] : this._context[id]; - return value; - }, - _evaluateIdentifierExpression: function () { - var value = this._evaluateIdentifier(false); - - switch (this._current.type) { - case imports.tokenType.dot: - case imports.tokenType.leftBracket: - return this._evaluateAccessExpressions(value); - default: - return value; - } - }, - _initialize: function (tokens, originalSource, context, functionContext) { - this._originalSource = originalSource; - this._tokens = tokens; - this._context = context; - this._functionContext = functionContext; - this._pos = 0; - this._current = this._tokens[0]; - }, - _read: function (expected) { - if (expected && this._current.type !== expected) { - this._unexpectedToken(expected); - } - if (this._current !== imports.tokenType.eof) { - this._current = this._tokens[++this._pos]; - } - }, - _peek: function (expected) { - if (expected && this._current.type !== expected) { - return; - } - if (this._current !== imports.tokenType.eof) { - return this._tokens[this._pos + 1]; - } - }, - _readAccessExpression: function (parts) { - switch (this._current.type) { - case imports.tokenType.dot: - this._read(); - switch (this._current.type) { - case imports.tokenType.identifier: - case this._current.keyword && this._current.type: - parts.push(this._current.value); - this._read(); - break; - - default: - this._unexpectedToken(imports.tokenType.identifier, imports.tokenType.reservedWord); - break; - } - return; - - case imports.tokenType.leftBracket: - this._read(); - parts.push(this._evaluateValue()); - this._read(imports.tokenType.rightBracket); - return; - - // default: is unreachable because all the callers are conditional on - // the next token being either a . or { - // - } - }, - _readAccessExpressions: function (parts) { - while (true) { - switch (this._current.type) { - case imports.tokenType.dot: - case imports.tokenType.leftBracket: - this._readAccessExpression(parts); - break; - - default: - return; - } - } - }, - _readIdentifier: function () { - var id = this._current.value; - this._read(imports.tokenType.identifier); - return id; - }, - _readIdentifierExpression: function () { - var parts = []; - if (this._peek(imports.tokenType.thisKeyword) && parts.length === 0) { - this._read(); - } - else { - parts.push(this._readIdentifier()); - } - - switch (this._current.type) { - case imports.tokenType.dot: - case imports.tokenType.leftBracket: - this._readAccessExpressions(parts); - break; - } - - return parts; - }, - _unexpectedToken: function (expected) { - var unexpected = (this._current.type === imports.tokenType.error ? "'" + this._current.value + "'" : tokenTypeName(this._current.type)); - if (expected) { - if (arguments.length == 1) { - expected = tokenTypeName(expected); - this._error(WinJS.Resources._formatString(strings.unexpectedTokenExpectedToken, unexpected, expected, this._currentOffset())); - } else { - var names = []; - for (var i = 0, len = arguments.length; i < len; i++) { - names.push(tokenTypeName(arguments[i])); - } - expected = names.join(", "); - this._error(WinJS.Resources._formatString(strings.unexpectedTokenExpectedTokens, unexpected, expected, this._currentOffset())); - } - } else { - this._error(WinJS.Resources._formatString(strings.unexpectedTokenGeneric, unexpected, this._currentOffset())); - } - } - }, { - supportedForProcessing: false, - }); - }), - - OptionsInterpreter: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(local.BaseInterpreter, function (tokens, originalSource, context, functionContext) { - this._initialize(tokens, originalSource, context, functionContext); - }, { - _error: function (message) { - throw new WinJS.ErrorFromName("WinJS.UI.ParseError", WinJS.Resources._formatString(strings.invalidOptionsRecord, this._originalSource, message)); - }, - _evaluateArrayLiteral: function () { - var a = []; - this._read(imports.tokenType.leftBracket); - this._readArrayElements(a); - this._read(imports.tokenType.rightBracket); - return a; - }, - _evaluateObjectLiteral: function () { - var o = {}; - this._read(imports.tokenType.leftBrace); - this._readObjectProperties(o); - this._tryReadComma(); - this._read(imports.tokenType.rightBrace); - return o; - }, - _evaluateOptionsLiteral: function () { - var value = this._evaluateValue(); - if (this._current.type !== imports.tokenType.eof) { - this._unexpectedToken(imports.tokenType.eof); - } - return value; - }, - _peekValue: function () { - switch (this._current.type) { - case imports.tokenType.falseLiteral: - case imports.tokenType.nullLiteral: - case imports.tokenType.stringLiteral: - case imports.tokenType.trueLiteral: - case imports.tokenType.numberLiteral: - case imports.tokenType.leftBrace: - case imports.tokenType.leftBracket: - case imports.tokenType.identifier: - return true; - default: - return false; - } - }, - _evaluateValue: function () { - switch (this._current.type) { - case imports.tokenType.falseLiteral: - case imports.tokenType.nullLiteral: - case imports.tokenType.stringLiteral: - case imports.tokenType.trueLiteral: - case imports.tokenType.numberLiteral: - var value = this._current.value; - this._read(); - return value; - - case imports.tokenType.leftBrace: - return this._evaluateObjectLiteral(); - - case imports.tokenType.leftBracket: - return this._evaluateArrayLiteral(); - - case imports.tokenType.identifier: - if (this._peek(imports.tokenType.identifier).type == imports.tokenType.leftParentheses) { - return requireSupportedForProcessing(this._evaluateObjectQueryExpression()); - } - return requireSupportedForProcessing(this._evaluateIdentifierExpression()); - - default: - this._unexpectedToken(imports.tokenType.falseLiteral, imports.tokenType.nullLiteral, imports.tokenType.stringLiteral, - imports.tokenType.trueLiteral, imports.tokenType.numberLiteral, imports.tokenType.leftBrace, imports.tokenType.leftBracket, - imports.tokenType.identifier); - break; - } - }, - _tryReadElement: function (a) { - if (this._peekValue()) { - a.push(this._evaluateValue()); - return true; - } else { - return false; - } - }, - _tryReadComma: function () { - if (this._peek(imports.tokenType.comma)) { - this._read(); - return true; - } - return false; - }, - _tryReadElision: function (a) { - var found = false; - while (this._tryReadComma()) { - a.push(undefined); - found = true; - } - return found; - }, - _readArrayElements: function (a) { - while (!this._peek(imports.tokenType.rightBracket)) { - var elision = this._tryReadElision(a); - var element = this._tryReadElement(a); - var comma = this._peek(imports.tokenType.comma); - if (element && comma) { - // if we had a element followed by a comma, eat the comma and try to read the next element - this._read(); - } else if (element || elision) { - // if we had a element without a trailing comma or if all we had were commas we're done - break; - } else { - // if we didn't have a element or elision then we are done and in error - this._unexpectedToken(imports.tokenType.falseLiteral, imports.tokenType.nullLiteral, imports.tokenType.stringLiteral, - imports.tokenType.trueLiteral, imports.tokenType.numberLiteral, imports.tokenType.leftBrace, imports.tokenType.leftBracket, - imports.tokenType.identifier); - break; - } - } - }, - _readObjectProperties: function (o) { - while (!this._peek(imports.tokenType.rightBrace)) { - var property = this._tryReadObjectProperty(o); - var comma = this._peek(imports.tokenType.comma); - if (property && comma) { - // if we had a property followed by a comma, eat the comma and try to read the next property - this._read(); - } else if (property) { - // if we had a property without a trailing comma we're done - break; - } else { - // if we didn't have a property then we are done and in error - this._unexpectedToken(imports.tokenType.numberLiteral, imports.tokenType.stringLiteral, imports.tokenType.identifier); - break; - } - } - }, - _tryReadObjectProperty: function (o) { - switch (this._current.type) { - case imports.tokenType.numberLiteral: - case imports.tokenType.stringLiteral: - case imports.tokenType.identifier: - case this._current.keyword && this._current.type: - var propertyName = this._current.value; - this._read(); - this._read(imports.tokenType.colon); - o[propertyName] = this._evaluateValue(); - return true; - - default: - return false; - } - }, - _failReadObjectProperty: function () { - this._unexpectedToken(imports.tokenType.numberLiteral, imports.tokenType.stringLiteral, imports.tokenType.identifier, imports.tokenType.reservedWord); - }, - _evaluateObjectQueryExpression: function () { - var functionName = this._current.value; - this._read(imports.tokenType.identifier); - this._read(imports.tokenType.leftParentheses); - var queryExpression = this._current.value; - this._read(imports.tokenType.stringLiteral); - this._read(imports.tokenType.rightParentheses); - - var value = requireSupportedForProcessing(this._functionContext[functionName])(queryExpression); - switch (this._current.type) { - case imports.tokenType.dot: - case imports.tokenType.leftBracket: - return this._evaluateAccessExpressions(value); - - default: - return value; - } - }, - run: function () { - return this._evaluateOptionsLiteral(); - } - }, { - supportedForProcessing: false, - }); - }), - - OptionsParser: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(local.OptionsInterpreter, function (tokens, originalSource) { - this._initialize(tokens, originalSource); - }, { - // When parsing it is illegal to get to any of these "evaluate" RHS productions because - // we will always instead go to the "read" version - // - _evaluateAccessExpression: illegal, - _evaluateAccessExpressions: illegal, - _evaluateIdentifier: illegal, - _evaluateIdentifierExpression: illegal, - _evaluateObjectQueryExpression: illegal, - - _evaluateValue: function () { - switch (this._current.type) { - case imports.tokenType.falseLiteral: - case imports.tokenType.nullLiteral: - case imports.tokenType.stringLiteral: - case imports.tokenType.trueLiteral: - case imports.tokenType.numberLiteral: - var value = this._current.value; - this._read(); - return value; - - case imports.tokenType.leftBrace: - return this._evaluateObjectLiteral(); - - case imports.tokenType.leftBracket: - return this._evaluateArrayLiteral(); - - case imports.tokenType.identifier: - if (this._peek(imports.tokenType.identifier).type == imports.tokenType.leftParentheses) { - return this._readObjectQueryExpression(); - } - return this._readIdentifierExpression(); - - default: - this._unexpectedToken(imports.tokenType.falseLiteral, imports.tokenType.nullLiteral, imports.tokenType.stringLiteral, - imports.tokenType.trueLiteral, imports.tokenType.numberLiteral, imports.tokenType.leftBrace, imports.tokenType.leftBracket, - imports.tokenType.identifier); - break; - } - }, - - _readIdentifierExpression: function () { - var parts = local.BaseInterpreter.prototype._readIdentifierExpression.call(this); - return new IdentifierExpression(parts); - }, - _readObjectQueryExpression: function () { - var functionName = this._current.value; - this._read(imports.tokenType.identifier); - this._read(imports.tokenType.leftParentheses); - var queryExpressionLiteral = this._current.value; - this._read(imports.tokenType.stringLiteral); - this._read(imports.tokenType.rightParentheses); - - var call = new CallExpression(functionName, queryExpressionLiteral); - switch (this._current.type) { - case imports.tokenType.dot: - case imports.tokenType.leftBracket: - var parts = [call]; - this._readAccessExpressions(parts); - return new IdentifierExpression(parts); - - default: - return call; - } - }, - }, { - supportedForProcessing: false, - }); - }) - - }); - - var parser = function (text, context, functionContext) { - var tokens = imports.lexer(text); - var interpreter = new local.OptionsInterpreter(tokens, text, context || {}, functionContext || {}); - return interpreter.run(); - }; - Object.defineProperty(parser, "_BaseInterpreter", { get: function () { return local.BaseInterpreter; } }); - - var parser2 = function (text) { - var tokens = imports.lexer(text); - var parser = new local.OptionsParser(tokens, text); - return parser.run(); - }; - - // Consumers of parser2 need to be able to see the AST for RHS expression in order to emit - // code representing these portions of the options record - // - var CallExpression = WinJS.Class.define(function (target, arg0Value) { - this.target = target; - this.arg0Value = arg0Value; - }); - CallExpression.supportedForProcessing = false; - - var IdentifierExpression = WinJS.Class.define(function (parts) { - this.parts = parts; - }); - IdentifierExpression.supportedForProcessing = false; - - WinJS.Namespace.define("WinJS.UI", { - - // This is the mis-named interpreter version of the options record processor. - // - optionsParser: parser, - - // This is the actual parser version of the options record processor. - // - _optionsParser: parser2, - _CallExpression: CallExpression, - _IdentifierExpression: IdentifierExpression, - - }); - -})(this); - - -(function tabManagerInit(global, WinJS, undefined) { - "use strict"; - - // not supported in WebWorker - if (!global.document) { - return; - } - - - function fireEvent(element, name, forward) { - var event = document.createEvent('UIEvent'); - event.initUIEvent(name, false, false, window, forward ? 1 : 0); - element.dispatchEvent(event); - } - - function onBeforeActivate(e, element, prefixWillHaveFocus) { - var hasFocus = element.contains(document.activeElement); - fireEvent(element, hasFocus ? "onTabExit" : "onTabEnter", (!hasFocus && prefixWillHaveFocus) || (hasFocus && !prefixWillHaveFocus)); - e.stopPropagation(); - e.preventDefault(); - } - - function prefixBeforeActivateHandler(e) { - return onBeforeActivate(e, e.srcElement.nextSibling, true); - } - - function postfixBeforeActivateHandler(e) { - return onBeforeActivate(e, e.srcElement.previousSibling, false); - } - - function TabHelperObject(element, tabIndex) { - function createCatcher(beforeActivateHandler) { - var fragment = document.createElement("DIV"); - fragment.tabIndex = (tabIndex ? tabIndex : 0); - fragment.addEventListener("beforeactivate", beforeActivateHandler); - fragment.setAttribute("aria-hidden", true); - return fragment; - }; - - var parent = element.parentNode; - - // Insert prefix focus catcher - var catcherBegin = createCatcher(prefixBeforeActivateHandler); - parent.insertBefore(catcherBegin, element); - - // Insert postfix focus catcher - var catcherEnd = createCatcher(postfixBeforeActivateHandler); - parent.insertBefore(catcherEnd, element.nextSibling); - - var refCount = 1; - this.addRef = function () { - refCount++; - }; - this.release = function () { - if (--refCount === 0) { - if (catcherBegin.parentElement) { - parent.removeChild(catcherBegin); - } - if (catcherEnd.parentElement) { - parent.removeChild(catcherEnd); - } - } - return refCount; - }; - this.updateTabIndex = function (tabIndex) { - catcherBegin.tabIndex = tabIndex; - catcherEnd.tabIndex = tabIndex; - } - } - - WinJS.Namespace.define("WinJS.UI.TrackTabBehavior", { - attach: function (element, tabIndex) { - /// - if (!element["win-trackTabHelperObject"]) { - element["win-trackTabHelperObject"] = new TabHelperObject(element, tabIndex); - } else { - element["win-trackTabHelperObject"].addRef(); - } - - return element["win-trackTabHelperObject"]; - }, - - detach: function (element) { - /// - if (!element["win-trackTabHelperObject"].release()) { - delete element["win-trackTabHelperObject"]; - } - } - }); - - WinJS.Namespace.define("WinJS.UI", { - TabContainer: WinJS.Class.define(function TabContainer_ctor(element, options) { - /// - /// - /// Constructs the TabContainer. - /// - /// - /// The DOM element to be associated with the TabContainer. - /// - /// - /// The set of options to be applied initially to the TabContainer. - /// - /// - /// A constructed TabContainer. - /// - /// - // TabContainer uses 2 TrackTabBehavior for its implementation: one for itself, another one for the active element. - // When onTabEnter is caught on TabContainer, it directly set focus on the active element. - // When onTabExit is caught on the active element (_tabExitHandler), it first prevents focus from being set on any element, - // effectively letting the focus skip any remaining items in the TabContainer. Then, when onTabExit is caught on - // TabContainer, it turns back on the possibility to receive focus on child elements. - this._element = element; - this._tabIndex = 0; - var that = this; - this._tabExitHandler = function () { - that._canFocus(false); - }; - - element.addEventListener("onTabEnter", function () { - if (that.childFocus) { - that.childFocus.focus(); - } else { - that._canFocus(false); - } - }); - - element.addEventListener("onTabExit", function () { - that._canFocus(true); - }); - - this._elementTabHelper = WinJS.UI.TrackTabBehavior.attach(element, this._tabIndex); - }, { - - // Public members - - /// - /// - /// Disposes the Tab Container. - /// - /// - dispose: function () { - WinJS.UI.TrackTabBehavior.detach(this._element, this._tabIndex); - }, - - /// - /// Gets or sets the child element that has focus. - /// - childFocus: { - set: function (e) { - if (e != this._focusElement) { - if (this._focusElement) { - WinJS.UI.TrackTabBehavior.detach(this._focusElement); - this._childTabHelper = null; - this._focusElement.removeEventListener("onTabExit", this._tabExitHandler); - } - - if (e && e.parentNode) { - this._focusElement = e; - this._childTabHelper = WinJS.UI.TrackTabBehavior.attach(e, this._tabIndex); - this._focusElement.addEventListener("onTabExit", this._tabExitHandler); - } else { - //#DBG _ASSERT(!!e.parentNode); - this._focusElement = null; - } - } - }, - get: function () { - return this._focusElement; - } - }, - - /// - /// Gets or sets the tab order of the control within its container. - /// - tabIndex: { - set: function (tabIndex) { - this._tabIndex = tabIndex; - this._elementTabHelper.updateTabIndex(tabIndex); - if (this._childTabHelper) { - this._childTabHelper.updateTabIndex(tabIndex); - } - }, - - get: function () { - return this._tabIndex; - } - }, - - // Private members - - _element: null, - _skipper: function (e) { - e.stopPropagation(); - e.preventDefault(); - }, - _canFocus: function (canfocus) { - if (canfocus) { - this._element.removeEventListener("beforeactivate", this._skipper); - } else { - this._element.addEventListener("beforeactivate", this._skipper); - } - }, - - _focusElement: null - - }, { // Static Members - supportedForProcessing: false, - }) - }); -})(this, WinJS); -(function transitionAnimationInit(global, WinJS, undefined) { - "use strict"; - - // not supported in WebWorker - if (!global.document) { - return; - } - - var Scheduler = WinJS.Utilities.Scheduler; - - function makeArray(elements) { - if (elements instanceof Array || elements instanceof NodeList || elements instanceof HTMLCollection) { - return elements; - } else if (elements) { - return [elements]; - } else { - return []; - } - } - - var keyframeCounter = 0; - function getUniqueKeyframeName() { - return "WinJSUIAnimation" + ++keyframeCounter; - } - function isUniqueKeyframeName(s) { - return "WinJSUIAnimation" === s.substring(0, 16); - } - - function resolveStyles(elem) { - window.getComputedStyle(elem, null).opacity; - } - - function copyWithEvaluation(iElem, elem) { - return function (obj) { - var newObj = {}; - for (var p in obj) { - var v = obj[p]; - if (typeof v === "function") { - v = v(iElem, elem); - } - newObj[p] = v; - } - if (!newObj.exactTiming) { - newObj.delay += UI._libraryDelay; - } - return newObj; - }; - } - - var activeActions = [ ]; - - var reason_ended = 0; - var reason_interrupted = 1; - var reason_canceled = 2; - - function stopExistingAction(id, prop) { - var key = id + "|" + prop; - var finish = activeActions[key]; - if (finish) { - finish(reason_interrupted); - } - } - - function registerAction(id, prop, finish) { - activeActions[id + "|" + prop] = finish; - } - - function unregisterAction(id, prop) { - delete activeActions[id + "|" + prop]; - } - - var StyleCache = WinJS.Class.define( - // Constructor - function StyleCache_ctor(id, desc, style) { - this.cref = 0; - this.id = id; - this.desc = desc; - this.removed = {}; - this.prevStyles = desc.props.map(function (p) { return style[p[0]]; }); - this.prevNames = this.names = style[desc.nameProp]; - desc.styleCaches[id] = this; - }, { - // Members - destroy: function StyleCache_destroy(style, skipStylesReset) { - var desc = this.desc; - delete desc.styleCaches[this.id]; - if (!skipStylesReset) { - if (this.prevNames === "" && - this.prevStyles.every(function (s) { return s === ""; })) { - style[desc.shorthandProp] = ""; - } else { - desc.props.forEach(function (p, i) { - style[p[0]] = this.prevStyles[i]; - }, this); - style[desc.nameProp] = this.prevNames; - } - } - }, - removeName: function StyleCache_removeName(style, name, elem, skipStylesReset) { - var nameValue = this.names; - var names = nameValue.split(", "); - var index = names.lastIndexOf(name); - if (index >= 0) { - names.splice(index, 1); - this.names = nameValue = names.join(", "); - if (nameValue === "" && this.desc.isTransition) { - nameValue = "none"; - } - } - if (--this.cref) { - style[this.desc.nameProp] = nameValue; - if (!isUniqueKeyframeName(name)) { - this.removed[name] = true; - } - } else { - if (elem && nameValue === "none") { - style[this.desc.nameProp] = nameValue; - resolveStyles(elem); - } - this.destroy(style, skipStylesReset); - } - } - }); - - function setTemporaryStyles(elem, id, style, actions, desc) { - var styleCache = desc.styleCaches[id] || - new StyleCache(id, desc, style); - styleCache.cref += actions.length; - - actions.forEach(function(action) { - stopExistingAction(id, action.property); - }); - - if (desc.isTransition || - actions.some(function(action) { - return styleCache.removed[action[desc.nameField]]; - })) { - resolveStyles(elem); - styleCache.removed = { }; - } - - var newShorthand = actions.map(function(action) { - return action[desc.nameField] + " " + - desc.props.map(function(p) { - return (p[1] ? action[p[1]] : "") + p[2]; - }).join(" "); - }).join(", "); - - var newNames = actions.map(function(action) { - return action[desc.nameField]; - }).join(", "); - if (styleCache.names !== "") { - newShorthand = styleCache.names + ", " + newShorthand; - newNames = styleCache.names + ", " + newNames; - } - - style[desc.shorthandProp] = newShorthand; - styleCache.names = newNames; - return styleCache; - } - - var elementTransitionProperties = { - shorthandProp: "transition", - nameProp: "transition-property", - nameField: "property", - props: [ - ["transition-duration", "duration", "ms"], - ["transition-timing-function", "timing", ""], - ["transition-delay", "delay", "ms"] - ], - isTransition: true, - styleCaches: [] - }; - - function completePromise(c, synchronous) { - if (synchronous) { - c(); - } else { - Scheduler.schedule(function _Animation_completeAnimationPromise() { - c(); - }, Scheduler.Priority.normal, null, "WinJS.UI._Animation._completeAnimationPromise"); - } - } - - var uniformizeStyle; - function executeElementTransition(elem, index, transitions, promises, animate) { - if (transitions.length > 0) { - var style = elem.style; - var id = elem.uniqueID; - if (!uniformizeStyle) { - uniformizeStyle = document.createElement("DIV").style; - } - transitions = transitions.map(copyWithEvaluation(index, elem)); - transitions.forEach(function (transition) { - if (transition.hasOwnProperty("from")) { - style[transition.property] = transition.from; - } - uniformizeStyle[transition.property] = transition.to; - transition.to = uniformizeStyle[transition.property]; - }); - - if (animate) { - var styleCache = setTemporaryStyles(elem, id, style, transitions, elementTransitionProperties); - var listener = elem.disabled ? document : elem; - - transitions.forEach(function (transition) { - var finish; - promises.push(new WinJS.Promise(function (c, e, p) { - finish = function (reason) { - if (onTransitionEnd) { - listener.removeEventListener("transitionend", onTransitionEnd, false); - unregisterAction(id, transition.property); - styleCache.removeName(style, transition.property, reason ? elem : null, transition.skipStylesReset); - clearTimeout(timeoutId); - onTransitionEnd = null; - } - completePromise(c, reason === reason_canceled); - }; - - var onTransitionEnd = function (event) { - if (event.srcElement === elem && event.propertyName === transition.property) { - finish(); - } - }; - - registerAction(id, transition.property, finish); - listener.addEventListener("transitionend", onTransitionEnd, false); - - var padding = 0; - if (style[transition.property] !== transition.to) { - style[transition.property] = transition.to; - padding = 50; - } - var timeoutId = setTimeout(function() { - timeoutId = setTimeout(finish, transition.delay + transition.duration); - }, padding); - }, function () { finish(reason_canceled); })); - }); - } else { - transitions.forEach(function (transition) { - style[transition.property] = transition.to; - }); - } - } - } - - var elementAnimationProperties = { - shorthandProp: "animation", - nameProp: "animation-name", - nameField: "keyframe", - props: [ - ["animation-duration", "duration", "ms"], - ["animation-timing-function", "timing", ""], - ["animation-delay", "delay", "ms"], - ["animation-iteration-count", "", "1"], - ["animation-direction", "", "normal"], - ["animation-fill-mode", "", "both"] - ], - isTransition: false, - styleCaches: [] - }; - - function executeElementAnimation(elem, index, anims, promises, animate) { - if (animate && anims.length > 0) { - var style = elem.style; - var id = elem.uniqueID; - anims = anims.map(copyWithEvaluation(index, elem)); - var styleElem; - var listener = elem.disabled ? document : elem; - anims.forEach(function (anim) { - if (!anim.keyframe) { - if (!styleElem) { - styleElem = document.createElement("STYLE"); - document.documentElement.appendChild(styleElem); - } - anim.keyframe = getUniqueKeyframeName(); - var kf = "@keyframes " + anim.keyframe + " { from {" + anim.property + ":" + anim.from + ";} to {" + anim.property + ":" + anim.to + ";}}"; - styleElem.sheet.insertRule(kf, 0); - } - }); - var styleCache = setTemporaryStyles(elem, id, style, anims, elementAnimationProperties); - anims.forEach(function (anim) { - var finish; - promises.push(new WinJS.Promise(function (c, e, p) { - - finish = function (reason) { - if (onAnimationEnd) { - listener.removeEventListener("animationend", onAnimationEnd, false); - unregisterAction(id, anim.property); - styleCache.removeName(style, anim.keyframe); - clearTimeout(timeoutId); - onAnimationEnd = null; - } - completePromise(c, reason === reason_canceled); - }; - - var onAnimationEnd = function (event) { - if (event.srcElement === elem && event.animationName === anim.keyframe) { - finish(); - } - }; - - registerAction(id, anim.property, finish); - var timeoutId = setTimeout(function() { - timeoutId = setTimeout(finish, anim.delay + anim.duration); - }, 50); - listener.addEventListener("animationend", onAnimationEnd, false); - }, function() { finish(reason_canceled); })); - }); - if (styleElem) { - setTimeout(function () { - var parentElement = styleElem.parentElement; - if (parentElement) { - parentElement.removeChild(styleElem); - } - }, 50); - } - } - } - - var enableCount = 0; - var animationSettings; - function initAnimations() { - if (!animationSettings) { - if (WinJS.Utilities.hasWinRT) { - animationSettings = new Windows.UI.ViewManagement.UISettings(); - } - else { - animationSettings = { animationsEnabled: true }; - } - } - } - - function isAnimationEnabled() { - /// - /// - /// Determines whether the WinJS Animation Library will perform animations. - /// - /// - /// true if WinJS animations will be performed. - /// false if WinJS animations are suppressed. - /// - /// - initAnimations(); - return enableCount + animationSettings.animationsEnabled > 0; - } - - function applyAction(element, action, execAction) { - try { - var animate = WinJS.UI.isAnimationEnabled(); - var elems = makeArray(element); - var actions = makeArray(action); - - var promises = []; - - for (var i = 0; i < elems.length; i++) { - if (elems[i] instanceof Array) { - for (var j = 0; j < elems[i].length; j++) { - execAction(elems[i][j], i, actions, promises, animate); - } - } else { - execAction(elems[i], i, actions, promises, animate); - } - } - - if (promises.length) { - return WinJS.Promise.join(promises); - } else { - return Scheduler.schedulePromiseNormal(null, "WinJS.UI._Animation._completeActionPromise").then(null, function (error) { - // Convert a cancelation to the success path - }); - } - } catch (e) { - return WinJS.Promise.wrapError(e); - } - } - - var UI = WinJS.Namespace.define("WinJS.UI", { - disableAnimations: function () { - /// - /// - /// Disables animations in the WinJS Animation Library - /// by decrementing the animation enable count. - /// - /// - enableCount--; - }, - - enableAnimations: function () { - /// - /// - /// Enables animations in the WinJS Animation Library - /// by incrementing the animation enable count. - /// - /// - enableCount++; - }, - - isAnimationEnabled: isAnimationEnabled, - - _libraryDelay: 0, - - executeAnimation: function (element, animation) { - /// - /// - /// Perform a CSS animation that can coexist with other - /// Animation Library animations. Applications are not expected - /// to call this function directly; they should prefer to use - /// the high-level animations in the Animation Library. - /// - /// - /// Single element or collection of elements on which - /// to perform a CSS animation. - /// - /// - /// Single animation description or array of animation descriptions. - /// - /// - /// Promise object that completes when the CSS animation is complete. - /// - /// - return applyAction(element, animation, executeElementAnimation); - }, - - executeTransition: function (element, transition) { - /// - /// - /// Perform a CSS transition that can coexist with other - /// Animation Library animations. Applications are not expected - /// to call this function directly; they should prefer to use - /// the high-level animations in the Animation Library. - /// - /// - /// Single element or collection of elements on which - /// to perform a CSS transition. - /// - /// - /// Single transition description or array of transition descriptions. - /// - /// - /// Promise object that completes when the CSS transition is complete. - /// - /// - return applyAction(element, transition, executeElementTransition); - } - }); -})(this, WinJS); - -(function utilitiesInit(global, undefined) { - "use strict"; - - var markSupportedForProcessing = WinJS.Utilities.markSupportedForProcessing; - - WinJS.Namespace.define("WinJS.UI", { - eventHandler: function (handler) { - /// - /// - /// Marks a event handler function as being compatible with declarative processing. - /// - /// - /// The handler to be marked as compatible with declarative processing. - /// - /// - /// The input handler. - /// - /// - return markSupportedForProcessing(handler); - }, - /// - /// Orientation options for a control's property - /// - Orientation: { - /// - /// Horizontal - /// - horizontal: "horizontal", - /// - /// Vertical - /// - vertical: "vertical" - } - }); - - - WinJS.Namespace.define("WinJS.Utilities", { - - _clamp: function (value, lowerBound, upperBound, defaultValue) { - var n = Math.max(lowerBound, Math.min(upperBound, +value)); - return n === 0 ? 0 : n || Math.max(lowerBound, Math.min(upperBound, defaultValue)); - }, - - _deprecated: function (message) { - console.warn(message); - } - - }); - - WinJS.Namespace.define("WinJS.Utilities", { - - // Take a renderer which may be a function (signature: (data) => element) or a WinJS.Binding.Template - // and return a function with a unified synchronous contract which is: - // - // (data, container) => element - // - // Where: - // - // 1) if you pass container the content will be rendered into the container and the - // container will be returned. - // - // 2) if you don't pass a container the content will be rendered and returned. - // - _syncRenderer: function (renderer, tagName) { - tagName = tagName || "div"; - if (typeof renderer === "function") { - return function (data, container) { - if (container) { - container.appendChild(renderer(data)); - return container; - } else { - return renderer(data); - } - }; - } - - var template; - if (typeof renderer.render === "function") { - template = renderer; - } else if (renderer.winControl && typeof renderer.winControl.render === "function") { - template = renderer.winControl; - } - - return function (data, container) { - var host = container || document.createElement(tagName); - template.render(data, host); - if (container) { - return container; - } else { - // The expectation is that the creation of the DOM elements happens synchronously - // and as such we steal the first child and make it the root element. - // - var element = host.firstElementChild; - - // Because we have changed the "root" we may need to move the dispose method - // created by the template to the child and do a little switcheroo on dispose. - // - if (element && host.dispose) { - var prev = element.dispose; - element.dispose = function () { - element.dispose = prev; - host.appendChild(element); - host.dispose(); - }; - } - return element; - } - }; - }, - - - _getLowestTabIndexInList: function Utilities_getLowestTabIndexInList(elements) { - // Returns the lowest positive tabIndex in a list of elements. - // Returns 0 if there are no positive tabIndices. - var lowestTabIndex = 0; - var elmTabIndex; - for (var i = 0; i < elements.length; i++) { - elmTabIndex = parseInt(elements[i].getAttribute("tabIndex"), 10); - if ((0 < elmTabIndex) - && ((elmTabIndex < lowestTabIndex) || !lowestTabIndex)) { - lowestTabIndex = elmTabIndex; - } - } - - return lowestTabIndex; - }, - - _getHighestTabIndexInList: function Utilities_getHighestTabIndexInList(elements) { - // Returns 0 if any element is explicitly set to 0. (0 is the highest tabIndex) - // Returns the highest tabIndex in the list of elements. - // Returns 0 if there are no positive tabIndices. - var highestTabIndex = 0; - var elmTabIndex; - for (var i = 0; i < elements.length; i++) { - elmTabIndex = parseInt(elements[i].getAttribute("tabIndex"), 10); - if (elmTabIndex === 0) { - return elmTabIndex; - } else if (highestTabIndex < elmTabIndex) { - highestTabIndex = elmTabIndex; - } - } - - return highestTabIndex; - }, - - _trySetActive: function Utilities_trySetActive(elem) { - return this._tryFocus(elem, true); - }, - - _tryFocus: function Utilities_tryFocus(elem, useSetActive) { - var previousActiveElement = document.activeElement; - - if (elem === previousActiveElement) { - return true; - } - - // IE allows focus to go to elements that it shouldn't sometimes. - // For reference: http://www.w3.org/html/wg/drafts/html/master/single-page.html#specially-focusable - // Workaround for majority of cases: - var simpleLogicForValidTabStop = - (elem.tabIndex >= 0) && - ((elem.nodeName === "A" && elem.href) || - (elem.nodeName === "LINK" && elem.href) || - (elem.nodeName === "BUTTON") || - (elem.nodeName === "INPUT" && elem.type !== "hidden") || - (elem.nodeName === "SELECT") || - (elem.nodeName === "TEXTAREA") || - (elem.nodeName === "MENUITEM") || - (elem.nodeName === "TH" && elem.sorted) || - (elem.draggable) || - (elem.getAttribute("tabindex") !== null)); - if (!simpleLogicForValidTabStop) { - return false; - } - - if (useSetActive) { - try { - elem.setActive(); - } catch (e) { - } - } else { - elem.focus(); - } - - if (previousActiveElement !== document.activeElement) { - return true; - } - return false; - }, - - _setActiveFirstFocusableElement: function Utilities_setActiveFirstFocusableElement(rootEl) { - return this._focusFirstFocusableElement(rootEl, true); - }, - - _focusFirstFocusableElement: function Utilities_focusFirstFocusableElement(rootEl, useSetActive) { - var _elms = rootEl.getElementsByTagName("*"); - - // Get the tabIndex set to the firstDiv (which is the lowest) - var _lowestTabIndex = this._getLowestTabIndexInList(_elms); - var _nextLowestTabIndex = 0; - - // If there are positive tabIndices, set focus to the element with the lowest tabIndex. - // Keep trying with the next lowest tabIndex until all tabIndices have been exhausted. - // Otherwise set focus to the first focusable element in DOM order. - while (_lowestTabIndex) { - for (var i = 0; i < _elms.length; i++) { - if (_elms[i].tabIndex === _lowestTabIndex) { - if (this._tryFocus(_elms[i], useSetActive)) { - return true; - } - } else if ((_lowestTabIndex < _elms[i].tabIndex) - && ((_elms[i].tabIndex < _nextLowestTabIndex) || (_nextLowestTabIndex === 0))) { - // Here if _lowestTabIndex < _elms[i].tabIndex < _nextLowestTabIndex - _nextLowestTabIndex = _elms[i].tabIndex; - } - } - - // We weren't able to set focus to anything at that tabIndex - // If we found a higher valid tabIndex, try that now - _lowestTabIndex = _nextLowestTabIndex; - _nextLowestTabIndex = 0; - } - - // Wasn't able to set focus to anything with a positive tabIndex, try everything now. - // This is where things with tabIndex of 0 will be tried. - for (i = 0; i < _elms.length; i++) { - if (this._tryFocus(_elms[i], useSetActive)) { - return true; - } - } - - return false; - }, - - _setActiveLastFocusableElement: function Utilities_setActiveLastFocusableElement(rootEl) { - return this._focusLastFocusableElement(rootEl, true); - }, - - _focusLastFocusableElement: function Utilities_focusLastFocusableElement(rootEl, useSetActive) { - var _elms = rootEl.getElementsByTagName("*"); - // Get the tabIndex set to the finalDiv (which is the highest) - var _highestTabIndex = this._getHighestTabIndexInList(_elms); - var _nextHighestTabIndex = 0; - - var previousActiveElement = document.activeElement; - - // Try all tabIndex 0 first. After this conditional the _highestTabIndex - // should be equal to the highest positive tabIndex. - if (_highestTabIndex === 0) { - for (var i = _elms.length - 1; i >= 0; i--) { - if (_elms[i].tabIndex === _highestTabIndex) { - if (this._tryFocus(_elms[i], useSetActive)) { - return true; - } - } else if (_nextHighestTabIndex < _elms[i].tabIndex) { - _nextHighestTabIndex = _elms[i].tabIndex; - } - } - - _highestTabIndex = _nextHighestTabIndex; - _nextHighestTabIndex = 0; - } - - // If there are positive tabIndices, set focus to the element with the highest tabIndex. - // Keep trying with the next highest tabIndex until all tabIndices have been exhausted. - // Otherwise set focus to the last focusable element in DOM order. - while (_highestTabIndex) { - for (i = _elms.length - 1; i >= 0; i--) { - if (_elms[i].tabIndex === _highestTabIndex) { - if (this._tryFocus(_elms[i], useSetActive)) { - return true; - } - } else if ((_nextHighestTabIndex < _elms[i].tabIndex) && (_elms[i].tabIndex < _highestTabIndex)) { - // Here if _nextHighestTabIndex < _elms[i].tabIndex < _highestTabIndex - _nextHighestTabIndex = _elms[i].tabIndex; - } - } - - // We weren't able to set focus to anything at that tabIndex - // If we found a lower valid tabIndex, try that now - _highestTabIndex = _nextHighestTabIndex; - _nextHighestTabIndex = 0; - } - - // Wasn't able to set focus to anything with a tabIndex, try everything now - for (i = _elms.length - 2; i > 0; i--) { - if (this._tryFocus(_elms[i], useSetActive)) { - return true; - } - } - - return false; - }, - - }); - -}(this)); - -(function applicationInit(global, WinJS, undefined) { - "use strict"; - - global.Debug && (global.Debug.setNonUserCodeExceptions = true); - - var Scheduler = WinJS.Utilities.Scheduler; - - var checkpointET = "checkpoint", - unloadET = "unload", - activatedET = "activated", - loadedET = "loaded", - readyET = "ready", - errorET = "error", - settingsET = "settings"; - - var outstandingPromiseErrors; - var eventQueue = []; - var eventQueueJob = null; - var eventQueuedSignal = null; - var running = false; - var registered = false; - // check for WinRT & document, which means we will disabled application WinRT stuff in web worker context - // - var useWinRT = WinJS.Utilities.hasWinRT && global.document; - - var ListenerType = WinJS.Class.mix(WinJS.Class.define(null, { /* empty */ }, { supportedForProcessing: false }), WinJS.Utilities.eventMixin); - var listeners = new ListenerType(); - var pendingDeferrals = {}; - var pendingDeferralID = 0; - - function safeSerialize(obj) { - var str; - try { - str = JSON.stringify(obj); - } - catch (err) { - // primitives, undefined, null, etc, all get serialized fine. In the - // case that stringify fails (typically due to circular graphs) we - // just show "[object]". While we may be able to tighten the condition - // for the exception, we never way this serialize to fail. - // - // Note: we make this be a JSON string, so that consumers of the log - // can always call JSON.parse. - str = JSON.stringify("[object]"); - } - return str; - } - - var terminateAppHandler = function (data, e) { - // This is the unhandled exception handler in WinJS. This handler is invoked whenever a promise - // has an exception occur that is not handled (via an error handler passed to then() or a call to done()). - // - // To see the original exception stack, look at data.stack. - // For more information on debugging and exception handling go to http://go.microsoft.com/fwlink/p/?LinkId=253583. - debugger; - MSApp.terminateApp(data); - }; - - function captureDeferral(obj) { - var id = "def" + (pendingDeferralID++); - return { deferral: pendingDeferrals[id] = obj.getDeferral(), id: id } - } - function completeDeferral(deferral, deferralID) { - // If we have a deferralID we our table to find the - // deferral. Since we remove it on completion, this - // ensures that we never double notify a deferral - // in the case of a user call "Application.stop" in - // the middle of processing an event - // - if (deferralID) { - deferral = pendingDeferrals[deferralID]; - delete pendingDeferrals[deferralID]; - } - if (deferral) { - deferral.complete(); - } - } - function cleanupAllPendingDeferrals() { - if (pendingDeferrals) { - Object.keys(pendingDeferrals).forEach(function (k) { - pendingDeferrals[k].complete(); - }); - pendingDeferrals = {}; - } - } - - function dispatchEvent(eventRecord) { - msWriteProfilerMark("WinJS.Application:Event_" + eventRecord.type + ",StartTM"); - - var waitForPromise = WinJS.Promise.as(); - eventRecord.setPromise = function (promise) { - /// - /// - /// Used to inform the application object that asynchronous work is being performed, and that this - /// event handler should not be considered complete until the promise completes. - /// - /// - /// The promise to wait for. - /// - /// - waitForPromise = waitForPromise.then(function () { return promise; }); - }; - eventRecord.detail = eventRecord.detail || {}; - if (typeof (eventRecord.detail) === "object") { - eventRecord.detail.setPromise = eventRecord.setPromise; - } - - try { - if (listeners._listeners) { - var handled = false; - l = listeners._listeners[eventRecord.type]; - if (l) { - l.forEach(function dispatchOne(e) { - handled = e.listener(eventRecord) || handled; - }); - } - } - - // Fire built in listeners last, for checkpoint this is important - // as it lets our built in serialization see any mutations to - // app.sessionState - // - var l = builtInListeners[eventRecord.type]; - if (l) { - l.forEach(function dispatchOne(e) { e(eventRecord, handled); }); - } - } - catch (err) { - queueEvent({ type: errorET, detail: err }); - } - - - function cleanup(r) { - msWriteProfilerMark("WinJS.Application:Event_" + eventRecord.type + ",StopTM"); - - if (eventRecord._deferral) { - completeDeferral(eventRecord._deferral, eventRecord._deferralID); - } - return r; - } - - return waitForPromise.then(cleanup, function(r) { - return WinJS.Promise.wrapError(cleanup(r)); - }); - } - - function createEventQueuedSignal() { - if (!eventQueuedSignal) { - eventQueuedSignal = new WinJS._Signal(); - eventQueuedSignal.promise.done(function () { - eventQueuedSignal = null; - }, function () { - eventQueuedSignal = null; - }); - } - return eventQueuedSignal; - } - - function drainOneEvent(queue) { - function drainError(err) { - queueEvent({ type: errorET, detail: err }); - } - - if (queue.length === 0) { - return createEventQueuedSignal().promise; - } else { - return dispatchEvent(queue.shift()).then(null, drainError); - } - } - - // Drains the event queue via the scheduler - // - function drainQueue(jobInfo) { - function drainNext() { - return drainQueue; - } - - var queue = jobInfo.job._queue; - - if (queue.length === 0 && eventQueue.length > 0) { - queue = jobInfo.job._queue = copyAndClearQueue(); - } - - jobInfo.setPromise(drainOneEvent(queue).then(drainNext, drainNext)); - } - - function startEventQueue() { - function markSync() { - sync = true; - } - - var queue = []; - var sync = true; - var promise; - - // Drain the queue as long as there are events and they complete synchronously - // - while (sync) { - if (queue.length === 0 && eventQueue.length > 0) { - queue = copyAndClearQueue(); - } - - sync = false; - promise = drainOneEvent(queue); - promise.done(markSync, markSync); - } - - // Schedule a job which will be responsible for draining events for the - // lifetime of the application. - // - eventQueueJob = Scheduler.schedule(function (jobInfo) { - function drainNext() { - return drainQueue; - } - jobInfo.setPromise(promise.then(drainNext, drainNext)); - }, Scheduler.Priority.high, null, "WinJS.Application._pumpEventQueue"); - eventQueueJob._queue = queue; - } - - function queueEvent(eventRecord) { - /// - /// - /// Queues an event to be processed by the WinJS.Application event queue. - /// - /// - /// The event object is expected to have a type property that is - /// used as the event name when dispatching on the WinJS.Application - /// event queue. The entire object is provided to event listeners - /// in the detail property of the event. - /// - /// - msWriteProfilerMark("WinJS.Application:Event_" + eventRecord.type + " queued,Info"); - eventQueue.push(eventRecord); - if (running && eventQueuedSignal) { - eventQueuedSignal.complete(drainQueue); - } - } - - function copyAndClearQueue() { - var queue = eventQueue; - eventQueue = []; - return queue; - } - - var builtInListeners = { - activated: [ - function Application_activatedHandler() { - queueEvent({ type: readyET }); - } - ], - checkpoint: [ - function Application_checkpointHandler(e) { - // comes from state.js - WinJS.Application._oncheckpoint(e); - } - ], - error: [ - function Application_errorHandler(e, handled) { - if (handled) { - return; - } - - WinJS.log && WinJS.log(safeSerialize(e), "winjs", "error"); - - if (useWinRT && WinJS.Application._terminateApp) { - var data = e.detail; - var number = data && (data.number || (data.exception && data.exception.number) || (data.error && data.error.number) || data.errorCode || 0); - var terminateData = { - description: safeSerialize(data), - // note: because of how we listen to events, we rarely get a stack - stack: data && (data.stack || (data.exception && data.exception.stack) || (data.error && data.error.stack) || null), - errorNumber: number, - number: number - }; - WinJS.Application._terminateApp(terminateData, e); - } - } - ], - }; - - // loaded == DOMContentLoaded - // activated == after WinRT Activated - // ready == after all of the above - // - function activatedHandler(e) { - var def = captureDeferral(e.activatedOperation); - WinJS.Application._loadState(e).then(function () { - queueEvent({ type: activatedET, detail: e, _deferral: def.deferral, _deferralID: def.id }); - }); - } - function suspendingHandler(e) { - var def = captureDeferral(e.suspendingOperation); - WinJS.Application.queueEvent({ type: checkpointET, _deferral: def.deferral, _deferralID: def.id }); - } - function domContentLoadedHandler(e) { - queueEvent({ type: loadedET }); - if (!useWinRT) { - var activatedArgs = { - arguments: "", - kind: "Windows.Launch", - previousExecutionState: 0 //Windows.ApplicationModel.Activation.ApplicationExecutionState.NotRunning - }; - WinJS.Application._loadState(activatedArgs).then(function () { - queueEvent({ type: activatedET, detail: activatedArgs }); - }); - } - } - function beforeUnloadHandler(e) { - cleanupAllPendingDeferrals(); - queueEvent({ type: unloadET }); - } - function errorHandler(e) { - var flattenedError = {}; - for (var k in e) { - flattenedError[k] = e[k]; - } - var data; - var handled = true; - var prev = WinJS.Application._terminateApp; - try { - WinJS.Application._terminateApp = function (d, e) { - handled = false; - data = d; - if (prev !== terminateAppHandler) { - prev(d, e); - } - } - dispatchEvent({ - type: errorET, - detail: { - error: flattenedError, - errorLine: e.lineno, - errorCharacter: e.colno, - errorUrl: e.filename, - errorMessage: e.message - } - }); - } finally { - WinJS.Application._terminateApp = prev; - } - return handled; - } - function promiseErrorHandler(e) { - // - // e.detail looks like: { exception, error, promise, handler, id, parent } - // - var details = e.detail; - var id = details.id; - - // If the error has a parent promise then this is not the origination of the - // error so we check if it has a handler, and if so we mark that the error - // was handled by removing it from outstandingPromiseErrors - // - if (details.parent) { - if (details.handler && outstandingPromiseErrors) { - delete outstandingPromiseErrors[id]; - } - return; - } - - // If this is the first promise error to occur in this period we need to schedule - // a helper to come along after a setImmediate that propagates any remaining - // errors to the application's queue. - // - var shouldScheduleErrors = !outstandingPromiseErrors; - - // Indicate that this error was orignated and needs to be handled - // - outstandingPromiseErrors = outstandingPromiseErrors || []; - outstandingPromiseErrors[id] = details; - - if (shouldScheduleErrors) { - Scheduler.schedule(function () { - var errors = outstandingPromiseErrors; - outstandingPromiseErrors = null; - errors.forEach(function (error) { - queueEvent({ type: errorET, detail: error }); - }); - }, Scheduler.Priority.high, null, "WinJS.Application._queuePromiseErrors"); - } - } - - // capture this early - // - if (global.document) { - document.addEventListener("DOMContentLoaded", domContentLoadedHandler, false); - } - - function commandsRequested(e) { - var event = { e: e, applicationcommands: undefined }; - listeners.dispatchEvent(settingsET, event); - } - - function register() { - if (!registered) { - registered = true; - global.addEventListener("beforeunload", beforeUnloadHandler, false); - - if (useWinRT) { - global.addEventListener("error", errorHandler, false); - - var wui = Windows.UI.WebUI.WebUIApplication; - wui.addEventListener("activated", activatedHandler, false); - wui.addEventListener("suspending", suspendingHandler, false); - - var settingsPane = Windows.UI.ApplicationSettings.SettingsPane.getForCurrentView(); - settingsPane.addEventListener("commandsrequested", commandsRequested); - } - - WinJS.Promise.addEventListener("error", promiseErrorHandler); - } - } - function unregister() { - if (registered) { - registered = false; - global.removeEventListener("beforeunload", beforeUnloadHandler, false); - - if (useWinRT) { - global.removeEventListener("error", errorHandler, false); - - var wui = Windows.UI.WebUI.WebUIApplication; - wui.removeEventListener("activated", activatedHandler, false); - wui.removeEventListener("suspending", suspendingHandler, false); - - var settingsPane = Windows.UI.ApplicationSettings.SettingsPane.getForCurrentView(); - settingsPane.removeEventListener("commandsrequested", commandsRequested); - } - - WinJS.Promise.removeEventListener("error", promiseErrorHandler); - } - } - - - WinJS.Namespace.define("WinJS.Application", { - stop: function () { - /// - /// - /// Stops application event processing and resets WinJS.Application - /// to its initial state. - /// - /// - - // Need to clear out the event properties explicitly to clear their backing - // state. - // - this.onactivated = null; - this.oncheckpoint = null; - this.onerror = null; - this.onloaded = null; - this.onready = null; - this.onsettings = null; - this.onunload = null; - listeners = new ListenerType(); - WinJS.Application.sessionState = {}; - running = false; - copyAndClearQueue(); - eventQueueJob && eventQueueJob.cancel(); - eventQueueJob = null; - eventQueuedSignal = null; - unregister(); - cleanupAllPendingDeferrals(); - }, - - addEventListener: function (eventType, listener, capture) { - /// - /// - /// Adds an event listener to the control. - /// - /// - /// The type (name) of the event. - /// - /// - /// The listener to invoke when the event is raised. - /// - /// - /// true to initiate capture; otherwise, false. - /// - /// - listeners.addEventListener(eventType, listener, capture); - }, - removeEventListener: function (eventType, listener, capture) { - /// - /// - /// Removes an event listener from the control. - /// - /// - /// The type (name) of the event. - /// - /// - /// The listener to remove. - /// - /// - /// Specifies whether or not to initiate capture. - /// - /// - listeners.removeEventListener(eventType, listener, capture); - }, - - checkpoint: function () { - /// - /// - /// Queues a checkpoint event. - /// - /// - queueEvent({ type: checkpointET }); - }, - - start: function () { - /// - /// - /// Starts processing events in the WinJS.Application event queue. - /// - /// - register(); - running = true; - startEventQueue(); - }, - - queueEvent: queueEvent, - - _terminateApp: terminateAppHandler, - - }); - - Object.defineProperties(WinJS.Application, WinJS.Utilities.createEventProperties(checkpointET, unloadET, activatedET, loadedET, readyET, settingsET, errorET)); -})(this, WinJS); - -(function navigationInit(WinJS, undefined) { - "use strict"; - - var navigatedEventName = "navigated"; - var navigatingEventName = "navigating"; - var beforenavigateEventName = "beforenavigate"; - var ListenerType = WinJS.Class.mix(WinJS.Class.define(null, { /* empty */ }, { supportedForProcessing: false }), WinJS.Utilities.eventMixin); - var listeners = new ListenerType(); - var history = { - backStack: [], - current: { location: "", initialPlaceholder: true }, - forwardStack: [] - }; - - var raiseBeforeNavigate = function (proposed) { - msWriteProfilerMark("WinJS.Navigation:navigation,StartTM"); - return WinJS.Promise.as(). - then(function () { - var waitForPromise = WinJS.Promise.as(); - var defaultPrevented = listeners.dispatchEvent(beforenavigateEventName, { - setPromise: function (promise) { - /// - /// - /// Used to inform the ListView that asynchronous work is being performed, and that this - /// event handler should not be considered complete until the promise completes. - /// - /// - /// The promise to wait for. - /// - /// - - waitForPromise = waitForPromise.then(function() { return promise; }); - }, - location: proposed.location, - state: proposed.state - }); - return waitForPromise.then(function beforeNavComplete(cancel) { - return defaultPrevented || cancel; - }); - }); - }; - var raiseNavigating = function (delta) { - return WinJS.Promise.as(). - then(function () { - var waitForPromise = WinJS.Promise.as(); - listeners.dispatchEvent(navigatingEventName, { - setPromise: function (promise) { - /// - /// - /// Used to inform the ListView that asynchronous work is being performed, and that this - /// event handler should not be considered complete until the promise completes. - /// - /// - /// The promise to wait for. - /// - /// - - waitForPromise = waitForPromise.then(function() { return promise; }); - }, - location: history.current.location, - state: history.current.state, - delta: delta - }); - return waitForPromise; - }); - }; - var raiseNavigated = function (value, err) { - msWriteProfilerMark("WinJS.Navigation:navigation,StopTM"); - var waitForPromise = WinJS.Promise.as(); - var detail = { - value: value, - location: history.current.location, - state: history.current.state, - setPromise: function (promise) { - /// - /// - /// Used to inform the ListView that asynchronous work is being performed, and that this - /// event handler should not be considered complete until the promise completes. - /// - /// - /// The promise to wait for. - /// - /// - - waitForPromise = waitForPromise.then(function() { return promise; }); - } - }; - if (!value && err) { - detail.error = err; - } - listeners.dispatchEvent(navigatedEventName, detail); - return waitForPromise; - }; - - var go = function (distance, fromStack, toStack, delta) { - distance = Math.min(distance, fromStack.length); - if (distance > 0) { - return raiseBeforeNavigate(fromStack[fromStack.length - distance]). - then(function goBeforeCompleted(cancel) { - if (!cancel) { - toStack.push(history.current); - while (distance - 1 != 0) { - distance--; - toStack.push(fromStack.pop()); - } - history.current = fromStack.pop(); - return raiseNavigating(delta).then( - raiseNavigated, - function (err) { - raiseNavigated(undefined, err || true); - throw err; - }).then(function () { return true; }); - } - else { - return false; - } - }); - } - return WinJS.Promise.wrap(false); - } - - WinJS.Namespace.define("WinJS.Navigation", { - /// - /// Determines whether it is possible to navigate forwards. - /// - canGoForward: { - get: function () { - return history.forwardStack.length > 0; - } - }, - /// - /// Determines whether it is possible to navigate backwards. - /// - canGoBack: { - get: function () { - return history.backStack.length > 0; - } - }, - /// - /// Gets the current location. - /// - location: { - get: function () { - return history.current.location; - } - }, - /// - /// Gets or sets the navigation state. - /// - state: { - get: function () { - return history.current.state; - }, - set: function (value) { - history.current.state = value; - } - }, - /// - /// Gets or sets the navigation history. - /// - history: { - get: function () { - return history; - }, - set: function (value) { - var s = history = value; - - // ensure the require fields are present - // - s.backStack = s.backStack || []; - s.forwardStack = s.forwardStack || []; - s.current = s.current || { location: "", initialPlaceholder: true }; - s.current.location = s.current.location || ""; - } - }, - forward: function (distance) { - /// - /// - /// Navigates forwards. - /// - /// - /// The number of entries to go forward. - /// - /// - /// A promise that is completed with a value that indicates whether or not - /// the navigation was successful. - /// - /// - distance = distance || 1; - return go(distance, history.forwardStack, history.backStack, distance); - }, - back: function (distance) { - /// - /// - /// Navigates backwards. - /// - /// - /// The number of entries to go back into the history. - /// - /// - /// A promise that is completed with a value that indicates whether or not - /// the navigation was successful. - /// - /// - distance = distance || 1; - return go(distance, history.backStack, history.forwardStack, -distance); - }, - navigate: function (location, initialState) { - /// - /// - /// Navigates to a location. - /// - /// - /// The location to navigate to. Generally the location is a string, but - /// it may be anything. - /// - /// - /// The navigation state that may be accessed through WinJS.Navigation.state. - /// - /// - /// A promise that is completed with a value that indicates whether or not - /// the navigation was successful. - /// - /// - var proposed = { location: location, state: initialState }; - return raiseBeforeNavigate(proposed). - then(function navBeforeCompleted(cancel) { - if (!cancel) { - if (!history.current.initialPlaceholder) { - history.backStack.push(history.current); - } - history.forwardStack = []; - history.current = proposed; - - // error or no, we go from navigating -> navigated - // cancelation should be handled with "beforenavigate" - // - return raiseNavigating().then( - raiseNavigated, - function (err) { - raiseNavigated(undefined, err || true); - throw err; - }).then(function () { return true; }); - } - else { - return false; - } - }); - }, - addEventListener: function (eventType, listener, capture) { - /// - /// - /// Adds an event listener to the control. - /// - /// - /// The type (name) of the event. - /// - /// - /// The listener to invoke when the event gets raised. - /// - /// - /// Specifies whether or not to initiate capture. - /// - /// - listeners.addEventListener(eventType, listener, capture); - }, - removeEventListener: function (eventType, listener, capture) { - /// - /// - /// Removes an event listener from the control. - /// - /// - /// The type (name) of the event. - /// - /// - /// The listener to remove. - /// - /// - /// Specifies whether or not to initiate capture. - /// - /// - listeners.removeEventListener(eventType, listener, capture); - } - }); - - Object.defineProperties(WinJS.Navigation, WinJS.Utilities.createEventProperties(navigatedEventName, navigatingEventName, beforenavigateEventName)); -})(WinJS); - -(function stateInit(global) { - "use strict"; - - function initWithWinRT() { - var local, temp, roaming; - - var IOHelper = WinJS.Class.define( - function IOHelper_ctor(folder) { - this.folder = folder; - this._path = folder.path; - }, { - exists: function (fileName) { - /// - /// - /// Determines if the specified file exists in the container - /// - /// - /// The file which may exist within this folder - /// - /// - /// Promise with either true (file exists) or false. - /// - /// - return this.folder.tryGetItemAsync(fileName).then(function (fileItem) { - return fileItem ? true : false; - }); - }, - remove: function (fileName) { - /// - /// - /// Delets a file in the container - /// - /// - /// The file to be deleted - /// - /// - /// Promise which is fulfilled when the file has been deleted - /// - /// - var that = this; - return this.folder.tryGetItemAsync(fileName).then(function (fileItem) { - return fileItem ? fileItem.deleteAsync() : false; - }).then(null, function () { return false; }); - }, - writeText: function (fileName, str) { - /// - /// - /// Writes a file to the container with the specified text - /// - /// - /// The file to write to - /// - /// - /// Content to be written to the file - /// - /// - /// Promise with the count of characters written - /// - /// - var sto = Windows.Storage; - var that = this; - return that.folder.createFileAsync(fileName, sto.CreationCollisionOption.openIfExists). - then(function (fileItem) { - if (sto.FileIO) { - return sto.FileIO.writeTextAsync(fileItem, str); - } - else { - return sto.StorageHelpers.writeAllTextUsingFileAsync(fileItem, str); - } - }); - }, - - readText: function (fileName, def) { - /// - /// - /// Reads the contents of a file from the container, if the file - /// doesn't exist, def is returned. - /// - /// - /// The file to read from - /// - /// - /// Default value to be returned if the file failed to open - /// - /// - /// Promise containing the contents of the file, or def. - /// - /// - var sto = Windows.Storage; - return this.folder.tryGetItemAsync(fileName).then(function (fileItem) { - return fileItem ? sto.FileIO.readTextAsync(fileItem) : def; - }).then(null, function () { return def; }); - } - - }, { - supportedForProcessing: false, - }); - - WinJS.Namespace.define("WinJS.Application", { - /// - /// Allows access to create files in the application local storage, which is preserved across runs - /// of an application and does not roam. - /// - local: { - get: function () { - if (!local) { - local = new IOHelper(Windows.Storage.ApplicationData.current.localFolder); - } - return local; - } - }, - /// - /// Allows access to create files in the application temp storage, which may be reclaimed - /// by the system between application runs. - /// - temp: { - get: function () { - if (!temp) { - temp = new IOHelper(Windows.Storage.ApplicationData.current.temporaryFolder); - } - return temp; - } - }, - /// - /// Allows access to create files in the application roaming storage, which is preserved across runs - /// of an application and roams with the user across multiple machines. - /// - roaming: { - get: function () { - if (!roaming) { - roaming = new IOHelper(Windows.Storage.ApplicationData.current.roamingFolder); - } - return roaming; - } - } - }); - }; - - function initWithStub() { - var InMemoryHelper = WinJS.Class.define( - function InMemoryHelper_ctor() { - this.storage = {}; - }, { - exists: function (fileName) { - /// - /// - /// Determines if the specified file exists in the container - /// - /// - /// The filename which may exist within this folder - /// - /// - /// Promise with either true (file exists) or false. - /// - /// - // force conversion to boolean - // - return WinJS.Promise.as(this.storage[fileName] !== undefined); - }, - remove: function (fileName) { - /// - /// - /// Deletes a file in the container - /// - /// - /// The file to be deleted - /// - /// - /// Promise which is fulfilled when the file has been deleted - /// - /// - delete this.storage[fileName]; - return WinJS.Promise.as(); - }, - writeText: function (fileName, str) { - /// - /// - /// Writes a file to the container with the specified text - /// - /// - /// The filename to write to - /// - /// - /// Content to be written to the file - /// - /// - /// Promise with the count of characters written - /// - /// - this.storage[fileName] = str; - return WinJS.Promise.as(str.length); - }, - readText: function (fileName, def) { - /// - /// - /// Reads the contents of a file from the container, if the file - /// doesn't exist, def is returned. - /// - /// - /// The filename to read from - /// - /// - /// Default value to be returned if the file failed to open - /// - /// - /// Promise containing the contents of the file, or def. - /// - /// - var result = this.storage[fileName]; - return WinJS.Promise.as(typeof result === "string" ? result : def); - } - }, { - supportedForProcessing: false, - } - ); - - WinJS.Namespace.define("WinJS.Application", { - /// - /// Allows access to create files in the application local storage, which is preserved across runs - /// of an application and does not roam. - /// - local: new InMemoryHelper(), - /// - /// Allows access to create files in the application temp storage, which may be reclaimed - /// by the system between application runs. - /// - temp: new InMemoryHelper(), - /// - /// Allows access to create files in the application roaming storage, which is preserved across runs - /// of an application and roams with the user across multiple machines. - /// - roaming: new InMemoryHelper() - }); - } - - if (WinJS.Utilities.hasWinRT) { - initWithWinRT(); - } - else { - initWithStub(); - } - - WinJS.Namespace.define("WinJS.Application", { - sessionState: {}, - _loadState: function (e) { - var app = WinJS.Application; - - // we only restore state if we are coming back from a clear termination from PLM - // - if (e.previousExecutionState === 3 /* ApplicationExecutionState.Terminated */) { - return app.local.readText("_sessionState.json", "{}"). - then(function (str) { - var sessionState = JSON.parse(str); - if (sessionState && Object.keys(sessionState).length > 0) { - app._sessionStateLoaded = true; - } - app.sessionState = sessionState; - }). - then(null, function (err) { - app.sessionState = {}; - }); - } - else { - return WinJS.Promise.as(); - } - }, - _oncheckpoint: function (e) { - if (global.MSApp && MSApp.getViewOpener && MSApp.getViewOpener()) { - // don't save state in child windows. - return; - } - var app = WinJS.Application; - var sessionState = app.sessionState; - if ((sessionState && Object.keys(sessionState).length > 0) || app._sessionStateLoaded) { - var stateString; - try { - stateString = JSON.stringify(sessionState) - } catch (e) { - stateString = ""; - WinJS.Application.queueEvent({ type: "error", detail: e }); - } - e.setPromise( - app.local.writeText("_sessionState.json", stateString). - then(null, function (err) { - app.queueEvent({ type: "error", detail: err }); - }) - ); - } - } - }); -})(this); - -(function bindingParserInit(global, undefined) { - "use strict"; - - - var strings = { - get invalidBinding() { return WinJS.Resources._getWinJSString("base/invalidBinding").value; }, - get bindingInitializerNotFound() { return WinJS.Resources._getWinJSString("base/bindingInitializerNotFound").value; }, - }; - -/* - See comment for data-win-options attribute grammar for context. - - Syntactic grammar for the value of the data-win-bind attribute. - - BindDeclarations: - BindDeclaration - BindDeclarations ; BindDeclaration - - BindDeclaration: - DestinationPropertyName : SourcePropertyName - DestinationPropertyName : SourcePropertyName InitializerName - - DestinationPropertyName: - IdentifierExpression - - SourcePropertyName: - IdentifierExpression - - InitializerName: - IdentifierExpression - - Value: - NumberLiteral - StringLiteral - - AccessExpression: - [ Value ] - . Identifier - - AccessExpressions: - AccessExpression - AccessExpressions AccessExpression - - IdentifierExpression: - Identifier - Identifier AccessExpressions - -*/ - var imports = WinJS.Namespace.defineWithParent(null, null, { - lexer: WinJS.Namespace._lazy("WinJS.UI._optionsLexer"), - tokenType: WinJS.Namespace._lazy("WinJS.UI._optionsLexer.tokenType"), - }); - - var requireSupportedForProcessing = WinJS.Utilities.requireSupportedForProcessing; - - var local = WinJS.Namespace.defineWithParent(null, null, { - - BindingInterpreter: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(WinJS.UI.optionsParser._BaseInterpreter, function (tokens, originalSource, context) { - this._initialize(tokens, originalSource, context); - }, { - _error: function (message) { - throw new WinJS.ErrorFromName("WinJS.Binding.ParseError", WinJS.Resources._formatString(strings.invalidBinding, this._originalSource, message)); - }, - _evaluateInitializerName: function () { - if (this._current.type === imports.tokenType.identifier) { - var initializer = this._evaluateIdentifierExpression(); - if (WinJS.log && !initializer) { - WinJS.log(WinJS.Resources._formatString(strings.bindingInitializerNotFound, this._originalSource), "winjs binding", "error"); - } - return requireSupportedForProcessing(initializer); - } - return; - }, - _evaluateValue: function () { - switch (this._current.type) { - case imports.tokenType.stringLiteral: - case imports.tokenType.numberLiteral: - var value = this._current.value; - this._read(); - return value; - - default: - this._unexpectedToken(imports.tokenType.stringLiteral, imports.tokenType.numberLiteral); - return; - } - }, - _readBindDeclarations: function () { - var bindings = []; - while (true) { - switch (this._current.type) { - case imports.tokenType.identifier: - case imports.tokenType.thisKeyword: - bindings.push(this._readBindDeclaration()); - break; - - case imports.tokenType.semicolon: - this._read(); - break; - - case imports.tokenType.eof: - return bindings; - - default: - this._unexpectedToken(imports.tokenType.identifier, imports.tokenType.semicolon, imports.tokenType.eof); - return; - } - } - }, - _readBindDeclaration: function () { - var dest = this._readDestinationPropertyName(); - this._read(imports.tokenType.colon); - var src = this._readSourcePropertyName(); - var initializer = this._evaluateInitializerName(); - return { - destination: dest, - source: src, - initializer: initializer, - }; - }, - _readDestinationPropertyName: function () { - return this._readIdentifierExpression(); - }, - _readSourcePropertyName: function () { - return this._readIdentifierExpression(); - }, - run: function () { - return this._readBindDeclarations(); - } - }, { - supportedForProcessing: false, - }); - }), - - BindingParser: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(local.BindingInterpreter, function (tokens, originalSource) { - this._initialize(tokens, originalSource, {}); - }, { - _readInitializerName: function () { - if (this._current.type === imports.tokenType.identifier) { - return this._readIdentifierExpression(); - } - return; - }, - _readBindDeclaration: function () { - var dest = this._readDestinationPropertyName(); - this._read(imports.tokenType.colon); - var src = this._readSourcePropertyName(); - var initializer = this._readInitializerName(); - return { - destination: dest, - source: src, - initializer: initializer, - }; - }, - }, { - supportedForProcessing: false, - }); - }) - - }); - - function parser(text, context) { - msWriteProfilerMark("WinJS.Binding:bindingParser,StartTM"); - var tokens = imports.lexer(text); - var interpreter = new local.BindingInterpreter(tokens, text, context || {}); - var res = interpreter.run(); - msWriteProfilerMark("WinJS.Binding:bindingParser,StopTM"); - return res; - } - - function parser2(text) { - msWriteProfilerMark("WinJS.Binding:bindingParser,StartTM"); - var tokens = imports.lexer(text); - var interpreter = new local.BindingParser(tokens, text); - var res = interpreter.run(); - msWriteProfilerMark("WinJS.Binding:bindingParser,StopTM"); - return res; - } - - WinJS.Namespace.define("WinJS.Binding", { - - _bindingParser: parser, - _bindingParser2: parser2, - - }); - -})(this); - -(function dataInit(WinJS, undefined) { - "use strict"; - - - var strings = { - get exceptionFromBindingInitializer() { return WinJS.Resources._getWinJSString("base/exceptionFromBindingInitializer").value; }, - get propertyIsUndefined() { return WinJS.Resources._getWinJSString("base/propertyIsUndefined").value; }, - get unsupportedDataTypeForBinding() { return WinJS.Resources._getWinJSString("base/unsupportedDataTypeForBinding").value; }, - }; - - var observableMixin = { - _listeners: null, - _pendingNotifications: null, - _notifyId: 0, - - _getObservable: function () { - return this; - }, - - _cancel: function (name) { - var v = this._pendingNotifications; - var hit = false; - if (v) { - var k = Object.keys(v); - for (var i = k.length - 1; i >= 0; i--) { - var entry = v[k[i]]; - if (entry.target === name) { - if (entry.promise) { - entry.promise.cancel(); - entry.promise = null; - } - delete v[k[i]]; - hit = true; - } - } - } - return hit; - }, - - notify: function (name, newValue, oldValue) { - /// - /// - /// Notifies listeners that a property value was updated. - /// - /// The name of the property that is being updated. - /// The new value for the property. - /// The old value for the property. - /// A promise that is completed when the notifications are complete. - /// - var listeners = this._listeners && this._listeners[name]; - if (listeners) { - var that = this; - - // Handle the case where we are updating a value that is currently updating - // - that._cancel(name); - - // Starting new work, we cache the work description and queue up to do the notifications - // - that._pendingNotifications = that._pendingNotifications || {}; - var x = that._notifyId++; - var cap = that._pendingNotifications[x] = { target: name }; - - var cleanup = function () { - delete that._pendingNotifications[x]; - } - - // Binding guarantees async notification, so we do timeout() - // - cap.promise = WinJS.Utilities.Scheduler.schedulePromiseNormal(null, "WinJS.Binding.observableMixin.notify"). - then(function () { - // cap.promise is removed after canceled, so we use this as a signal - // to indicate that we should abort early - // - for (var i = 0, l = listeners.length; i < l && cap.promise; i++) { - try { - listeners[i](newValue, oldValue); - } - catch (e) { - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.exceptionFromBindingInitializer, e.toString()), "winjs binding", "error"); - } - } - cleanup(); - return newValue; - }); - - return cap.promise; - } - - return WinJS.Promise.as(); - }, - - bind: function (name, action) { - /// - /// - /// Links the specified action to the property specified in the name parameter. - /// This function is invoked when the value of the property may have changed. - /// It is not guaranteed that the action will be called only when a value has actually changed, - /// nor is it guaranteed that the action will be called for every value change. The implementation - /// of this function coalesces change notifications, such that multiple updates to a property - /// value may result in only a single call to the specified action. - /// - /// - /// The name of the property to which to bind the action. - /// - /// - /// The function to invoke asynchronously when the property may have changed. - /// - /// - /// This object is returned. - /// - /// - - this._listeners = this._listeners || {}; - var listeners = this._listeners[name] = this._listeners[name] || []; - - // duplicate detection, multiple binds with the same action should have no effect - // - var found = false; - for (var i = 0, l = listeners.length; i < l; i++) { - if (listeners[i] === action) { - found = true; - break; - } - } - - if (!found) { - listeners.push(action); - - // out of band notification, we want to avoid a broadcast to all listeners - // so we can't just call notify. - // - action(unwrap(this[name])); - } - return this; - }, - - unbind: function (name, action) { - /// - /// - /// Removes one or more listeners from the notification list for a given property. - /// - /// - /// The name of the property to unbind. If this parameter is omitted, all listeners - /// for all events are removed. - /// - /// - /// The function to remove from the listener list for the specified property. If this parameter is omitted, all listeners - /// are removed for the specific property. - /// - /// - /// This object is returned. - /// - /// - - this._listeners = this._listeners || {}; - - if (name && action) { - // this assumes we rarely have more than one - // listener, so we optimize to not do a lot of - // array manipulation, although it means we - // may do some extra GC churn in the other cases... - // - var listeners = this._listeners[name]; - if (listeners) { - var nl; - for (var i = 0, l = listeners.length; i < l; i++) { - if (listeners[i] !== action) { - (nl = nl || []).push(listeners[i]); - } - } - this._listeners[name] = nl; - } - - // we allow any pending notification sweep to complete, - // which means that "unbind" inside of a notification - // will not prevent that notification from occuring. - // - } - else if (name) { - this._cancel(name); - delete this._listeners[name]; - } - else { - var that = this; - if (that._pendingNotifications) { - var v = that._pendingNotifications; - that._pendingNotifications = {}; - Object.keys(v).forEach(function (k) { - var n = v[k]; - if (n.promise) { n.promise.cancel(); } - }); - } - this._listeners = {}; - } - return this; - } - }; - - var dynamicObservableMixin = { - _backingData: null, - - _initObservable: function (data) { - this._backingData = data || {}; - }, - - getProperty: function (name) { - /// - /// - /// Gets a property value by name. - /// - /// - /// The name of property to get. - /// - /// - /// The value of the property as an observable object. - /// - /// - var data = this._backingData[name]; - if (WinJS.log && data === undefined) { - WinJS.log(WinJS.Resources._formatString(strings.propertyIsUndefined, name), "winjs binding", "warn"); - } - return as(data); - }, - - setProperty: function (name, value) { - /// - /// - /// Updates a property value and notifies any listeners. - /// - /// - /// The name of the property to update. - /// - /// - /// The new value of the property. - /// - /// - /// This object is returned. - /// - /// - - this.updateProperty(name, value); - return this; - }, - - addProperty: function (name, value) { - /// - /// - /// Adds a property with change notification to this object, including a ECMAScript5 property definition. - /// - /// - /// The name of the property to add. - /// - /// - /// The value of the property. - /// - /// - /// This object is returned. - /// - /// - - // we could walk Object.keys to more deterministically determine this, - // however in the normal case this avoids a bunch of string compares - // - if (!this[name]) { - Object.defineProperty(this, - name, { - get: function () { return this.getProperty(name); }, - set: function (value) { this.setProperty(name, value); }, - enumerable: true, - configurable: true - } - ); - } - return this.setProperty(name, value); - }, - - updateProperty: function (name, value) { - /// - /// - /// Updates a property value and notifies any listeners. - /// - /// - /// The name of the property to update. - /// - /// - /// The new value of the property. - /// - /// - /// A promise that completes when the notifications for - /// this property change have been processed. If multiple notifications are coalesced, - /// the promise may be canceled or the value of the promise may be updated. - /// The fulfilled value of the promise is the new value of the property for - /// which the notifications have been completed. - /// - /// - - var oldValue = this._backingData[name]; - var newValue = unwrap(value); - if (oldValue !== newValue) { - this._backingData[name] = newValue; - - // This will complete when the listeners are notified, even - // if a new value is used. The only time this promise will fail - // (cancel) will be if we start notifying and then have to - // cancel in the middle of processing it. That's a pretty - // subtle contract. - // - return this.notify(name, newValue, oldValue); - } - return WinJS.Promise.as(); - }, - - removeProperty: function (name) { - /// - /// - /// Removes a property value. - /// - /// - /// The name of the property to remove. - /// - /// - /// This object is returned. - /// - /// - - var oldValue = this._backingData[name]; - var value; // capture "undefined" - // in strict mode these may throw - try { - delete this._backingData[name]; - } catch (e) { } - try { - delete this[name]; - } catch (e) { } - this.notify(name, value, oldValue); - return this; - } - }; - - // Merge "obsevable" into "dynamicObservable" - // - Object.keys(observableMixin).forEach(function (k) { - dynamicObservableMixin[k] = observableMixin[k]; - }); - - - var bind = function (observable, bindingDescriptor) { - /// - /// - /// Binds to one or more properties on the observable object or or on child values - /// of that object. - /// - /// - /// The object to bind to. - /// - /// - /// An object literal containing the binding declarations. Binding declarations take the form: - /// { propertyName: (function | bindingDeclaration), ... } - /// - /// For example, binding to a nested member of an object is declared like this: - /// bind(someObject, { address: { street: function(v) { ... } } }); - /// - /// - /// An object that contains at least a "cancel" field, which is - /// a function that removes all bindings associated with this bind - /// request. - /// - /// - return bindImpl(observable, bindingDescriptor); - } - var bindRefId = 0; - var createBindRefId = function () { - return "bindHandler" + (bindRefId++); - }; - var createProxy = function (func, bindStateRef) { - if (!WinJS.Utilities.hasWinRT) { - return func; - } - - var id = createBindRefId(); - WinJS.Utilities._getWeakRefElement(bindStateRef)[id] = func; - return function (n, o) { - var bindState = WinJS.Utilities._getWeakRefElement(bindStateRef); - if (bindState) { - bindState[id](n, o); - } - }; - } - var bindImpl = function (observable, bindingDescriptor, bindStateRef) { - observable = WinJS.Binding.as(observable); - if (!observable) { - return { cancel: function () { }, empty: true }; - } - - var bindState; - if (!bindStateRef) { - bindStateRef = createBindRefId(); - bindState = {}; - WinJS.Utilities._createWeakRef(bindState, bindStateRef); - } - - var complexLast = {}; - var simpleLast = null; - - function cancelSimple() { - if (simpleLast) { - simpleLast.forEach(function (e) { - e.source.unbind(e.prop, e.listener); - }); - } - simpleLast = null; - } - - function cancelComplex(k) { - if (complexLast[k]) { - complexLast[k].complexBind.cancel(); - delete complexLast[k]; - } - } - - Object.keys(bindingDescriptor).forEach(function (k) { - var listener = bindingDescriptor[k]; - if (listener instanceof Function) { - // Create a proxy for the listener which indirects weakly through the bind - // state, if this is the root object tack the bind state onto the listener - // - listener = createProxy(listener, bindStateRef); - listener.bindState = bindState; - simpleLast = simpleLast || []; - simpleLast.push({ source: observable, prop: k, listener: listener }); - observable.bind(k, listener); - } - else { - var propChanged = function (v) { - cancelComplex(k); - var complexBind = bindImpl(as(v), listener, bindStateRef); - - // In the case that we hit an "undefined" in the chain, we prop the change - // notification to all listeners, basically saying that x.y.z where "y" - // is undefined resolves to undefined. - // - if (complexBind.empty) { - var recursiveNotify = function (root) { - Object.keys(root).forEach(function (key) { - var item = root[key]; - if (item instanceof Function) { - item(undefined, undefined); - } - else { - recursiveNotify(item); - } - }); - }; - recursiveNotify(listener); - } - complexLast[k] = { source: v, complexBind: complexBind }; - }; - - // Create a proxy for the listener which indirects weakly through the bind - // state, if this is the root object tack the bind state onto the listener - // - propChanged = createProxy(propChanged, bindStateRef); - propChanged.bindState = bindState; - simpleLast = simpleLast || []; - simpleLast.push({ source: observable, prop: k, listener: propChanged }); - observable.bind(k, propChanged); - } - }); - - return { - cancel: function () { - cancelSimple(); - Object.keys(complexLast).forEach(function (k) { cancelComplex(k); }); - } - } - }; - - - var ObservableProxy = WinJS.Class.mix(function (data) { - this._initObservable(data); - Object.defineProperties(this, expandProperties(data)); - }, dynamicObservableMixin); - - var expandProperties = function (shape) { - /// - /// - /// Wraps the specified object so that all its properties - /// are instrumented for binding. This is meant to be used in - /// conjunction with the binding mixin. - /// - /// - /// The specification for the bindable object. - /// - /// - /// An object with a set of properties all of which are wired for binding. - /// - /// - var props = {}; - function addToProps(k) { - props[k] = { - get: function () { return this.getProperty(k); }, - set: function (value) { this.setProperty(k, value); }, - enumerable: true, - configurable: true // enables delete - }; - } - while (shape && shape !== Object.prototype) { - Object.keys(shape).forEach(addToProps); - shape = Object.getPrototypeOf(shape); - } - return props; - }; - - var define = function (data) { - /// - /// - /// Creates a new constructor function that supports observability with - /// the specified set of properties. - /// - /// - /// The object to use as the pattern for defining the set of properties, for example: - /// var MyPointClass = define({x:0,y:0}); - /// - /// - /// A constructor function with 1 optional argument that is the initial state of - /// the properties. - /// - /// - - // Common unsupported types, we just coerce to be an empty record - // - if (!data || typeof (data) !== "object" || (data instanceof Date) || (data instanceof Array)) { - if (WinJS.validation) { - throw new WinJS.ErrorFromName("WinJS.Binding.UnsupportedDataType", WinJS.Resources._formatString(strings.unsupportedDataTypeForBinding)); - } - else { - return; - } - } - - return WinJS.Class.mix( - function (init) { - /// - /// - /// Creates a new observable object. - /// - /// - /// The initial values for the properties. - /// - /// - - this._initObservable(init || Object.create(data)); - }, - WinJS.Binding.dynamicObservableMixin, - WinJS.Binding.expandProperties(data) - ); - }; - - var as = function (data) { - /// - /// - /// Returns an observable object. This may be an observable proxy for the specified object, an existing proxy, or - /// the specified object itself if it directly supports observability. - /// - /// - /// Object to provide observability for. - /// - /// - /// The observable object. - /// - /// - - if (!data) { - return data; - } - - var type = typeof data; - if (type === "object" - && !(data instanceof Date) - && !(data instanceof Array)) { - if (data._getObservable) { - return data._getObservable(); - } - - var observable = new ObservableProxy(data); - observable.backingData = data; - Object.defineProperty( - data, - "_getObservable", - { - value: function () { return observable; }, - enumerable: false, - writable: false - } - ); - return observable; - } - else { - return data; - } - }; - - var unwrap = function (data) { - /// - /// - /// Returns the original (non-observable) object is returned if the specified object is an observable proxy, . - /// - /// - /// The object for which to retrieve the original value. - /// - /// - /// If the specified object is an observable proxy, the original object is returned, otherwise the same object is returned. - /// - /// - if (data && data.backingData) - return data.backingData; - else - return data; - }; - - WinJS.Namespace.define("WinJS.Binding", { - // must use long form because mixin has "get" and "set" as members, so the define - // method thinks it's a property - mixin: { value: dynamicObservableMixin, enumerable: false, writable: true, configurable: true }, - dynamicObservableMixin: { value: dynamicObservableMixin, enumerable: true, writable: true, configurable: true }, - observableMixin: { value: observableMixin, enumerable: true, writable: true, configurable: true }, - expandProperties: expandProperties, - define: define, - as: as, - unwrap: unwrap, - bind: bind - }); -})(WinJS); - -(function dataTemplateInit(global, WinJS, undefined) { - "use strict"; - - // not supported in WebWorker - if (!global.document) { - return; - } - - var P = WinJS.Promise; - var cancelBlocker = P._cancelBlocker; - var markSupportedForProcessing = WinJS.Utilities.markSupportedForProcessing; - - WinJS.Namespace.define("WinJS.Binding", { - - /// - /// Provides a reusable declarative binding element. - /// - /// Template - ///
    Place content here
    ]]>
    - /// - /// - /// - /// - Template: WinJS.Namespace._lazy(function () { - function interpretedRender(template, dataContext, container) { - msWriteProfilerMark("WinJS.Binding:templateRender" + template._profilerMarkIdentifier + ",StartTM"); - - if (++template._counter === 1 && (template.debugBreakOnRender || WinJS.Binding.Template._debugBreakOnRender)) { - debugger; - } - - var workPromise = WinJS.Promise.wrap(); - var d = container || document.createElement(template.element.tagName); - - WinJS.Utilities.addClass(d, "win-template"); - WinJS.Utilities.addClass(d, "win-loading"); - var that = template; - function done() { - WinJS.Utilities.removeClass(d, "win-loading"); - msWriteProfilerMark("WinJS.Binding:templateRender" + template._profilerMarkIdentifier + ",StopTM"); - return extractedChild || d; - } - var initial = d.children.length; - var element; - var extractedChild; - var dispose = function () { - var bindings = WinJS.Utilities.data(d).winBindings; - if (bindings) { - bindings.forEach(function (item) { - item.cancel(); - }); - } - workPromise.cancel(); - }; - if (template.extractChild) { - element = WinJS.UI.Fragments.renderCopy(that.href || that.element, document.createElement(that.element.tagName)).then(function (frag) { - var child = frag.firstElementChild; - extractedChild = child; - WinJS.Utilities.markDisposable(child, dispose); - d.appendChild(child); - return child; - }); - } else { - WinJS.Utilities.markDisposable(d, dispose); - element = WinJS.UI.Fragments.renderCopy(that.href || that.element, d); - } - var renderComplete = element. - then(function Template_renderImpl_renderComplete_then() { - var work; - // If no existing children, we can do the faster path of just calling - // on the root element... - // - if (initial === 0) { - work = function (f, a, b, c) { return f(extractedChild || d, a, b, c); }; - } - // We only grab the newly added nodes (always at the end) - // and in the common case of only adding a single new element - // we avoid the "join" overhead - // - else { - var all = d.children; - if (all.length === initial + 1) { - work = function (f, a, b, c) { return f(all[initial], a, b, c); }; - } - else { - // we have to capture the elements first, in case - // doing the work affects the children order/content - // - var elements = []; - for (var i = initial, l = all.length; i < l; i++) { - elements.push(all[i]); - } - work = function (f, a, b, c) { - var join = []; - elements.forEach(function (e) { - join.push(f(e, a, b, c)); - }); - return WinJS.Promise.join(join); - }; - } - } - - var child = d.firstElementChild; - while (child) { - child.msParentSelectorScope = true; - child = child.nextElementSibling; - } - - // This allows "0" to mean no timeout (at all) and negative values - // mean setImmediate (no setTimeout). Since Promise.timeout uses - // zero to mean setImmediate, we have to coerce. - // - var timeout = that.processTimeout; - function complete() { - return work(WinJS.UI.processAll). - then(function () { return cancelBlocker(dataContext); }). - then(function Template_renderImpl_Binding_processAll(data) { - return work(WinJS.Binding.processAll, data, !extractedChild && !initial, that.bindingCache); - }). - then(null, function (e) { - if (typeof e === "object" && e.name === "Canceled") { - (extractedChild || d).dispose(); - } - return WinJS.Promise.wrapError(e); - }); - } - if (timeout) { - if (timeout < 0) { timeout = 0; } - return WinJS.Promise.timeout(timeout).then(function () { - return workPromise = complete(); - }); - } - else { - return workPromise = complete(); - } - }).then(done, function (err) { done(); return WinJS.Promise.wrapError(err); }); - - return { element: element, renderComplete: renderComplete }; - } - - return WinJS.Class.define(function Template_ctor(element, options) { - /// - /// - /// Creates a template that provides a reusable declarative binding element. - /// - /// - /// The DOM element to convert to a template. - /// - /// - /// If this parameter is supplied, the template is loaded from the URI and - /// the content of the element parameter is ignored. - /// - /// - - this._element = element || document.createElement("div"); - this._element.winControl = this; - - this._profilerMarkIdentifier = WinJS.Utilities._getProfilerMarkIdentifier(this._element); - msWriteProfilerMark("WinJS.Binding:newTemplate" + this._profilerMarkIdentifier + ",StartTM"); - - var that = this; - this._element.renderItem = function (itemPromise, recycled) { return that._renderItemImpl(itemPromise, recycled); }; - - options = options || {}; - this.href = options.href; - this.enableRecycling = !!options.enableRecycling; - this.processTimeout = options.processTimeout || 0; - this.bindingInitializer = options.bindingInitializer; - this.debugBreakOnRender = options.debugBreakOnRender; - this.disableOptimizedProcessing = options.disableOptimizedProcessing; - this.extractChild = options.extractChild; - this._counter = 0; - - // This will eventually change name and reverse polarity, starting opt-in. - // - this._compile = !!options._compile; - - if (!this.href) { - this.element.style.display = "none"; - } - this.bindingCache = { expressions: {} }; - - msWriteProfilerMark("WinJS.Binding:newTemplate" + this._profilerMarkIdentifier + ",StopTM"); - }, { - _shouldCompile: { - get: function () { - // This is the temporary switch to opt-in to compilation, eventually replaced - // by default opt-in with an opt-out switch. - // - var shouldCompile = true; - shouldCompile = shouldCompile && !WinJS.Binding.Template._interpretAll; - shouldCompile = shouldCompile && !this.disableOptimizedProcessing; - - if (shouldCompile) { - shouldCompile = shouldCompile && this.processTimeout === 0; - shouldCompile = shouldCompile && (!this.href || this.href instanceof HTMLElement); - - if (!shouldCompile) { - WinJS.log && WinJS.log("Cannot compile templates which use processTimeout or href properties", "winjs binding", "warn"); - } - } - - return shouldCompile; - } - }, - - /// - /// If specified this function is used as the default initializer for any data bindings which do not explicitly specify one. The - /// provided function must be marked as supported for processing. - /// - bindingInitializer: { - get: function () { return this._bindingInitializer; }, - set: function (value) { - this._bindingInitializer = value; - this._reset(); - } - }, - - /// - /// Indicates whether a templates should break in the debugger on first render - /// - debugBreakOnRender: { - get: function () { return this._debugBreakOnRender; }, - set: function (value) { - this._debugBreakOnRender = !!value; - this._reset(); - } - }, - - /// - /// Set this property to true to resotre classic template processing and data binding and disable template compilation. - /// - disableOptimizedProcessing: { - get: function () { return this._disableOptimizedProcessing; }, - set: function (value) { - this._disableOptimizedProcessing = !!value; - this._reset(); - } - }, - - /// - element: { - get: function () { return this._element; }, - }, - - /// - /// Return the first element child of the template instead of a wrapper element hosting all the template content. - /// - extractChild: { - get: function () { return this._extractChild; }, - set: function (value) { - this._extractChild = !!value; - this._reset(); - } - }, - - /// - /// Number of milliseconds to delay instantiating declarative controls. Zero (0) will result in no delay, any negative number - /// will result in a setImmediate delay, any positive number will be treated as the number of milliseconds. - /// - processTimeout: { - get: function () { return this._processTimeout || 0; }, - set: function (value) { - this._processTimeout = value; - this._reset(); - } - }, - - render: WinJS.Utilities.markSupportedForProcessing(function (dataContext, container) { - /// - /// - /// Binds values from the specified data context to elements that are descendents of the specified root element - /// and have the declarative binding attributes (data-win-bind). - /// - /// - /// The object to use for default data binding. - /// - /// - /// The element to which to add this rendered template. If this parameter is omitted, a new DIV is created. - /// - /// - /// A promise that is completed after binding has finished. The value is - /// either the element specified in the container parameter or the created DIV. - /// - /// - - return this._renderImpl(dataContext, container); - }), - - // Hook point for compiled template - // - _renderImpl: function (dataContext, container) { - if (this._shouldCompile) { - try { - this._renderImpl = this._compileTemplate({ target: "render" }); - return this._renderImpl(dataContext, container); - } catch (e) { - return WinJS.Promise.wrapError(e); - } - } - - var render = interpretedRender(this, dataContext, container); - return render.element.then(function () { return render.renderComplete; }); - }, - - _renderInterpreted: function (dataContext, container) { - return interpretedRender(this, dataContext, container); - }, - - renderItem: function (item, recycled) { - /// - /// - /// Renders an instance of this template bound to the data contained in item. If - /// the recycled parameter is present, and enableRecycling is true, then the template attempts - /// to reuse the DOM elements from the recycled parameter. - /// - /// - /// The object that contains the data to bind to. Only item.data is required. - /// - /// - /// A previously-generated template instance. - /// - /// - /// The DOM element. - /// - /// - return this._renderItemImpl(item, recycled); - }, - - // Hook point for compiled template - // - _renderItemImpl: function (item, recycled) { - if (this._shouldCompile) { - try { - this._renderItemImpl = this._compileTemplate({ target: "renderItem" }); - return this._renderItemImpl(item); - } catch (e) { - return { - element: WinJS.Promise.wrapError(e), - renderComplete: WinJS.Promise.wrapError(e), - }; - } - } - - var that = this; - - // we only enable element cache when we are trying - // to recycle. Otherwise our element cache would - // grow unbounded. - // - if (this.enableRecycling && !this.bindingCache.elements) { - this.bindingCache.elements = {}; - } - - if (this.enableRecycling - && recycled - && recycled.msOriginalTemplate === this) { - - // If we are asked to recycle, we cleanup any old work no matter what - // - var cacheEntry = this.bindingCache.elements[recycled.id]; - var okToReuse = true; - if (cacheEntry) { - cacheEntry.bindings.forEach(function (v) { v(); }); - cacheEntry.bindings = []; - okToReuse = !cacheEntry.nocache; - } - - // If our cache indicates that we hit a non-cancelable thing, then we are - // in an unknown state, so we actually can't recycle the tree. We have - // cleaned up what we can, but at this point we need to reset and create - // a new tree. - // - if (okToReuse) { - // Element recycling requires that there be no other content in "recycled" other than this - // templates' output. - // - return { - element: recycled, - renderComplete: item.then(function (item) { - return WinJS.Binding.processAll(recycled, item.data, true, that.bindingCache); - }), - }; - } - } - - var render = interpretedRender(this, item.then(function (item) { return item.data; })); - render.element = render.element.then(function (e) { e.msOriginalTemplate = that; return e; }); - return render; - }, - - _compileTemplate: function (options) { - - var that = this; - - var result = WinJS.Binding._TemplateCompiler.compile(this, this.href || this.element, { - debugBreakOnRender: this.debugBreakOnRender || WinJS.Binding.Template._debugBreakOnRender, - defaultInitializer: this.bindingInitializer || options.defaultInitializer, - disableTextBindingOptimization: options.disableTextBindingOptimization || false, - target: options.target, - extractChild: this.extractChild, - profilerMarkIdentifier: this._profilerMarkIdentifier - }); - - var resetOnFragmentChange = options.resetOnFragmentChange || (window.Windows && Windows.ApplicationModel && Windows.ApplicationModel.DesignMode && Windows.ApplicationModel.DesignMode.designModeEnabled); - if (resetOnFragmentChange) { - var mo = new MutationObserver(function () { - that._reset(); - mo.disconnect(); - }); - mo.observe(WinJS.Utilities.data(this.element).docFragment, { - childList: true, - attributes: true, - characterData: true, - subtree: true, - }); - } - - return result; - - }, - - _reset: function () { - // Reset the template to being not compiled. In design mode this triggers on a mutation - // of the original document fragment. - delete this._renderImpl; - delete this._renderItemImpl; - }, - - }, { - isDeclarativeControlContainer: { value: true, writable: false, configurable: false }, - render: { - value: function (href, dataContext, container) { - /// - /// - /// Renders a template based on a URI. - /// - /// - /// The URI from which to load the template. - /// - /// - /// The object to use for default data binding. - /// - /// - /// The element to which to add this rendered template. If this parameter is omitted, a new DIV is created. - /// - /// - /// A promise that is completed after binding has finished. The value is - /// either the object in the container parameter or the created DIV. - /// - /// - return new WinJS.Binding.Template(null, { href: href }).render(dataContext, container); - } - } - }); - }) - }); - - if (WinJS.Utilities && WinJS.Utilities.QueryCollection) { - WinJS.Class.mix(WinJS.Utilities.QueryCollection, { - template: function (templateElement, data, renderDonePromiseCallback) { - /// - /// - /// Renders a template that is bound to the given data - /// and parented to the elements included in the QueryCollection. - /// If the QueryCollection contains multiple elements, the template - /// is rendered multiple times, once at each element in the QueryCollection - /// per item of data passed. - /// - /// - /// The DOM element to which the template control is attached to. - /// - /// - /// The data to render. If the data is an array (or any other object - /// that has a forEach method) then the template is rendered - /// multiple times, once for each item in the collection. - /// - /// - /// If supplied, this function is called - /// each time the template gets rendered, and is passed a promise - /// that is fulfilled when the template rendering is complete. - /// - /// - /// The QueryCollection. - /// - /// - if (templateElement instanceof WinJS.Utilities.QueryCollection) { - templateElement = templateElement[0]; - } - var template = templateElement.winControl; - - if (data === null || data === undefined || !data.forEach) { - data = [data]; - } - - renderDonePromiseCallback = renderDonePromiseCallback || function () { }; - - var that = this; - var donePromises = []; - data.forEach(function (datum) { - that.forEach(function (element) { - donePromises.push(template.render(datum, element)); - }); - }); - renderDonePromiseCallback(WinJS.Promise.join(donePromises)); - - return this; - } - }); - } - -})(this, WinJS); - -(function declarativeInit(WinJS, global, undefined) { - "use strict"; - - var uid = (Math.random() * 1000) >> 0; - - // If we have proper weak references then we can move away from using the element's ID property - // - var optimizeBindingReferences = WinJS.Utilities.hasWinRT && global.msSetWeakWinRTProperty && global.msGetWeakWinRTProperty; - - var strings = { - get attributeBindingSingleProperty() { return WinJS.Resources._getWinJSString("base/attributeBindingSingleProperty").value; }, - get cannotBindToThis() { return WinJS.Resources._getWinJSString("base/cannotBindToThis").value; }, - get creatingNewProperty() { return WinJS.Resources._getWinJSString("base/creatingNewProperty").value; }, - get duplicateBindingDetected() { return WinJS.Resources._getWinJSString("base/duplicateBindingDetected").value; }, - get elementNotFound() { return WinJS.Resources._getWinJSString("base/elementNotFound").value; }, - get errorInitializingBindings() { return WinJS.Resources._getWinJSString("base/errorInitializingBindings").value; }, - get propertyDoesNotExist() { return WinJS.Resources._getWinJSString("base/propertyDoesNotExist").value; }, - get idBindingNotSupported() { return WinJS.Resources._getWinJSString("base/idBindingNotSupported").value; }, - get nestedDOMElementBindingNotSupported() { return WinJS.Resources._getWinJSString("base/nestedDOMElementBindingNotSupported").value; } - } - - var markSupportedForProcessing = WinJS.Utilities.markSupportedForProcessing; - var requireSupportedForProcessing = WinJS.Utilities.requireSupportedForProcessing; - - function registerAutoDispose(bindable, callback) { - var d = bindable._autoDispose; - d && d.push(callback); - } - function autoDispose(bindable) { - bindable._autoDispose = (bindable._autoDispose || []).filter(function (callback) { return callback(); }); - } - - function checkBindingToken(element, bindingId) { - if (element) { - if (element.winBindingToken === bindingId) { - return element; - } - else { - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.duplicateBindingDetected, element.id), "winjs binding", "error"); - } - } - else { - return element; - } - } - - function setBindingToken(element) { - if (element.winBindingToken) { - return element.winBindingToken; - } - - var bindingToken = "_win_bind" + (uid++); - Object.defineProperty(element, "winBindingToken", { configurable: false, writable: false, enumerable: false, value: bindingToken }); - return bindingToken; - } - - function initializerOneBinding(bind, ref, bindingId, source, e, pend, cacheEntry) { - var initializer = bind.initializer; - if (initializer) { - initializer = initializer.winControl || initializer["data-win-control"] || initializer; - } - if (initializer instanceof Function) { - var result = initializer(source, bind.source, e, bind.destination); - - if (cacheEntry) { - if (result && result.cancel) { - cacheEntry.bindings.push(function () { result.cancel(); }); - } - else { - // notify the cache that we encountered an uncancellable thing - // - cacheEntry.nocache = true; - } - } - return result; - } - else if (initializer && initializer.render) { - pend.count++; - - // notify the cache that we encountered an uncancellable thing - // - if (cacheEntry) { - cacheEntry.nocache = true; - } - - requireSupportedForProcessing(initializer.render).call(initializer, getValue(source, bind.source), e). - then(function () { - pend.checkComplete(); - }); - } - } - - function makeBinding(ref, bindingId, pend, bindable, bind, cacheEntry) { - var first = true; - var bindResult; - var canceled = false; - - autoDispose(bindable); - - var resolveWeakRef = function () { - if (canceled) { return; } - - var found = checkBindingToken(WinJS.Utilities._getWeakRefElement(ref), bindingId); - if (!found) { - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.elementNotFound, ref), "winjs binding", "info"); - if (bindResult) { - bindResult.cancel(); - } - } - return found; - } - var bindingAction = function (v) { - var found = resolveWeakRef(); - if (found) { - nestedSet(found, bind.destination, v); - } - if (first) { - pend.checkComplete(); - first = false; - } - }; - registerAutoDispose(bindable, resolveWeakRef); - - bindResult = bindWorker(bindable, bind.source, bindingAction); - if (bindResult) { - var cancel = bindResult.cancel; - bindResult.cancel = function () { - canceled = true; - return cancel.call(bindResult); - }; - if (cacheEntry) { - cacheEntry.bindings.push(function () { bindResult.cancel(); }); - } - } - - return bindResult; - } - - function sourceOneBinding(bind, ref, bindingId, source, e, pend, cacheEntry) { - var bindable; - if (source !== global) { - source = WinJS.Binding.as(source); - } - if (source._getObservable) { - bindable = source._getObservable(); - } - if (bindable) { - pend.count++; - // declarative binding must use a weak ref to the target element - // - return makeBinding(ref, bindingId, pend, bindable, bind, cacheEntry); - } - else { - nestedSet(e, bind.destination, getValue(source, bind.source)); - } - } - - function filterIdBinding(declBind, bindingStr) { - for (var bindIndex = declBind.length - 1; bindIndex >= 0; bindIndex--) { - var bind = declBind[bindIndex]; - var dest = bind.destination; - if (dest.length === 1 && dest[0] === "id") { - if (WinJS.validation) { - throw new WinJS.ErrorFromName("WinJS.Binding.IdBindingNotSupported", WinJS.Resources._formatString(strings.idBindingNotSupported, bindingStr)); - } - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.idBindingNotSupported, bindingStr), "winjs binding", "error"); - declBind.splice(bindIndex, 1); - } - } - return declBind; - } - - function calcBinding(bindingStr, bindingCache) { - if (bindingCache) { - var declBindCache = bindingCache.expressions[bindingStr]; - var declBind; - if (!declBindCache) { - declBind = filterIdBinding(WinJS.Binding._bindingParser(bindingStr, global), bindingStr); - bindingCache.expressions[bindingStr] = declBind; - } - if (!declBind) { - declBind = declBindCache; - } - return declBind; - } - else { - return filterIdBinding(WinJS.Binding._bindingParser(bindingStr, global), bindingStr); - } - } - - function declarativeBindImpl(rootElement, dataContext, skipRoot, bindingCache, defaultInitializer, c, e, p) { - msWriteProfilerMark("WinJS.Binding:processAll,StartTM"); - - var pend = { - count: 0, - checkComplete: function checkComplete() { - this.count--; - if (this.count === 0) { - msWriteProfilerMark("WinJS.Binding:processAll,StopTM"); - c(); - } - } - }; - var baseElement = (rootElement || document.body); - var selector = "[data-win-bind],[data-win-control]"; - var elements = baseElement.querySelectorAll(selector); - var neg; - if (!skipRoot && baseElement.getAttribute("data-win-bind")) { - neg = baseElement; - } - - pend.count++; - var source = dataContext || global; - - WinJS.Utilities._DOMWeakRefTable_fastLoadPath = true; - try { - var baseElementData = WinJS.Utilities.data(baseElement); - baseElementData.winBindings = baseElementData.winBindings || []; - - for (var i = (neg ? -1 : 0), l = elements.length; i < l; i++) { - var element = i < 0 ? neg : elements[i]; - - // If we run into a declarative control container (e.g. Binding.Template) we don't process its - // children, but we do give it an opportunity to process them later using this data context. - // - if (element.winControl && element.winControl.constructor && element.winControl.constructor.isDeclarativeControlContainer) { - i += element.querySelectorAll(selector).length; - - var idcc = element.winControl.constructor.isDeclarativeControlContainer; - if (typeof idcc === "function") { - idcc = requireSupportedForProcessing(idcc); - idcc(element.winControl, function (element) { - return WinJS.Binding.processAll(element, dataContext, false, bindingCache, defaultInitializer); - }); - } - } - - // In order to catch controls above we may have elements which don't have bindings, skip them - // - if (!element.hasAttribute("data-win-bind")) { - continue; - } - - var original = element.getAttribute("data-win-bind"); - var declBind = calcBinding(original, bindingCache); - - if (!declBind.implemented) { - for (var bindIndex = 0, bindLen = declBind.length; bindIndex < bindLen; bindIndex++) { - var bind = declBind[bindIndex]; - bind.initializer = bind.initializer || defaultInitializer; - if (bind.initializer) { - bind.implementation = initializerOneBinding; - } - else { - bind.implementation = sourceOneBinding; - } - } - declBind.implemented = true; - } - - pend.count++; - - var bindingId = setBindingToken(element); - var ref = optimizeBindingReferences ? bindingId : element.id; - - if (!ref) { - // We use our own counter here, as the IE "uniqueId" is only - // global to a document, which means that binding against - // unparented DOM elements would get duplicate IDs. - // - // The elements may not be parented at this point, but they - // will be parented by the time the binding action is fired. - // - element.id = ref = bindingId; - } - - WinJS.Utilities._createWeakRef(element, ref); - var elementData = WinJS.Utilities.data(element); - elementData.winBindings = null; - var cacheEntry; - if (bindingCache && bindingCache.elements) { - cacheEntry = bindingCache.elements[ref]; - if (!cacheEntry) { - bindingCache.elements[ref] = cacheEntry = { bindings: [] }; - } - } - - for (var bindIndex2 = 0, bindLen2 = declBind.length; bindIndex2 < bindLen2; bindIndex2++) { - var bind2 = declBind[bindIndex2]; - var cancel2 = bind2.implementation(bind2, ref, bindingId, source, element, pend, cacheEntry); - if (cancel2) { - elementData.winBindings = elementData.winBindings || []; - elementData.winBindings.push(cancel2); - baseElementData.winBindings.push(cancel2); - } - } - pend.count--; - } - } - finally { - WinJS.Utilities._DOMWeakRefTable_fastLoadPath = false; - } - pend.checkComplete(); - } - - function declarativeBind(rootElement, dataContext, skipRoot, bindingCache, defaultInitializer) { - /// - /// - /// Binds values from the specified data context to elements that are descendants of the specified root element - /// and have declarative binding attributes (data-win-bind). - /// - /// - /// The element at which to start traversing to find elements to bind to. If this parameter is omitted, the entire document - /// is searched. - /// - /// - /// The object to use for default data binding. - /// - /// - /// If true, the elements to be bound skip the specified root element and include only the children. - /// - /// - /// The cached binding data. - /// - /// - /// The binding initializer to use in the case that one is not specified in a binding expression. If not - /// provided the behavior is the same as WinJS.Binding.defaultBind. - /// - /// - /// A promise that completes when each item that contains binding declarations has - /// been processed and the update has started. - /// - /// - - return new WinJS.Promise(function (c, e, p) { - declarativeBindImpl(rootElement, dataContext, skipRoot, bindingCache, defaultInitializer, c, e, p); - }).then(null, function (e) { - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.errorInitializingBindings, e && e.message), "winjs binding", "error"); - return WinJS.Promise.wrapError(e); - }); - } - - function converter(convert) { - /// - /// - /// Creates a default binding initializer for binding between a source - /// property and a destination property with a provided converter function - /// that is executed on the value of the source property. - /// - /// - /// The conversion that operates over the result of the source property - /// to produce a value that is set to the destination property. - /// - /// - /// The binding initializer. - /// - /// - var userConverter = function (source, sourceProperties, dest, destProperties, initialValue) { - var bindingId = setBindingToken(dest); - var ref = optimizeBindingReferences ? bindingId : dest.id; - - if (!ref) { - dest.id = ref = bindingId; - } - - WinJS.Utilities._createWeakRef(dest, ref); - - var bindable; - if (source !== global) { - source = WinJS.Binding.as(source); - } - if (source._getObservable) { - bindable = source._getObservable(); - } - if (bindable) { - var counter = 0; - var workerResult = bindWorker(WinJS.Binding.as(source), sourceProperties, function (v) { - if (++counter === 1) { - if (v === initialValue) { - return; - } - } - var found = checkBindingToken(WinJS.Utilities._getWeakRefElement(ref), bindingId); - if (found) { - nestedSet(found, destProperties, convert(requireSupportedForProcessing(v))); - } - else if (workerResult) { - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.elementNotFound, ref), "winjs binding", "info"); - workerResult.cancel(); - } - }); - return workerResult; - } else { - var value = getValue(source, sourceProperties); - if (value !== initialValue) { - nestedSet(dest, destProperties, convert(value)); - } - } - }; - return markSupportedForProcessing(userConverter); - } - - function getValue(obj, path) { - if (obj !== global) { - obj = requireSupportedForProcessing(obj); - } - if (path) { - for (var i = 0, len = path.length; i < len && (obj !== null && obj !== undefined) ; i++) { - obj = requireSupportedForProcessing(obj[path[i]]); - } - } - return obj; - } - - function nestedSet(dest, destProperties, v) { - requireSupportedForProcessing(v); - dest = requireSupportedForProcessing(dest); - for (var i = 0, len = (destProperties.length - 1) ; i < len; i++) { - dest = requireSupportedForProcessing(dest[destProperties[i]]); - if (!dest) { - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.propertyDoesNotExist, destProperties[i], destProperties.join(".")), "winjs binding", "error"); - return; - } - else if (dest instanceof Node) { - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.nestedDOMElementBindingNotSupported, destProperties[i], destProperties.join(".")), "winjs binding", "error"); - return; - } - } - if (destProperties.length === 0) { - WinJS.log && WinJS.log(strings.cannotBindToThis, "winjs binding", "error"); - return; - } - var prop = destProperties[destProperties.length - 1]; - if (WinJS.log) { - if (dest[prop] === undefined) { - WinJS.log(WinJS.Resources._formatString(strings.creatingNewProperty, prop, destProperties.join(".")), "winjs binding", "warn"); - } - } - dest[prop] = v; - } - - function attributeSet(dest, destProperties, v) { - dest = requireSupportedForProcessing(dest); - if (!destProperties || destProperties.length !== 1 || !destProperties[0]) { - WinJS.log && WinJS.log(strings.attributeBindingSingleProperty, "winjs binding", "error"); - return; - } - dest.setAttribute(destProperties[0], v); - } - - function setAttribute(source, sourceProperties, dest, destProperties, initialValue) { - /// - /// - /// Creates a one-way binding between the source object and - /// an attribute on the destination element. - /// - /// - /// The source object. - /// - /// - /// The path on the source object to the source property. - /// - /// - /// The destination object (must be a DOM element). - /// - /// - /// The path on the destination object to the destination property, this must be a single name. - /// - /// - /// The known initial value of the target, if the source value is the same as this initial - /// value (using ===) then the target is not set the first time. - /// - /// - /// An object with a cancel method that is used to coalesce bindings. - /// - /// - - var bindingId = setBindingToken(dest); - var ref = optimizeBindingReferences ? bindingId : dest.id; - - if (!ref) { - dest.id = ref = bindingId; - } - - WinJS.Utilities._createWeakRef(dest, ref); - - var bindable; - if (source !== global) { - source = WinJS.Binding.as(source); - } - if (source._getObservable) { - bindable = source._getObservable(); - } - if (bindable) { - var counter = 0; - var workerResult = bindWorker(bindable, sourceProperties, function (v) { - if (++counter === 1) { - if (v === initialValue) { - return; - } - } - var found = checkBindingToken(WinJS.Utilities._getWeakRefElement(ref), bindingId); - if (found) { - attributeSet(found, destProperties, requireSupportedForProcessing(v)); - } - else if (workerResult) { - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.elementNotFound, ref), "winjs binding", "info"); - workerResult.cancel(); - } - }); - return workerResult; - } else { - var value = getValue(source, sourceProperties); - if (value !== initialValue) { - attributeSet(dest, destProperties, value); - } - } - } - function setAttributeOneTime(source, sourceProperties, dest, destProperties) { - /// - /// - /// Sets an attribute on the destination element to the value of the source property - /// - /// - /// The source object. - /// - /// - /// The path on the source object to the source property. - /// - /// - /// The destination object (must be a DOM element). - /// - /// - /// The path on the destination object to the destination property, this must be a single name. - /// - /// - return attributeSet(dest, destProperties, getValue(source, sourceProperties)); - } - - function addClassOneTime(source, sourceProperties, dest) { - /// - /// - /// Adds a class on the destination element to the value of the source property - /// - /// - /// The source object. - /// - /// - /// The path on the source object to the source property. - /// - /// - /// The destination object (must be a DOM element). - /// - /// - dest = requireSupportedForProcessing(dest); - dest.classList.add(getValue(source, sourceProperties)); - } - - var defaultBindImpl = converter(function defaultBind_passthrough(v) { return v; }); - - function defaultBind(source, sourceProperties, dest, destProperties, initialValue) { - /// - /// - /// Creates a one-way binding between the source object and - /// the destination object. - /// - /// - /// The source object. - /// - /// - /// The path on the source object to the source property. - /// - /// - /// The destination object. - /// - /// - /// The path on the destination object to the destination property. - /// - /// - /// The known initial value of the target, if the source value is the same as this initial - /// value (using ===) then the target is not set the first time. - /// - /// - /// An object with a cancel method that is used to coalesce bindings. - /// - /// - - return defaultBindImpl(source, sourceProperties, dest, destProperties, initialValue); - } - function bindWorker(bindable, sourceProperties, func) { - if (sourceProperties.length > 1) { - var root = {}; - var current = root; - for (var i = 0, l = sourceProperties.length - 1; i < l; i++) { - current = current[sourceProperties[i]] = {}; - } - current[sourceProperties[sourceProperties.length - 1]] = func; - - return WinJS.Binding.bind(bindable, root, true); - } - else if (sourceProperties.length === 1) { - bindable.bind(sourceProperties[0], func, true); - return { - cancel: function () { - bindable.unbind(sourceProperties[0], func); - this.cancel = noop; - } - }; - } - else { - // can't bind to object, so we just push it through - // - func(bindable); - } - } - function noop() { } - function oneTime(source, sourceProperties, dest, destProperties) { - /// - /// - /// Sets the destination property to the value of the source property. - /// - /// - /// The source object. - /// - /// - /// The path on the source object to the source property. - /// - /// - /// The destination object. - /// - /// - /// The path on the destination object to the destination property. - /// - /// - /// An object with a cancel method that is used to coalesce bindings. - /// - /// - nestedSet(dest, destProperties, getValue(source, sourceProperties)); - return { cancel: noop }; - } - - function initializer(customInitializer) { - /// - /// - /// Marks a custom initializer function as being compatible with declarative data binding. - /// - /// - /// The custom initializer to be marked as compatible with declarative data binding. - /// - /// - /// The input customInitializer. - /// - /// - return markSupportedForProcessing(customInitializer); - } - - WinJS.Namespace.define("WinJS.Binding", { - processAll: declarativeBind, - oneTime: initializer(oneTime), - defaultBind: initializer(defaultBind), - converter: converter, - initializer: initializer, - setAttribute: initializer(setAttribute), - setAttributeOneTime: initializer(setAttributeOneTime), - addClassOneTime: initializer(addClassOneTime), - }); - -})(WinJS, this); - -(function DOMWeakRefTableInit(global, undefined) { - "use strict"; - - if (WinJS.Utilities.hasWinRT && global.msSetWeakWinRTProperty && global.msGetWeakWinRTProperty) { - - var host = new Windows.Foundation.Uri("about://blank"); - - WinJS.Namespace.define("WinJS.Utilities", { - - _createWeakRef: function (element, id) { - msSetWeakWinRTProperty(host, id, element); - return id; - }, - - _getWeakRefElement: function (id) { - return msGetWeakWinRTProperty(host, id); - } - - }); - - return; - - } - - var U = WinJS.Utilities; - - // Defaults - var SWEEP_PERIOD = 500; - var TIMEOUT = 1000; - var table = {}; - var cleanupToken; - - function cleanup() { - if (U._DOMWeakRefTable_sweepPeriod === 0) { // If we're using post - cleanupToken = 0; // indicate that cleanup has run - } - var keys = Object.keys(table); - var time = Date.now() - U._DOMWeakRefTable_timeout; - var i, len; - for (i = 0, len = keys.length; i < len; i++) { - var id = keys[i]; - if (table[id].time < time) { - delete table[id]; - } - } - unscheduleCleanupIfNeeded(); - } - - function scheduleCleanupIfNeeded() { - if ((Debug.debuggerEnabled && U._DOMWeakRefTable_noTimeoutUnderDebugger) || cleanupToken) { - return; - } - var period = U._DOMWeakRefTable_sweepPeriod; - if (period === 0) { - setImmediate(cleanup); - cleanupToken = 1; - } else { - cleanupToken = setInterval(cleanup, U._DOMWeakRefTable_sweepPeriod); - } - } - - function unscheduleCleanupIfNeeded() { - if (Debug.debuggerEnabled && U._DOMWeakRefTable_noTimeoutUnderDebugger) { - return; - } - var period = U._DOMWeakRefTable_sweepPeriod; - if (period === 0) { // if we're using post - if (!cleanupToken) { // and there isn't already one scheduled - if (Object.keys(table).length !== 0) { // and there are items in the table - setImmediate(cleanup); // schedule another call to cleanup - cleanupToken = 1; // and protect against overscheduling - } - } - } else if (cleanupToken) { - if (Object.keys(table).length === 0) { - clearInterval(cleanupToken); - cleanupToken = 0; - } - } - } - - function createWeakRef(element, id) { - table[id] = { element: element, time: Date.now() }; - scheduleCleanupIfNeeded(); - return id; - } - - function getWeakRefElement(id) { - if (WinJS.Utilities._DOMWeakRefTable_fastLoadPath) { - var entry = table[id]; - if (entry) { - return entry.element; - } - else { - return document.getElementById(id); - } - } - else { - var element = document.getElementById(id); - if (element) { - delete table[id]; - unscheduleCleanupIfNeeded(); - } else { - var entry = table[id]; - if (entry) { - entry.time = Date.now(); - element = entry.element; - } - } - return element; - } - } - - WinJS.Namespace.define("WinJS.Utilities", { - _DOMWeakRefTable_noTimeoutUnderDebugger: true, - _DOMWeakRefTable_sweepPeriod: SWEEP_PERIOD, - _DOMWeakRefTable_timeout: TIMEOUT, - _DOMWeakRefTable_tableSize: { get: function () { return Object.keys(table).length; } }, - _DOMWeakRefTable_fastLoadPath: false, - _createWeakRef: createWeakRef, - _getWeakRefElement: getWeakRefElement - - }); - -}(this)); - -// WinJS.Binding.List -// -(function listInit(global, undefined) { - "use strict"; - - var strings = { - get sparseArrayNotSupported() { return WinJS.Resources._getWinJSString("base/sparseArrayNotSupported").value; }, - get illegalListLength() { return WinJS.Resources._getWinJSString("base/illegalListLength").value; }, - }; - - function copyargs(args) { - return Array.prototype.slice.call(args, 0); - } - - function cloneItem(item) { - return { - handle: item.handle, - key: item.key, - data: item.data, - groupKey: item.groupKey, - groupSize: item.groupSize, - firstItemKey: item.firstItemKey, - firstItemIndexHint: item.firstItemIndexHint - }; - } - - function asNumber(n) { - return n === undefined ? undefined : +n; - } - - var createEvent = WinJS.Utilities._createEventProperty; - - var emptyOptions = {}; - - // We need a stable sort in order to implement SortedListProjection because we want to be able to - // perform insertions in a predictable location s.t. if we were to apply another sorted projection - // over the same list (now containing the inserted data) the resulting order would be the same. - // - function mergeSort(m, sorter) { - var length = m.length; - if (length <= 1) { - return m; - } - var middle = (length / 2) >>> 0; - var left = mergeSort(m.slice(0, middle), sorter); - var right = mergeSort(m.slice(middle), sorter); - return merge(left, right, sorter); - } - function merge(left, right, sorter) { - var result = []; - while (left.length && right.length) { - var r = sorter(left[0], right[0]); - if (r <= 0) { - result.push(left.shift()); - } else { - result.push(right.shift()); - } - } - if (left.length) { - result.push.apply(result, left); - } - if (right.length) { - result.push.apply(result, right); - } - return result; - } - - // Private namespace used for local lazily init'd classes - var ns = WinJS.Namespace.defineWithParent(null, null, { - ListBase: WinJS.Namespace._lazy(function () { - var ListBase = WinJS.Class.define(null, { - _annotateWithIndex: function (item, index) { - var result = cloneItem(item); - result.index = index; - return result; - }, - - /// - /// The value identified by the specified key has been replaced with a different value. - /// - onitemchanged: createEvent("itemchanged"), - - /// - /// A new value has been inserted into the list. - /// - oniteminserted: createEvent("iteminserted"), - - /// - /// The value identified by the specified key has been moved from one index in the list to another index. - /// - onitemmoved: createEvent("itemmoved"), - - /// - /// The value identified by the specified key has been mutated. - /// - onitemmutated: createEvent("itemmutated"), - - /// - /// The value identified by the specified key has been removed from the list. - /// - onitemremoved: createEvent("itemremoved"), - - /// - /// The list has been refreshed. Any references to items in the list may be incorrect. - /// - onreload: createEvent("reload"), - - _notifyItemChanged: function (key, index, oldValue, newValue, oldItem, newItem) { - if (this._listeners && this._listeners.itemchanged) { - this.dispatchEvent("itemchanged", { key: key, index: index, oldValue: oldValue, newValue: newValue, oldItem: oldItem, newItem: newItem }); - } - }, - _notifyItemInserted: function (key, index, value) { - if (this._listeners && this._listeners.iteminserted) { - this.dispatchEvent("iteminserted", { key: key, index: index, value: value }); - } - var len = this.length; - if (len !== this._lastNotifyLength) { - this.notify("length", len, this._lastNotifyLength); - this._lastNotifyLength = len; - } - }, - _notifyItemMoved: function (key, oldIndex, newIndex, value) { - if (this._listeners && this._listeners.itemmoved) { - this.dispatchEvent("itemmoved", { key: key, oldIndex: oldIndex, newIndex: newIndex, value: value }); - } - }, - _notifyItemMutated: function (key, value, item) { - if (this._listeners && this._listeners.itemmutated) { - this.dispatchEvent("itemmutated", { key: key, value: value, item: item }); - } - }, - _notifyItemRemoved: function (key, index, value, item) { - if (this._listeners && this._listeners.itemremoved) { - this.dispatchEvent("itemremoved", { key: key, index: index, value: value, item: item }); - } - var len = this.length; - if (len !== this._lastNotifyLength) { - this.notify("length", len, this._lastNotifyLength); - this._lastNotifyLength = len; - } - }, - _notifyReload: function () { - if (this._listeners && this._listeners.reload) { - this.dispatchEvent("reload"); - } - if (len !== this._lastNotifyLength) { - var len = this.length; - this.notify("length", len, this._lastNotifyLength); - this._lastNotifyLength = len; - } - }, - - _normalizeIndex: function (index) { - index = asNumber(index); - return index < 0 ? this.length + index : index; - }, - - // ABSTRACT: length - - // Notifications: - // - // ABSTRACT: notifyMutated: function (index) - _notifyMutatedFromKey: function (key) { - var item = this.getItemFromKey(key); - this._notifyItemMutated(key, item.data, item); - }, - notifyReload: function () { - /// - /// - /// Forces the list to send a reload notification to any listeners. - /// - /// - this._notifyReload(); - }, - - // NOTE: performance can be improved in a number of the projections by overriding getAt/_getArray/_getFromKey/_getKey - // - getAt: function (index) { - /// - /// - /// Gets the value at the specified index. - /// - /// The index of the value to get. - /// The value at the specified index. - /// - index = asNumber(index); - var item = this.getItem(index); - return item && item.data; - }, - // returns [ data* ] - _getArray: function () { - var results = new Array(this.length); - for (var i = 0, len = this.length; i < len; i++) { - var item = this.getItem(i); - if (item) { - results[i] = item.data; - } - } - return results; - }, - // returns data - _getFromKey: function (key) { - var item = this.getItemFromKey(key); - return item && item.data; - }, - // ABSTRACT: getItem(index) - // ABSTRACT: getItemFromKey(key) - // returns string - _getKey: function (index) { - index = asNumber(index); - var item = this.getItem(index); - return item && item.key; - }, - - // Normal list non-modifiying operations - // - concat: function (item) { - /// - /// - /// Returns a new list consisting of a combination of two arrays. - /// - /// Additional items to add to the end of the list. - /// An array containing the concatenation of the list and any other supplied items. - /// - var a = this._getArray(); - return a.concat.apply(a, arguments); - }, - join: function (separator) { - /// - /// - /// Returns a string consisting of all the elements of a list separated by the specified separator string. - /// - /// A string used to separate the elements of a list. If this parameter is omitted, the list elements are separated with a comma. - /// The elements of a list separated by the specified separator string. - /// - return this._getArray().join(separator || ","); - }, - slice: function (begin, end) { - /// - /// - /// Extracts a section of a list and returns a new list. - /// - /// The index that specifies the beginning of the section. - /// The index that specifies the end of the section. - /// Returns a section of an array. - /// - return this._getArray().slice(begin, end); - }, - indexOf: function (searchElement, fromIndex) { - /// - /// - /// Gets the index of the first occurrence of the specified value in a list. - /// - /// The value to locate in the list. - /// The index at which to begin the search. If fromIndex is omitted, the search starts at index 0. - /// Index of the first occurrence of a value in a list or -1 if not found. - /// - fromIndex = asNumber(fromIndex); - fromIndex = Math.max(0, this._normalizeIndex(fromIndex) || 0); - for (var i = fromIndex, len = this.length; i < len; i++) { - var item = this.getItem(i); - if (item && item.data === searchElement) { - return i; - } - } - return -1; - }, - // ABSTRACT: indexOfKey(key) - lastIndexOf: function (searchElement, fromIndex) { - /// - /// - /// Gets the index of the last occurrence of the specified value in a list. - /// - /// The value to locate in the list. - /// The index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the list. - /// The index of the last occurrence of a value in a list, or -1 if not found. - /// - fromIndex = asNumber(fromIndex); - var length = this.length; - fromIndex = Math.min(this._normalizeIndex(fromIndex !== undefined ? fromIndex : length), length - 1); - var i; - for (i = fromIndex; i >= 0; i--) { - var item = this.getItem(i); - if (item && item.data === searchElement) { - return i; - } - } - return -1; - }, - - // - // Normal list projection operations - // - - every: function (callback, thisArg) { - /// - /// - /// Checks whether the specified callback function returns true for all elements in a list. - /// - /// A function that accepts up to three arguments. This function is called for each element in the list until it returns false or the end of the list is reached. - /// An object to which the this keyword can refer in the callback function. If thisArg is omitted, undefined is used. - /// True if the callback returns true for all elements in the list. - /// - return this._getArray().every(callback, thisArg); - }, - filter: function (callback, thisArg) { - /// - /// - /// Returns the elements of a list that meet the condition specified in a callback function. - /// - /// A function that accepts up to three arguments. The function is called for each element in the list. - /// An object to which the this keyword can refer in the callback function. If thisArg is omitted, undefined is used. - /// An array containing the elements that meet the condition specified in the callback function. - /// - return this._getArray().filter(callback, thisArg); - }, - forEach: function (callback, thisArg) { - /// - /// - /// Calls the specified callback function for each element in a list. - /// - /// A function that accepts up to three arguments. The function is called for each element in the list. - /// An object to which the this keyword can refer in the callback function. If thisArg is omitted, undefined is used. - /// - this._getArray().forEach(callback, thisArg); - }, - map: function (callback, thisArg) { - /// - /// - /// Calls the specified callback function on each element of a list, and returns an array that contains the results. - /// - /// A function that accepts up to three arguments. The function is called for each element in the list. - /// An object to which the this keyword can refer in the callback function. If thisArg is omitted, undefined is used. - /// An array containing the result of calling the callback function on each element in the list. - /// - return this._getArray().map(callback, thisArg); - }, - some: function (callback, thisArg) { - /// - /// - /// Checks whether the specified callback function returns true for any element of a list. - /// - /// A function that accepts up to three arguments. The function is called for each element in the list until it returns true, or until the end of the list. - /// An object to which the this keyword can refer in the callback function. If thisArg is omitted, undefined is used. - /// True if callback returns true for any element in the list. - /// - return this._getArray().some(callback, thisArg); - }, - reduce: function (callback, initialValue) { - /// - /// - /// Accumulates a single result by calling the specified callback function for all elements in a list. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. - /// - /// A function that accepts up to four arguments. The function is called for each element in the list. - /// If initialValue is specified, it is used as the value with which to start the accumulation. The first call to the function provides this value as an argument instead of a list value. - /// The return value from the last call to the callback function. - /// - if (arguments.length > 1) { - return this._getArray().reduce(callback, initialValue); - } - return this._getArray().reduce(callback); - }, - reduceRight: function (callback, initialValue) { - /// - /// - /// Accumulates a single result by calling the specified callback function for all elements in a list, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. - /// - /// A function that accepts up to four arguments. The function is called for each element in the list. - /// If initialValue is specified, it is used as the value with which to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of a list value. - /// The return value from last call to callback function. - /// - if (arguments.length > 1) { - return this._getArray().reduceRight(callback, initialValue); - } - return this._getArray().reduceRight(callback); - }, - - // - // Live Projections - if you want the lifetime of the returned projections to - // be shorter than that of the list object on which they are based you have - // to remember to call .dispose() on them when done. - // - - createFiltered: function (predicate) { - /// - /// - /// Creates a live filtered projection over this list. As the list changes, the filtered projection reacts to those changes and may also change. - /// - /// A function that accepts a single argument. The createFiltered function calls the callback with each element in the list. If the function returns true, that element will be included in the filtered list. - /// Filtered projection over the list. - /// - return new ns.FilteredListProjection(this, predicate); - }, - createGrouped: function (groupKey, groupData, groupSorter) { - /// - /// - /// Creates a live grouped projection over this list. As the list changes, the grouped projection reacts to those changes and may also change. The grouped projection sorts all the elements of the list to be in group-contiguous order. The grouped projection also contains a .groups property which is a WinJS.Binding.List representing the groups that were found in the list. - /// - /// A function that accepts a single argument. The function is called with each element in the list, the function should return a string representing the group containing the element. - /// A function that accepts a single argument. The function is called on an element in the list for each group. It should return the value that should be set as the data of the .groups list element for this group. - /// A function that accepts two arguments. The function is called with the key of groups found in the list. It must return one of the following numeric values: negative if the first argument is less than the second, zero if the two arguments are equivalent, positive if the first argument is greater than the second. If omitted, the groups are sorted in ascending, ASCII character order. - /// A grouped projection over the list. - /// - return new ns.GroupedSortedListProjection(this, groupKey, groupData, groupSorter); - }, - createSorted: function (sorter) { - /// - /// - /// Creates a live sorted projection over this list. As the list changes, the sorted projection reacts to those changes and may also change. - /// - /// A function that accepts two arguments. The function is called with elements in the list. It must return one of the following numeric values: negative if the first argument is less than the second, zero if the two arguments are equivalent, positive if the first argument is greater than the second. - /// A sorted projection over the list. - /// - return new ns.SortedListProjection(this, sorter); - }, - - dataSource: { - get: function () { - return (this._dataSource = this._dataSource || new WinJS.Binding._BindingListDataSource(this)); - } - }, - - }, { - supportedForProcessing: false, - }) - WinJS.Class.mix(ListBase, WinJS.Binding.observableMixin); - WinJS.Class.mix(ListBase, WinJS.Utilities.eventMixin); - return ListBase; - }), - - ListBaseWithMutators: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(ns.ListBase, null, { - // ABSTRACT: setAt(index, value) - - // Normal list modifying operations - // - // returns data from tail of list - pop: function () { - /// - /// - /// Removes the last element from a list and returns it. - /// - /// Last element from the list. - /// - return this.splice(-1, 1)[0]; - }, - push: function (value) { - /// - /// - /// Appends new element(s) to a list, and returns the new length of the list. - /// - /// The element to insert at the end of the list. - /// The new length of the list. - /// - if (arguments.length === 1) { - this.splice(this.length, 0, value); - return this.length; - } else { - var args = copyargs(arguments); - args.splice(0, 0, this.length, 0); - this.splice.apply(this, args); - return this.length; - } - }, - // returns data from head of list - shift: function () { - /// - /// - /// Removes the first element from a list and returns it. - /// - /// First element from the list. - /// - return this.splice(0, 1)[0]; - }, - unshift: function (value) { - /// - /// - /// Appends new element(s) to a list, and returns the new length of the list. - /// - /// The element to insert at the start of the list. - /// The new length of the list. - /// - if (arguments.length === 1) { - this.splice(0, 0, value); - } else { - var args = copyargs(arguments); - // Wow, this looks weird. Insert 0, 0 at the beginning of splice. - args.splice(0, 0, 0, 0); - this.splice.apply(this, args); - } - return this.length; - } - - // ABSTRACT: splice(index, howMany, values...) - // ABSTRACT: _spliceFromKey(key, howMany, values...) - }, { - supportedForProcessing: false, - }) - }), - - ListProjection: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(ns.ListBaseWithMutators, null, { - _list: null, - _myListeners: null, - - _addListListener: function (name, func) { - var l = { name: name, handler: func.bind(this) }; - this._myListeners = this._myListeners || []; - this._myListeners.push(l); - this._list.addEventListener(name, l.handler); - }, - - // ABSTRACT: _listReload() - - dispose: function () { - /// - /// - /// Disconnects this WinJS.Binding.List projection from its underlying WinJS.Binding.List. This is important only if they have different lifetimes. - /// - /// - var list = this._list; - - var listeners = this._myListeners; - this._myListeners = []; - - for (var i = 0, len = listeners.length; i < len; i++) { - var l = listeners[i]; - list.removeEventListener(l.name, l.handler); - } - - // Set this to an empty list and tell everyone that they need to reload to avoid - // consumers null-refing on an empty list. - this._list = new WinJS.Binding.List(); - this._listReload(); - }, - - getItemFromKey: function (key) { - /// - /// - /// Gets a key/data pair for the specified key. - /// - /// The key of the value to retrieve. - /// An object with .key and .data properties. - /// - return this._list.getItemFromKey(key); - }, - - move: function (index, newIndex) { - /// - /// - /// Moves the value at index to position newIndex. - /// - /// The original index of the value. - /// The index of the value after the move. - /// - index = asNumber(index); - newIndex = asNumber(newIndex); - if (index === newIndex || index < 0 || newIndex < 0 || index >= this.length || newIndex >= this.length) { - return; - } - index = this._list.indexOfKey(this._getKey(index)); - newIndex = this._list.indexOfKey(this._getKey(newIndex)); - this._list.move(index, newIndex); - }, - - _notifyMutatedFromKey: function (key) { - this._list._notifyMutatedFromKey(key); - }, - - splice: function (index, howMany, item) { - /// - /// - /// Removes elements from a list and, if necessary, inserts new elements in their place, returning the deleted elements. - /// - /// The zero-based location in the list from which to start removing elements. - /// The number of elements to remove. - /// The elements to insert into the list in place of the deleted elements. - /// The deleted elements. - /// - index = asNumber(index); - index = Math.max(0, this._normalizeIndex(index)); - var args = copyargs(arguments); - if (index === this.length) { - // In order to getAt the tail right we just push on to the end of the underlying list - args[0] = this._list.length; - return this._list.splice.apply(this._list, args); - } else { - args[0] = this._getKey(index); - return this._spliceFromKey.apply(this, args); - } - }, - - _setAtKey: function (key, value) { - this._list._setAtKey(key, value); - }, - - }, { - supportedForProcessing: false, - }) - }), - - FilteredListProjection: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(ns.ListProjection, function (list, filter) { - this._list = list; - this._addListListener("itemchanged", this._listItemChanged); - this._addListListener("iteminserted", this._listItemInserted); - this._addListListener("itemmutated", this._listItemMutated); - this._addListListener("itemmoved", this._listItemMoved); - this._addListListener("itemremoved", this._listItemRemoved); - this._addListListener("reload", this._listReload); - this._filter = filter; - this._initFilteredKeys(); - }, { - _filter: null, - _filteredKeys: null, - _initFilteredKeys: function () { - var filter = this._filter; - var list = this._list; - var keys = []; - for (var i = 0, len = list.length; i < len; i++) { - var item = list.getItem(i); - if (item && filter(item.data)) { - keys.push(item.key); - } - } - this._filteredKeys = keys; - }, - - _findInsertionPosition: function (key, index) { - // find the spot to insert this by identifing the previous element in the list - var filter = this._filter; - var previousKey; - while ((--index) >= 0) { - var item = this._list.getItem(index); - if (item && filter(item.data)) { - previousKey = item.key; - break; - } - } - var filteredKeys = this._filteredKeys; - var filteredIndex = previousKey ? (filteredKeys.indexOf(previousKey) + 1) : 0; - return filteredIndex; - }, - - _listItemChanged: function (event) { - var key = event.detail.key; - var index = event.detail.index; - var oldValue = event.detail.oldValue; - var newValue = event.detail.newValue; - var oldItem = event.detail.oldItem; - var newItem = event.detail.newItem; - var filter = this._filter; - var oldInFilter = filter(oldValue); - var newInFilter = filter(newValue); - if (oldInFilter && newInFilter) { - var filteredKeys = this._filteredKeys; - var filteredIndex = filteredKeys.indexOf(key); - this._notifyItemChanged(key, filteredIndex, oldValue, newValue, oldItem, newItem); - } else if (oldInFilter && !newInFilter) { - this._listItemRemoved({ detail: { key: key, index: index, value: oldValue, item: oldItem } }); - } else if (!oldInFilter && newInFilter) { - this._listItemInserted({ detail: { key: key, index: index, value: newValue } }); - } - }, - _listItemInserted: function (event) { - var key = event.detail.key; - var index = event.detail.index; - var value = event.detail.value; - var filter = this._filter; - if (filter(value)) { - var filteredIndex = this._findInsertionPosition(key, index); - var filteredKeys = this._filteredKeys; - filteredKeys.splice(filteredIndex, 0, key); - this._notifyItemInserted(key, filteredIndex, value); - } - }, - _listItemMoved: function (event) { - var key = event.detail.key; - var newIndex = event.detail.newIndex; - var value = event.detail.value; - var filteredKeys = this._filteredKeys; - var oldFilteredIndex = filteredKeys.indexOf(key); - if (oldFilteredIndex !== -1) { - filteredKeys.splice(oldFilteredIndex, 1); - var newFilteredIndex = this._findInsertionPosition(key, newIndex); - filteredKeys.splice(newFilteredIndex, 0, key); - this._notifyItemMoved(key, oldFilteredIndex, newFilteredIndex, value); - } - }, - _listItemMutated: function (event) { - var key = event.detail.key; - var value = event.detail.value; - var item = event.detail.item; - var filter = this._filter; - var filteredKeys = this._filteredKeys; - var filteredIndex = filteredKeys.indexOf(key); - var oldInFilter = filteredIndex !== -1; - var newInFilter = filter(value); - if (oldInFilter && newInFilter) { - this._notifyItemMutated(key, value, item); - } else if (oldInFilter && !newInFilter) { - filteredKeys.splice(filteredIndex, 1); - this._notifyItemRemoved(key, filteredIndex, value, item); - } else if (!oldInFilter && newInFilter) { - this._listItemInserted({ detail: { key: key, index: this._list.indexOfKey(key), value: value } }); - } - }, - _listItemRemoved: function (event) { - var key = event.detail.key; - var value = event.detail.value; - var item = event.detail.item; - var filteredKeys = this._filteredKeys; - var filteredIndex = filteredKeys.indexOf(key); - if (filteredIndex !== -1) { - filteredKeys.splice(filteredIndex, 1); - this._notifyItemRemoved(key, filteredIndex, value, item); - } - }, - _listReload: function () { - this._initFilteredKeys(); - this._notifyReload(); - }, - - /// Returns an integer value one higher than the highest element defined in an list. - length: { - get: function () { return this._filteredKeys.length; }, - set: function (value) { - if (typeof value === "number" && value >= 0) { - var current = this.length; - if (current > value) { - this.splice(value, current - value); - } - } else { - throw new WinJS.ErrorFromName("WinJS.Binding.List.IllegalLength", strings.illegalListLength); - } - } - }, - - getItem: function (index) { - /// - /// - /// Returns a key/data pair for the specified index. - /// - /// The index of the value to retrieve. - /// An object with .key and .data properties. - /// - index = asNumber(index); - return this.getItemFromKey(this._filteredKeys[index]); - }, - - indexOfKey: function (key) { - /// - /// - /// Returns the index of the first occurrence of a key in a list. - /// - /// The key to locate in the list. - /// The index of the first occurrence of a key in a list, or -1 if not found. - /// - return this._filteredKeys.indexOf(key); - }, - - notifyMutated: function (index) { - /// - /// - /// Forces the list to send a itemmutated notification to any listeners for the value at the specified index. - /// - /// The index of the value that was mutated. - /// - index = asNumber(index); - return this._notifyMutatedFromKey(this._filteredKeys[index]); - }, - - setAt: function (index, value) { - /// - /// - /// Replaces the value at the specified index with a new value. - /// - /// The index of the value that was replaced. - /// The new value. - /// - index = asNumber(index); - this._setAtKey(this._filteredKeys[index], value); - }, - - // returns [ data* ] of removed items - _spliceFromKey: function (key, howMany) { - // first add in all the new items if we have any, this should serve to push key to the right - if (arguments.length > 2) { - var args = copyargs(arguments); - args[1] = 0; // howMany - this._list._spliceFromKey.apply(this._list, args); - } - // now we can remove anything that needs to be removed, since they are not necessarially contiguous - // in the underlying list we remove them one by one. - var result = []; - if (howMany) { - var keysToRemove = []; - var filteredKeys = this._filteredKeys; - var filteredKeyIndex = filteredKeys.indexOf(key); - for (var i = filteredKeyIndex, len = filteredKeys.length; i < len && (i - filteredKeyIndex) < howMany; i++) { - var key = filteredKeys[i]; - keysToRemove.push(key); - } - var that = this; - keysToRemove.forEach(function (key) { - result.push(that._list._spliceFromKey(key, 1)[0]); - }); - } - return result; - } - }, { - supportedForProcessing: false, - }) - }), - - SortedListProjection: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(ns.ListProjection, function (list, sortFunction) { - this._list = list; - this._addListListener("itemchanged", this._listItemChanged); - this._addListListener("iteminserted", this._listItemInserted); - this._addListListener("itemmoved", this._listItemMoved); - this._addListListener("itemmutated", this._listItemMutated); - this._addListListener("itemremoved", this._listItemRemoved); - this._addListListener("reload", this._listReload); - this._sortFunction = sortFunction; - this._initSortedKeys(); - }, { - _sortFunction: null, - _sortedKeys: null, - _initSortedKeys: function () { - var list = this._list; - var keys = []; - for (var i = 0, len = list.length; i < len; i++) { - var item = list.getItem(i); - if (item) { - keys[i] = item.key; - } - } - var sorter = this._sortFunction; - var sorted = mergeSort(keys, function (l, r) { - l = list.getItemFromKey(l).data; - r = list.getItemFromKey(r).data; - return sorter(l, r); - }); - this._sortedKeys = sorted; - }, - - _findInsertionPos: function (key, index, value, startingMin, startingMax) { - var sorter = this._sortFunction; - var sortedKeys = this._sortedKeys; - var min = Math.max(0, startingMin || -1); - var max = Math.min(sortedKeys.length, startingMax || Number.MAX_VALUE); - var mid = min; - while (min <= max) { - mid = ((min + max) / 2) >>> 0; - var sortedKey = sortedKeys[mid]; - if (!sortedKey) { - break; - } - var sortedItem = this.getItemFromKey(sortedKey); - var r = sorter(sortedItem.data, value); - if (r < 0) { - min = mid + 1; - } else if (r === 0) { - return this._findStableInsertionPos(key, index, min, max, mid, value); - } else { - max = mid - 1; - } - } - return min; - }, - _findBeginningOfGroup: function (mid, sorter, list, sortedKeys, value) { - // we made it to the beginning of the list without finding something - // that sorts equal to this value, insert this key at the beginning of - // this section of keys. - var min = 0; - var max = mid; - while (min <= max) { - mid = ((min + max) / 2) >>> 0; - var sortedKey = sortedKeys[mid]; - var sortedItem = list.getItemFromKey(sortedKey); - var r = sorter(sortedItem.data, value); - if (r < 0) { - min = mid + 1; - } else { - max = mid - 1; - } - } - return min; - }, - _findEndOfGroup: function (mid, sorter, list, sortedKeys, value) { - // we made it ot the end of the list without finding something that sorts - // equal to this value, insert this key at the end of this section of - // keys. - var min = mid; - var max = sortedKeys.length; - while (min <= max) { - mid = ((min + max) / 2) >>> 0; - var sortedKey = sortedKeys[mid]; - if (!sortedKey) { - return sortedKeys.length; - } - var sortedItem = list.getItemFromKey(sortedKey); - var r = sorter(sortedItem.data, value); - if (r <= 0) { - min = mid + 1; - } else { - max = mid - 1; - } - } - return min; - }, - _findStableInsertionPos: function (key, index, min, max, mid, value) { - var list = this._list; - var length = list.length; - var sorter = this._sortFunction; - var sortedKeys = this._sortedKeys; - if (index < (length / 2)) { - for (var i = index - 1; i >= 0; i--) { - var item = list.getItem(i); - if (sorter(item.data, value) === 0) { - // we have found the next item to the left, insert this item to - // the right of that. - if ((length - min) > max) { - return sortedKeys.indexOf(item.key, min) + 1; - } else { - return sortedKeys.lastIndexOf(item.key, max) + 1; - } - } - } - return this._findBeginningOfGroup(mid, sorter, list, sortedKeys, value); - } else { - for (var i = index + 1; i < length; i++) { - var item = list.getItem(i); - if (sorter(item.data, value) === 0) { - // we have found the next item to the right, insert this item - // to the left of that. - if ((length - min) > max) { - return sortedKeys.indexOf(item.key, min); - } else { - return sortedKeys.lastIndexOf(item.key, max); - } - } - } - return this._findEndOfGroup(mid, sorter, list, sortedKeys, value); - } - }, - - _listItemChanged: function (event) { - var key = event.detail.key; - var newValue = event.detail.newValue; - var oldValue = event.detail.oldValue; - var sortFunction = this._sortFunction; - if (sortFunction(oldValue, newValue) === 0) { - var sortedIndex = this.indexOfKey(key); - this._notifyItemChanged(key, sortedIndex, oldValue, newValue, event.detail.oldItem, event.detail.newItem); - } else { - this._listItemRemoved({ detail: { key: key, index: event.detail.index, value: event.detail.oldValue, item: event.detail.oldItem } }); - this._listItemInserted({ detail: { key: key, index: event.detail.index, value: event.detail.newValue } }); - } - }, - _listItemInserted: function (event, knownMin, knownMax) { - var key = event.detail.key; - var index = event.detail.index; - var value = event.detail.value; - var sortedIndex = this._findInsertionPos(key, index, value, knownMin, knownMax); - this._sortedKeys.splice(sortedIndex, 0, key); - this._notifyItemInserted(key, sortedIndex, value); - }, - _listItemMoved: function (event, knownMin, knownMax) { - var key = event.detail.key; - var newIndex = event.detail.newIndex; - var value = event.detail.value; - var sortedKeys = this._sortedKeys; - var oldSortedIndex = sortedKeys.indexOf(key, knownMin); - sortedKeys.splice(oldSortedIndex, 1); - var newSortedIndex = this._findInsertionPos(key, newIndex, value, knownMin, knownMax); - sortedKeys.splice(newSortedIndex, 0, key); - if (newSortedIndex !== oldSortedIndex) { - // The move in the underlying list resulted in a move in the sorted list - // - this._notifyItemMoved(key, oldSortedIndex, newSortedIndex, value); - } else { - // The move in the underlying list resulted in no change in the sorted list - // - } - }, - _listItemMutated: function (event) { - var key = event.detail.key; - var value = event.detail.value; - var item = event.detail.item; - var index = this._list.indexOfKey(key); - var sortedIndex = this._sortedKeys.indexOf(key); - this._sortedKeys.splice(sortedIndex, 1); - var targetIndex = this._findInsertionPos(key, index, value); - this._sortedKeys.splice(sortedIndex, 0, key); - if (sortedIndex === targetIndex) { - this._notifyItemMutated(key, value, item); - return; - } - this._listItemRemoved({ detail: { key: key, index: index, value: value, item: item } }); - this._listItemInserted({ detail: { key: key, index: index, value: value } }); - }, - _listItemRemoved: function (event, knownMin) { - var key = event.detail.key; - var value = event.detail.value; - var item = event.detail.item; - var sortedKeys = this._sortedKeys; - var sortedIndex = sortedKeys.indexOf(key, knownMin); - sortedKeys.splice(sortedIndex, 1); - this._notifyItemRemoved(key, sortedIndex, value, item); - }, - _listReload: function () { - this._initSortedKeys(); - this._notifyReload(); - }, - - /// Gets or sets the length of the list. Returns an integer value one higher than the highest element defined in a list. - length: { - get: function () { return this._sortedKeys.length; }, - set: function (value) { - if (typeof value === "number" && value >= 0) { - var current = this.length; - if (current > value) { - this.splice(value, current - value); - } - } else { - throw new WinJS.ErrorFromName("WinJS.Binding.List.IllegalLength", strings.illegalListLength); - } - } - }, - - getItem: function (index) { - /// - /// - /// Returns a key/data pair for the specified index. - /// - /// The index of the value to retrieve. - /// An object with .key and .data properties. - /// - index = asNumber(index); - return this.getItemFromKey(this._sortedKeys[index]); - }, - - indexOfKey: function (key) { - /// - /// - /// Returns the index of the first occurrence of a key. - /// - /// The key to locate in the list. - /// The index of the first occurrence of a key in a list, or -1 if not found. - /// - return this._sortedKeys.indexOf(key); - }, - - notifyMutated: function (index) { - /// - /// - /// Forces the list to send a itemmutated notification to any listeners for the value at the specified index. - /// - /// The index of the value that was mutated. - /// - index = asNumber(index); - this._notifyMutatedFromKey(this._sortedKeys[index]); - }, - - setAt: function (index, value) { - /// - /// - /// Replaces the value at the specified index with a new value. - /// - /// The index of the value that was replaced. - /// The new value. - /// - index = asNumber(index); - this._setAtKey(this._sortedKeys[index], value); - }, - - // returns [ data* ] of removed items - _spliceFromKey: function (key, howMany) { - // first add in all the new items if we have any, this should serve to push key to the right - if (arguments.length > 2) { - var args = copyargs(arguments); - args[1] = 0; // howMany - this._list._spliceFromKey.apply(this._list, args); - } - // now we can remove anything that needs to be removed, since they are not necessarially contiguous - // in the underlying list we remove them one by one. - var result = []; - if (howMany) { - var keysToRemove = []; - var sortedKeys = this._sortedKeys; - var sortedKeyIndex = sortedKeys.indexOf(key); - for (var i = sortedKeyIndex, len = sortedKeys.length; i < len && (i - sortedKeyIndex) < howMany; i++) { - keysToRemove.push(sortedKeys[i]); - } - var that = this; - keysToRemove.forEach(function (key) { - result.push(that._list._spliceFromKey(key, 1)[0]); - }); - } - return result; - } - }, { - supportedForProcessing: false, - }) - }), - - // This projection sorts the underlying list by group key and within a group - // respects the position of the item in the underlying list. It is built on top - // of the SortedListProjection and has an intimate contract with - // GroupsListProjection. - // - GroupedSortedListProjection: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(ns.SortedListProjection, function (list, groupKeyOf, groupDataOf, groupSorter) { - this._list = list; - this._addListListener("itemchanged", this._listGroupedItemChanged); - this._addListListener("iteminserted", this._listGroupedItemInserted); - this._addListListener("itemmoved", this._listGroupedItemMoved); - this._addListListener("itemmutated", this._listGroupedItemMutated); - this._addListListener("itemremoved", this._listGroupedItemRemoved); - this._addListListener("reload", this._listReload); - this._sortFunction = function (l, r) { - l = groupKeyOf(l); - r = groupKeyOf(r); - if (groupSorter) { - return groupSorter(l, r); - } else { - return l < r ? -1 : l === r ? 0 : 1; - } - }; - this._groupKeyOf = groupKeyOf; - this._groupDataOf = groupDataOf; - this._initSortedKeys(); - this._initGroupedItems(); - }, { - _groupKeyOf: null, - _groupDataOf: null, - - _groupedItems: null, - _initGroupedItems: function () { - var groupedItems = {}; - var list = this._list; - var groupKeyOf = this._groupKeyOf; - for (var i = 0, len = list.length; i < len; i++) { - var item = cloneItem(list.getItem(i)); - item.groupKey = groupKeyOf(item.data); - groupedItems[item.key] = item; - } - this._groupedItems = groupedItems; - }, - - _groupsProjection: null, - - _listGroupedItemChanged: function (event) { - var key = event.detail.key; - var oldValue = event.detail.oldValue; - var newValue = event.detail.newValue; - var groupedItems = this._groupedItems; - var oldGroupedItem = groupedItems[key]; - var newGroupedItem = cloneItem(oldGroupedItem); - newGroupedItem.data = newValue; - newGroupedItem.groupKey = this._groupKeyOf(newValue); - groupedItems[key] = newGroupedItem; - var index; - if (oldGroupedItem.groupKey === newGroupedItem.groupKey) { - index = this.indexOfKey(key); - this._notifyItemChanged(key, index, oldValue, newValue, oldGroupedItem, newGroupedItem); - } else { - index = event.detail.index; - this._listItemChanged({ detail: { key: key, index: index, oldValue: oldValue, newValue: newValue, oldItem: oldGroupedItem, newItem: newGroupedItem } }); - } - }, - _listGroupedItemInserted: function (event) { - var key = event.detail.key; - var value = event.detail.value; - var groupKey = this._groupKeyOf(value); - this._groupedItems[key] = { - handle: key, - key: key, - data: value, - groupKey: groupKey - }; - var groupMin, groupMax; - if (this._groupsProjection) { - var groupItem = this._groupsProjection._groupItems[groupKey]; - if (groupItem) { - groupMin = groupItem.firstItemIndexHint; - groupMax = groupMin + groupItem.groupSize; - } - } - this._listItemInserted(event, groupMin, groupMax); - }, - _listGroupedItemMoved: function (event) { - var groupMin, groupMax; - var groupKey = this._groupedItems[event.detail.key].groupKey; - if (this._groupsProjection) { - var groupItem = this._groupsProjection._groupItems[groupKey]; - groupMin = groupItem.firstItemIndexHint; - groupMax = groupMin + groupItem.groupSize; - } - this._listItemMoved(event, groupMin, groupMax); - }, - _listGroupedItemMutated: function (event) { - var key = event.detail.key; - var value = event.detail.value; - var groupedItems = this._groupedItems; - var oldGroupedItem = groupedItems[key]; - var groupKey = this._groupKeyOf(value); - if (oldGroupedItem.groupKey === groupKey) { - this._notifyItemMutated(key, value, oldGroupedItem); - } else { - var newGroupedItem = cloneItem(oldGroupedItem); - newGroupedItem.groupKey = groupKey; - groupedItems[key] = newGroupedItem; - var index = this._list.indexOfKey(key); - this._listItemRemoved({ detail: { key: key, index: index, value: value, item: oldGroupedItem } }); - this._listItemInserted({ detail: { key: key, index: index, value: value } }); - } - }, - _listGroupedItemRemoved: function (event) { - var key = event.detail.key; - var index = event.detail.index; - var value = event.detail.value; - var groupedItems = this._groupedItems; - var groupedItem = groupedItems[key]; - delete groupedItems[key]; - var groupMin, groupMax; - if (this._groupsProjection) { - var groupItem = this._groupsProjection._groupItems[groupedItem.groupKey]; - groupMin = groupItem.firstItemIndexHint; - groupMax = groupMin + groupItem.groupSize; - } - this._listItemRemoved({ detail: { key: key, index: index, value: value, item: groupedItem } }, groupMin, groupMax); - }, - - // override _listReload - _listReload: function () { - this._initGroupedItems(); - ns.SortedListProjection.prototype._listReload.call(this); - }, - - /// Gets a WinJS.Binding.List, which is a projection of the groups that were identified in this list. - groups: { - get: function () { - if (this._groupsProjection === null) { - this._groupsProjection = new ns.GroupsListProjection(this, this._groupKeyOf, this._groupDataOf); - } - return this._groupsProjection; - } - }, - - // We have to implement this because we keep our own set of items so that we can - // tag them with groupKey. - // - getItemFromKey: function (key) { - /// - /// - /// Gets a key/data pair for the specified item key. - /// - /// The key of the value to retrieve. - /// An object with .key and .data properties. - /// - return this._groupedItems[key]; - } - }, { - supportedForProcessing: false, - }) - }), - - // This is really an implementation detail of GroupedSortedListProjection and takes a - // dependency on its internals and implementation details. - // - GroupsListProjection: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(ns.ListBase, function (list, groupKeyOf, groupDataOf) { - this._list = list; - this._addListListener("itemchanged", this._listItemChanged); - this._addListListener("iteminserted", this._listItemInserted); - this._addListListener("itemmoved", this._listItemMoved); - // itemmutated is handled by the GroupedSortedListProjection because if the item - // changes groups it turns into a remove/insert. - this._addListListener("itemremoved", this._listItemRemoved); - this._addListListener("reload", this._listReload); - this._groupKeyOf = groupKeyOf; - this._groupDataOf = groupDataOf; - this._initGroupKeysAndItems(); - }, { - _list: null, - - _addListListener: function (name, func) { - // interestingly, since GroupsListProjection has the same lifetime as the GroupedSortedListProjection - // we don't have to worry about cleaning up the cycle here. - this._list.addEventListener(name, func.bind(this)); - }, - - _groupDataOf: null, - _groupKeyOf: null, - _groupOf: function (item) { - return this.getItemFromKey(this._groupKeyOf(item.data)); - }, - - _groupKeys: null, - _groupItems: null, - _initGroupKeysAndItems: function () { - var groupDataOf = this._groupDataOf; - var list = this._list; - var groupItems = {}; - var groupKeys = []; - var currentGroupKey = null; - var currentGroupItem = null; - var groupCount; - for (var i = 0, len = list.length; i < len; i++) { - var item = list.getItem(i); - var groupKey = item.groupKey; - if (groupKey !== currentGroupKey) { - // new group - if (currentGroupItem) { - currentGroupItem.groupSize = groupCount; - } - groupCount = 1; - currentGroupKey = groupKey; - currentGroupItem = { - handle: groupKey, - key: groupKey, - data: groupDataOf(item.data), - firstItemKey: item.key, - firstItemIndexHint: i - }; - groupItems[groupKey] = currentGroupItem; - groupKeys.push(groupKey); - } else { - // existing group - groupCount++; - } - } - if (currentGroupItem) { - currentGroupItem.groupSize = groupCount; - } - this._groupKeys = groupKeys; - this._groupItems = groupItems; - }, - - _listItemChanged: function (event) { - // itemchanged is only interesting if the item that changed is the first item - // of a group at which point we need to regenerate the group item. - // - var key = event.detail.key; - var index = event.detail.index; - var newValue = event.detail.newValue; - var list = this._list; - var groupKey = list.getItemFromKey(key).groupKey; - var groupItems = this._groupItems; - var groupItem = groupItems[groupKey]; - if (groupItem.firstItemIndexHint === index) { - var newGroupItem = cloneItem(groupItem); - newGroupItem.data = this._groupDataOf(newValue); - newGroupItem.firstItemKey = key; - groupItems[groupKey] = newGroupItem; - this._notifyItemChanged(groupKey, this._groupKeys.indexOf(groupKey), groupItem.data, newGroupItem.data, groupItem, newGroupItem); - } - }, - _listItemInserted: function (event) { - // iteminserted is only interesting if this is a new group, or is the first - // item of the group at which point the group data is regenerated. It will - // however always result in a +1 to all the following firstItemIndexHints - // - var key = event.detail.key; - var index = event.detail.index; - var value = event.detail.value; - var list = this._list; - var groupKey = list.getItemFromKey(key).groupKey; - var groupItems = this._groupItems; - var groupKeys = this._groupKeys; - var groupItem = groupItems[groupKey]; - var groupIndex; - var oldGroupItem, newGroupItem; - - var i, len; - if (!groupItem) { - // we have a new group, add it - for (i = 0, len = groupKeys.length; i < len; i++) { - groupItem = groupItems[groupKeys[i]]; - if (groupItem.firstItemIndexHint >= index) { - break; - } - } - groupIndex = i; - groupItem = { - handle: groupKey, - key: groupKey, - data: this._groupDataOf(value), - groupSize: 1, - firstItemKey: key, - firstItemIndexHint: index - }; - groupKeys.splice(groupIndex, 0, groupKey); - groupItems[groupKey] = groupItem; - this._notifyItemInserted(groupKey, groupIndex, groupItem.data); - } else { - oldGroupItem = groupItem; - newGroupItem = cloneItem(oldGroupItem); - newGroupItem.groupSize++; - if (oldGroupItem.firstItemIndexHint === index) { - newGroupItem.groupData = this._groupDataOf(value); - newGroupItem.firstItemKey = key; - newGroupItem.firstItemIndexHint = index; - } - groupItems[groupKey] = newGroupItem; - groupIndex = groupKeys.indexOf(groupKey); - this._notifyItemChanged(groupKey, groupIndex, oldGroupItem.data, newGroupItem.data, oldGroupItem, newGroupItem); - } - // update the firstItemIndexHint on following groups - for (i = groupIndex + 1, len = groupKeys.length; i < len; i++) { - oldGroupItem = groupItems[groupKeys[i]]; - newGroupItem = cloneItem(oldGroupItem); - newGroupItem.firstItemIndexHint++; - groupItems[newGroupItem.key] = newGroupItem; - this._notifyItemChanged(newGroupItem.key, i, oldGroupItem.data, newGroupItem.data, oldGroupItem, newGroupItem); - } - }, - _listItemMoved: function (event) { - // itemmoved is not important to grouping unless the move resulted in a new - // first item in the group at which point we will regenerate the group data - // - var key = event.detail.key; - var oldIndex = event.detail.oldIndex; - var newIndex = event.detail.newIndex; - var list = this._list; - var groupKey = list.getItemFromKey(key).groupKey; - var groupItems = this._groupItems; - var groupItem = groupItems[groupKey]; - if (groupItem.firstItemIndexHint === newIndex || - groupItem.firstItemIndexHint === oldIndex) { - // the first item of the group has changed, update it. - var item = list.getItem(groupItem.firstItemIndexHint); - var newGroupItem = cloneItem(groupItem); - newGroupItem.data = this._groupDataOf(item.data); - newGroupItem.firstItemKey = item.key; - groupItems[groupKey] = newGroupItem; - this._notifyItemChanged(groupKey, this._groupKeys.indexOf(groupKey), groupItem.data, newGroupItem.data, groupItem, newGroupItem); - } - }, - _listItemRemoved: function (event) { - // itemremoved is only interesting if the group was of size 1 or was the - // first item of the group at which point the group data is regenerated. - // It will however always result in a -1 to all of the following - // firstItemIndexHints. - // - var index = event.detail.index; - var item = event.detail.item; - var groupItems = this._groupItems; - var groupKeys = this._groupKeys; - // since the value is no longer in the list we can't ask for its item and - // get the group key from there. - var groupKey = item.groupKey; - var groupItem = groupItems[groupKey]; - var groupIndex = groupKeys.indexOf(groupKey); - var oldGroupItem, newGroupItem; - - if (groupItem.groupSize === 1) { - groupKeys.splice(groupIndex, 1); - delete groupItems[groupKey]; - this._notifyItemRemoved(groupKey, groupIndex, groupItem.data, groupItem); - // after removing the group we need to decrement the index because it is used - // for modifying subsequent group firstItemIndexHint's - groupIndex--; - } else { - oldGroupItem = groupItem; - newGroupItem = cloneItem(oldGroupItem); - newGroupItem.groupSize--; - if (oldGroupItem.firstItemIndexHint === index) { - // find the next group item, it will be at the same index as the old - // first group item. - var newFirstItem = this._list.getItem(index); - newGroupItem.data = this._groupDataOf(newFirstItem.data); - newGroupItem.firstItemKey = newFirstItem.key; - } - groupItems[groupKey] = newGroupItem; - this._notifyItemChanged(groupKey, groupIndex, oldGroupItem.data, newGroupItem.data, oldGroupItem, newGroupItem); - } - for (var i = groupIndex + 1, len = groupKeys.length; i < len; i++) { - oldGroupItem = groupItems[groupKeys[i]]; - newGroupItem = cloneItem(oldGroupItem); - newGroupItem.firstItemIndexHint--; - groupItems[newGroupItem.key] = newGroupItem; - this._notifyItemChanged(newGroupItem.key, i, oldGroupItem.data, newGroupItem.data, oldGroupItem, newGroupItem); - } - }, - _listReload: function () { - this._initGroupKeysAndItems(); - this._notifyReload(); - }, - - /// Gets the length of the list. Returns an integer value one higher than the highest element defined in a list. - length: { - get: function () { return this._groupKeys.length; } - }, - - getItem: function (index) { - /// - /// - /// Gets a key/data pair for the specified index . - /// - /// The index of the value to retrieve. - /// An object with .key and .data properties. - /// - index = asNumber(index); - return this._groupItems[this._groupKeys[index]]; - }, - getItemFromKey: function (key) { - /// - /// - /// Gets a key/data pair for the specified key. - /// - /// The key of the value to retrieve. - /// An object with .key and .data properties. - /// - return this._groupItems[key]; - }, - - indexOfKey: function (key) { - /// - /// - /// Returns the index of the first occurrence of a key in a list. - /// - /// The key to locate in the list. - /// The index of the first occurrence of a key in a list, or -1 if not found. - /// - return this._groupKeys.indexOf(key); - } - }, { - supportedForProcessing: false, - }) - }), - }); - - WinJS.Namespace.define("WinJS.Binding", { - List: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(ns.ListBaseWithMutators, function (list, options) { - /// - /// - /// Creates a WinJS.Binding.List object. - /// - /// The array containing the elements to initalize the list. - /// If options.binding is true, the list will contain the result of calling WinJS.Binding.as() on the element values. If options.proxy is true, the list specified as the first parameter is used as the storage for the WinJS.Binding.List. This option should be used with care because uncoordinated edits to the data storage will result in errors. - /// The newly-constructed WinJS.Binding.List instance. - /// - - this._currentKey = 0; - this._keys = null; - this._keyMap = {}; - - // options: - // - binding: binding.as on items - // - proxy: proxy over input data - // - options = options || emptyOptions; - this._proxy = options.proxy; - this._binding = options.binding; - if (this._proxy) { - if (Object.keys(list).length !== list.length) { - throw new WinJS.ErrorFromName("WinJS.Binding.List.NotSupported", strings.sparseArrayNotSupported); - } - this._data = list; - this._currentKey = list.length; - } else if (list) { - var keyDataMap = this._keyMap; - var pos = 0, i = 0; - for (var len = list.length; i < len; i++) { - if (i in list) { - var item = list[i]; - if (this._binding) { - item = WinJS.Binding.as(item); - } - var key = pos.toString(); - pos++; - keyDataMap[key] = { handle: key, key: key, data: item }; - } - } - if (pos !== i) { - this._initializeKeys(); - } - this._currentKey = pos; - } - }, { - _currentKey: 0, - - _keys: null, - _keyMap: null, - - _modifyingData: 0, - - _initializeKeys: function () { - if (this._keys) { - return; - } - - var keys = []; - if (this._data) { - // If this list is a proxy over the data then we will have been lazily initializing - // the entries in the list, however the 1:1 mapping between index and key is about - // to go away so this is our last chance to pull the items out of the data. - // - var keyMap = this._keyMap; - var data = this._data; - for (var i = 0, len = data.length; i < len; i++) { - if (i in data) { - var key = i.toString(); - keys[i] = key; - if (!(key in keyMap)) { - var item = data[i]; - if (this._binding) { - item = WinJS.Binding.as(item); - } - keyMap[key] = { handle: key, key: key, data: item }; - } - } - } - } else { - // In the case where List owns the data we will have created the keyMap at initialization - // time and can use that to harvest all the keys into the _keys list. - // - Object.keys(this._keyMap).forEach(function (key) { - keys[key >>> 0] = key; - }); - } - this._keys = keys; - }, - _lazyPopulateEntry: function (index) { - if (this._data && index in this._data) { - var item = this._data[index]; - if (this._binding) { - item = WinJS.Binding.as(item); - } - var key = index.toString(); - var entry = { handle: key, key: key, data: item }; - this._keyMap[entry.key] = entry; - return entry; - } - }, - - _assignKey: function () { - return (++this._currentKey).toString(); - }, - - /// Gets or sets the length of the list, which is an integer value one higher than the highest element defined in the list. - length: { - get: function () { - // If we are proxying use the underlying list's length - // If we have already allocated keys use that length - // If we haven't allocated keys then we can use _currentKey which was set at initialization time - // to be length of the input list. - if (this._data) { - return this._data.length; - } else if (this._keys) { - return this._keys.length; - } else { - return this._currentKey; - } - }, - set: function (value) { - if (typeof value === "number" && value >= 0) { - this._initializeKeys(); - var current = this.length; - if (current > value) { - this.splice(value, current - value); - } else { - // We don't support setting lengths to longer in order to have sparse behavior - value = current; - } - if (this._data) { - this._modifyingData++; - try { - this._data.length = value; - } finally { - this._modifyingData--; - } - } - if (this._keys) { - this._keys.length = value; - } - } else { - throw new WinJS.ErrorFromName("WinJS.Binding.List.IllegalLength", strings.illegalListLength); - } - } - }, - - getItem: function (index) { - /// - /// - /// Gets a key/data pair for the specified list index. - /// - /// The index of value to retrieve. - /// An object with .key and .data properties. - /// - var entry; - var key; - index = asNumber(index); - if (this._keys) { - key = this._keys[index]; - entry = key && this._keyMap[key]; - } else { - key = index.toString(); - entry = this._keyMap[key] || this._lazyPopulateEntry(index); - } - return entry; - }, - getItemFromKey: function (key) { - /// - /// - /// Gets a key/data pair for the list item key specified. - /// - /// The key of the value to retrieve. - /// An object with .key and .data properties. - /// - var entry; - // if we have a keys list we know to go through the keyMap, or if we are not - // proxying through _data we also know to go through the keyMap. - if (this._keys || !this._data) { - entry = this._keyMap[key]; - } else { - entry = this.getItem(key >>> 0); - } - return entry; - }, - - indexOfKey: function (key) { - /// - /// - /// Gets the index of the first occurrence of a key in a list. - /// - /// The key to locate in the list. - /// The index of the first occurrence of a key in a list, or -1 if not found. - /// - var index = -1; - if (this._keys) { - index = this._keys.indexOf(key); - } else { - var t = key >>> 0; - if (t < this._currentKey) { - index = t; - } - } - return index; - }, - - move: function (index, newIndex) { - /// - /// - /// Moves the value at index to the specified position. - /// - /// The original index of the value. - /// The index of the value after the move. - /// - index = asNumber(index); - newIndex = asNumber(newIndex); - this._initializeKeys(); - if (index === newIndex || index < 0 || newIndex < 0 || index >= this.length || newIndex >= this.length) { - return; - } - if (this._data) { - this._modifyingData++; - try { - var item = this._data.splice(index, 1)[0]; - this._data.splice(newIndex, 0, item); - } finally { - this._modifyingData--; - } - } - var key = this._keys.splice(index, 1)[0]; - this._keys.splice(newIndex, 0, key); - this._notifyItemMoved(key, index, newIndex, this.getItemFromKey(key).data); - }, - - notifyMutated: function (index) { - /// - /// - /// Forces the list to send a itemmutated notification to any listeners for the value at the specified index. - /// - /// The index of the value that was mutated. - /// - index = asNumber(index); - var key = this._keys ? this._keys[index] : index.toString(); - this._notifyMutatedFromKey(key); - }, - - setAt: function (index, newValue) { - /// - /// - /// Replaces the value at the specified index with a new value. - /// - /// The index of the value that was replaced. - /// The new value. - /// - index = asNumber(index); - this._initializeKeys(); - var length = this.length; - if (index === length) { - this.push(newValue); - } else if (index < length) { - if (this._data) { - this._modifyingData++; - try { - this._data[index] = newValue; - } finally { - this._modifyingData--; - } - } - if (this._binding) { - newValue = WinJS.Binding.as(newValue); - } - if (index in this._keys) { - var key = this._keys[index]; - var oldEntry = this._keyMap[key]; - var newEntry = cloneItem(oldEntry); - newEntry.data = newValue; - this._keyMap[key] = newEntry; - this._notifyItemChanged(key, index, oldEntry.data, newValue, oldEntry, newEntry); - } - } - }, - - _setAtKey: function (key, newValue) { - this.setAt(this.indexOfKey(key), newValue); - }, - - // These are the traditional Array mutators, they don't result in projections. In particular - // having both sort and sorted is a bit confusing. It may be the case that we want to eliminate - // the various array helpers outside of the standard push/pop,shift/unshift,splice,get*,setAt - // and then offer up the specific projections: filter, sorted, grouped. Anything else can be - // obtained through _getArray(). - // - reverse: function () { - /// - /// - /// Returns a list with the elements reversed. This method reverses the elements of a list object in place. It does not create a new list object during execution. - /// - /// The reversed list. - /// - this._initializeKeys(); - if (this._data) { - this._modifyingData++; - try { - this._data.reverse(); - } finally { - this._modifyingData--; - } - } - this._keys.reverse(); - this._notifyReload(); - return this; - }, - sort: function (sortFunction) { - /// - /// - /// Returns a list with the elements sorted. This method sorts the elements of a list object in place. It does not create a new list object during execution. - /// - /// The function used to determine the order of the elements. If omitted, the elements are sorted in ascending, ASCII character order. - /// The sorted list. - /// - this._initializeKeys(); - if (this._data) { - this._modifyingData++; - try { - this._data.sort(sortFunction); - } finally { - this._modifyingData--; - } - } - var that = this; - this._keys.sort(function (l, r) { - l = that._keyMap[l]; - r = that._keyMap[r]; - if (sortFunction) { - return sortFunction(l.data, r.data); - } - l = (l && l.data || "").toString(); - r = (l && r.data || "").toString(); - return l < r ? -1 : l === r ? 0 : 1; - }); - this._notifyReload(); - return this; - }, - - pop: function () { - /// - /// - /// Removes the last element from a list and returns it. - /// - /// Last element from the list. - /// - if (this.length === 0) { - return; - } - this._initializeKeys(); - var key = this._keys.pop(); - var entry = this._keyMap[key]; - var data = entry && entry.data; - if (this._data) { - this._modifyingData++; - try { - this._data.pop(); - } finally { - this._modifyingData--; - } - } - delete this._keyMap[key]; - this._notifyItemRemoved(key, this._keys.length, data, entry); - return data; - }, - - push: function (value) { - /// - /// - /// Appends new element(s) to a list, and returns the new length of the list. - /// - /// The element to insert at the end of the list. - /// The new length of the list. - /// - this._initializeKeys(); - var length = arguments.length; - for (var i = 0; i < length; i++) { - var item = arguments[i]; - if (this._binding) { - item = WinJS.Binding.as(item); - } - var key = this._assignKey(); - this._keys.push(key); - if (this._data) { - this._modifyingData++; - try { - this._data.push(arguments[i]) - } finally { - this._modifyingData--; - } - } - this._keyMap[key] = { handle: key, key: key, data: item }; - this._notifyItemInserted(key, this._keys.length - 1, item); - } - return this.length; - }, - - shift: function () { - /// - /// - /// Removes the first element from a list and returns it. - /// - /// First element from the list. - /// - if (this.length === 0) { - return; - } - - this._initializeKeys(); - var key = this._keys.shift(); - var entry = this._keyMap[key]; - var data = entry && entry.data; - if (this._data) { - this._modifyingData++; - try { - this._data.shift(); - } finally { - this._modifyingData--; - } - } - delete this._keyMap[key]; - this._notifyItemRemoved(key, 0, data, entry); - return data; - }, - - unshift: function (value) { - /// - /// - /// Appends new element(s) to a list, and returns the new length of the list. - /// - /// The element to insert at the start of the list. - /// The new length of the list. - /// - this._initializeKeys(); - var length = arguments.length; - for (var i = length - 1; i >= 0; i--) { - var item = arguments[i]; - if (this._binding) { - item = WinJS.Binding.as(item); - } - var key = this._assignKey(); - this._keys.unshift(key); - if (this._data) { - this._modifyingData++; - try { - this._data.unshift(arguments[i]) - } finally { - this._modifyingData--; - } - } - this._keyMap[key] = { handle: key, key: key, data: item }; - this._notifyItemInserted(key, 0, item); - } - return this.length; - }, - - splice: function (index, howMany, item) { - /// - /// - /// Removes elements from a list and, if necessary, inserts new elements in their place, returning the deleted elements. - /// - /// The zero-based location in the list from which to start removing elements. - /// The number of elements to remove. - /// The elements to insert into the list in place of the deleted elements. - /// The deleted elements. - /// - index = asNumber(index); - this._initializeKeys(); - index = Math.max(0, this._normalizeIndex(index)); - howMany = Math.max(0, Math.min(howMany || 0, this.length - index)); - var result = []; - while (howMany) { - var key = this._keys[index]; - var entry = this._keyMap[key]; - var data = entry && entry.data; - result.push(data); - this._keys.splice(index, 1); - if (this._data) { - this._modifyingData++; - try { - this._data.splice(index, 1); - } finally { - this._modifyingData--; - } - } - delete this._keyMap[key]; - this._notifyItemRemoved(key, index, data, entry); - --howMany; - } - if (arguments.length > 2) { - for (var i = 2, len = arguments.length; i < len; i++) { - var additionalItem = arguments[i]; - if (this._binding) { - additionalItem = WinJS.Binding.as(additionalItem); - } - var pos = Math.min(index + i - 2, this.length); - var newKey = this._assignKey(); - this._keys.splice(pos, 0, newKey); - if (this._data) { - this._modifyingData++; - try { - this._data.splice(pos, 0, arguments[i]); - } finally { - this._modifyingData--; - } - } - this._keyMap[newKey] = { handle: newKey, key: newKey, data: additionalItem }; - this._notifyItemInserted(newKey, pos, additionalItem); - } - } - return result; - }, - // returns [ data* ] of removed items - _spliceFromKey: function (key, howMany) { - this._initializeKeys(); - var args = copyargs(arguments); - args[0] = this._keys.indexOf(key); - return this.splice.apply(this, args); - } - }, { - supportedForProcessing: false, - }); - }) - }); - - -}(this)); - - -(function templateCompilerInit(global) { - "use strict"; - - // not supported in WebWorker - if (!global.document) { - return; - } - - var strings = { - get attributeBindingSingleProperty() { return WinJS.Resources._getWinJSString("base/attributeBindingSingleProperty").value; }, - get cannotBindToThis() { return WinJS.Resources._getWinJSString("base/cannotBindToThis").value; }, - get idBindingNotSupported() { return WinJS.Resources._getWinJSString("base/idBindingNotSupported").value; }, - }; - - WinJS.Namespace.define("WinJS.Binding", { - _TemplateCompiler: WinJS.Namespace._lazy(function () { - - var Signal = WinJS._Signal; - var Promise = WinJS.Promise; - var cancelBlocker = Promise._cancelBlocker; - - // Eagerly bind to stuff that will be needed by the compiler - // - var init_defaultBind = WinJS.Binding.defaultBind; - var init_oneTime = WinJS.Binding.oneTime; - var init_setAttribute = WinJS.Binding.setAttribute; - var init_setAttributeOneTime = WinJS.Binding.setAttributeOneTime; - var init_addClassOneTime = WinJS.Binding.addClassOneTime; - var binding_as = WinJS.Binding.as; - var promise_as = WinJS.Promise.as; - var supportedForProcessing = WinJS.Utilities.supportedForProcessing; - var requireSupportedForProcessing = WinJS.Utilities.requireSupportedForProcessing; - var insertAdjacentHTMLUnsafe = WinJS.Utilities.insertAdjacentHTMLUnsafe; - var utilities_data = WinJS.Utilities.data; - var markDisposable = WinJS.Utilities.markDisposable; - var ui_processAll = WinJS.UI.processAll; - var binding_processAll = WinJS.Binding.processAll; - var options_parser = WinJS.UI._optionsParser; - var CallExpression = WinJS.UI._CallExpression; - var IdentifierExpression = WinJS.UI._IdentifierExpression; - var binding_parser = WinJS.Binding._bindingParser2; - var scopedSelect = WinJS.UI.scopedSelect; - - // Runtime helper functions - // - function disposeInstance(container, workPromise, renderCompletePromise) { - var bindings = WinJS.Utilities.data(container).bindTokens; - if (bindings) { - bindings.forEach(function (binding) { - if (binding && binding.cancel) { - binding.cancel(); - } - }); - } - if (workPromise) { - workPromise.cancel(); - } - if (renderCompletePromise) { - renderCompletePromise.cancel(); - } - } - function delayedBindingProcessing(data, defaultInitializer) { - return function (element) { - return WinJS.Binding.processAll(element, data, false, null, defaultInitializer); - } - } - - function targetSecurityCheck(value) { - value = requireSupportedForProcessing(value); - return value instanceof Node ? null : value; - } - - // Compiler formatting functions - // - var identifierRegEx = /^[A-Za-z]\w*$/; - var identifierCharacterRegEx = /[^A-Za-z\w$]/g; - var encodeHtmlRegEx = /[&<>'"]/g; - var encodeHtmlEscapeMap = { - "&": "&", - "<": "<", - ">": ">", - "'": "'", - '"': """ - }; - var formatRegEx = /({{)|(}})|{(\w+)}|({)|(})/g; - var semiColonOnlyLineRegEx = /^\s*;\s*$/; - var capitalRegEx = /[A-Z]/g; - - function format(string, parts) { - var multiline = string.indexOf("\n") !== -1; - var args = arguments; - // - // This allows you to format a string like: "hello{there}you{0} {{encased in curlies}}" and will - // replace the holes {there} and {0} while turning the {{ and }} into single curlies. - // - // If the replacement is a number then it is inferred to be off of arguments, otherwise it is - // a member on parts. - // - // If the replacement is a multiline string and the hole is indented then the entirety of the - // replacement will have the same indentation as the hole. - // - var result = string.replace(formatRegEx, function (unused, left, right, part, illegalLeft, illegalRight, replacementIndex) { - if (illegalLeft || illegalRight) { - throw new WinJS.ErrorFromName( - "Format:MalformedInputString", - "Did you forget to escape a: " + (illegalLeft || illegalRight) + " at: " + replacementIndex); - } - if (left) { return "{"; } - if (right) { return "}"; } - var result; - var index = +part; - if (index === +index) { - result = args[index + 1]; - } else { - result = parts[part]; - } - if (result === undefined) { - throw new WinJS.ErrorFromName( - "Format:MissingPart", - "Missing part '" + part + "'" - ); - } - if (multiline) { - var pos = replacementIndex; - while (pos > 0 && string[--pos] === " ") { /* empty */ } - if (pos >= 0 && string[pos] === "\n") { - result = indent(replacementIndex - pos - 1, result); - } - } - return result; - }); - return result; - } - function indent(numberOfSpaces, multilineStringToBeIndented) { - var indent = ""; - for (var i = 0; i < numberOfSpaces; i++) { indent += " "; } - return multilineStringToBeIndented.split("\n").map(function (line, index) { return index ? indent + line : line; }).join("\n"); - } - function trim(s) { - return s.trim(); - } - function statements(array) { - return array.join(";\n"); - } - function declarationList(array) { - return array.join(", ") || "empty"; - } - function identifierAccessExpression(parts) { - return parts.map(function (part) { - // If this can be a member access optimize to that instead of a string lookup - // - if (part.match(identifierRegEx)) { return "." + part; } - if (+part === part) { return format("[{0}]", part); } - return format("[{0}]", literal(part)); - }).join(""); - } - function nullableFilteredIdentifierAccessExpression(initial, parts, temporary, filter) { - // - // generates: "(t = initial) && filter(t = t.p0) && filter(t = t.p1) && t" - // - // There are a number of contexts in which we will be derefernceing developer provided - // identifier access expressions, in those case we don't know whether or not the target - // property exists or in fact if anything exists along the path. - // - // In order to provide 'correct' behavior we dereference conditionally on whether - // we have a non-null value. This results in returning undefined unless the entire - // path is defined. - // - // In these cases we also want to filter the result for security purposes. - // - var parts = parts.map(function (part) { - // If this can be a member access optimize to that instead of a string lookup - // - if (part.match(identifierRegEx)) { return "." + part; } - if (+part === part) { part = +part; } - return brackets(literal(part)); - }).map(function (part) { - return format("{filter}({temp} = {temp}{part})", { - filter: filter, - temp: temporary, - part: part - }); - }); - parts.unshift(parens(assignment(temporary, initial))); - parts.push(temporary); - return parens(parts.join(" && ")); - } - function literal(instance) { - return JSON.stringify(instance); - } - function newArray(N) { - return N ? "new Array(" + (+N) + ")" : "[]"; - } - function assignment(target, source) { - return "" + target + " = " + source; - } - function parens(expression) { - return "(" + expression + ")"; - } - function brackets(expression) { - return "[" + expression + "]"; - } - function propertyName(name) { - if (name.match(identifierRegEx)) { return name; } - if (+name === name) { return +name; } - return literal(name); - } - function htmlEscape(str) { - str = "" + str; - return str.replace(encodeHtmlRegEx, function (m) { - return encodeHtmlEscapeMap[m] || " "; - }); - } - function createIdentifier(prefix, count, suffix) { - if (suffix) { - return new String("" + prefix + count + "_" + suffix); - } else { - return new String("" + prefix + count); - } - } - function multiline(str) { - return str.replace(/\\n/g, "\\n\\\n"); - } - - // Compiler helper functions - // - function keys(object) { - return Object.keys(object); - } - function values(object) { - return Object.keys(object).map(function (key) { return object[key]; }); - } - function merge(a, b) { - return mergeAll([a, b]); - } - function mergeAll(list) { - var o = {}; - for (var i = 0, len = list.length; i < len; i++) { - var part = list[i]; - var keys = Object.keys(part); - for (var j = 0, len2 = keys.length; j < len2; j++) { - var key = keys[j]; - o[key] = part[key]; - } - } - return o; - } - function globalLookup(parts) { - return parts.reduce( - function (current, name) { - if (current) { - return requireSupportedForProcessing(current[name]); - } - return null; - }, - global - ); - } - function visit(node, key, pre, post) { - var children = node.children; - if (children) { - var keys = Object.keys(children); - (key && pre) && pre(node, key, keys.length); - for (var i = 0, len = keys.length; i < len; i++) { - var childKey = keys[i]; - var child = children[childKey]; - visit(child, childKey, pre, post); - } - (key && post) && post(node, key, Object.keys(children).length); - } else { - (key && pre) && pre(node, key, 0); - (key && post) && post(node, key, 0); - } - } - - // Compiler helper types - // - var TreeCSE = WinJS.Class.define(function (compiler, name, kind, accessExpression, filter) { - - var that = this; - this.compiler = compiler; - this.kind = kind; - this.base = new String(name); - this.tree = { - children: {}, - parent: this.base, - reference: function () { return that.base; } - }; - this.accessExpression = accessExpression; - this.filter = filter || ""; - - }, { - - createPathExpression: function (path, name) { - - if (path.length) { - var that = this; - var tail = path.reduce( - function (node, part) { - node.children = node.children || {}; - node.children[part] = node.children[part] || { parent: node }; - return node.children[part]; - }, - this.tree - ); - tail.name = tail.name || that.compiler.defineInstance( - that.kind, - name || "", - function () { - return that.accessExpression( - /*l*/tail.parent.name ? tail.parent.name : tail.parent.reference(), - /*r*/path.slice(-1)[0], - /*root*/tail.parent.parent === that.base, - /*filter*/that.filter, - /*last*/true - ); - } - ); - return tail.name; - } else { - return this.base; - } - - }, - - lower: function () { - - var that = this; - var aggregatedName = []; - var reference = function (node, name, last) { - return that.accessExpression( - /*l*/node.parent.name ? node.parent.name : node.parent.reference(), - /*r*/name, - /*root*/node.parent.parent === that.base, - /*filter*/that.filter, - /*last*/last - ); - }; - - // Ensure that all shared internal nodes have names and that all nodes - // know who they reference - // - visit(this.tree, "", - function pre(node, key, childCount) { - aggregatedName.push(key); - - if (childCount > 1) { - node.name = node.name || that.compiler.defineInstance( - that.kind, - aggregatedName.join("_"), - reference.bind(null, node, key, true) - ); - node.reference = function () { return node.name; }; - } else if (childCount === 1) { - node.reference = reference.bind(null, node, key); - } - }, - function post(node, key, childCount) { - aggregatedName.pop(); - } - ); - - }, - - deadNodeElimination: function () { - - // Kill all dead nodes from the tree - // - visit(this.tree, "", null, function post(node, key, childCount) { - if (!node.name || node.name.dead) { - if (childCount === 0) { - if (node.parent && node.parent.children) { - delete node.parent.children[key]; - } - } - } - }); - - }, - - definitions: function () { - - var nodes = []; - - // Gather the nodes in a depth first ordering, any node which has a name - // needs to have a definition generated - // - visit(this.tree, "", function pre(node, key) { - if (node.name) { - nodes.push(node); - } - }); - - return nodes.map(function (n) { return n.name.definition(); }); - - }, - - }); - - var InstanceKind = { - "capture": "capture", - "temporary": "temporary", - "variable": "variable", - "data": "data", - "global": "global", - }; - var InstanceKindPrefixes = { - "capture": "c", - "temporary": "t", - "variable": "iv", - "data": "d", - "global": "g", - }; - - var StaticKind = { - "import": "import", - "variable": "variable", - }; - var StaticKindPrefixes = { - "import": "i", - "variable": "sv", - }; - - var BindingKind = { - "tree": "tree", - "text": "text", - "initializer": "initializer", - "template": "template", - "error": "error", - }; - - var TextBindingKind = { - "attribute": "attribute", - "booleanAttribute": "booleanAttribute", - "inlineStyle": "inlineStyle", - "textContent": "textContent", - }; - - // Constants - // - var IMPORTS_ARG_NAME = "imports"; - - var Stage = { - initial: 0, - analyze: 1, - optimze: 2, - lower: 3, - compile: 4, - link: 5, - done: 6, - }; - - // Compiler - // - var TemplateCompiler = WinJS.Class.define(function (templateElement, options) { - this._stage = Stage.initial; - this._staticVariables = {}; - this._staticVariablesCount = 0; - this._instanceVariables = {}; - this._instanceVariablesCount = {}; - this._debugBreak = options.debugBreakOnRender; - this._defaultInitializer = requireSupportedForProcessing(options.defaultInitializer || init_defaultBind); - this._optimizeTextBindings = !options.disableTextBindingOptimization; - this._templateElement = templateElement; - this._templateContent = document.createElement(templateElement.tagName); - this._extractChild = options.extractChild || false; - this._controls = null; - this._bindings = null; - this._bindTokens = null; - this._textBindingPrefix = null; - this._textBindingId = 0; - this._suffix = []; - this._htmlProcessors = []; - this._profilerMarkIdentifier = options.profilerMarkIdentifier; - this._captureCSE = new TreeCSE(this, "container", InstanceKind.capture, this.generateElementCaptureAccess.bind(this)); - this._dataCSE = new TreeCSE(this, "data", InstanceKind.data, this.generateNormalAccess.bind(this), this.importSafe("dataSecurityCheck", requireSupportedForProcessing)); - this._globalCSE = new TreeCSE(this, this.importSafe("global", global), InstanceKind.global, this.generateNormalAccess.bind(this), this.importSafe("globalSecurityCheck", requireSupportedForProcessing)); - - // Clone the template content and import it into its own HTML document for further processing - WinJS.UI.Fragments.renderCopy(this._templateElement, this._templateContent); - - // If we are extracting the first child we only bother compiling the one child - if (this._extractChild) { - while (this._templateContent.childElementCount > 1) { - this._templateContent.removeChild(this._templateContent.lastElementChild); - } - } - }, { - - addClassOneTimeTextBinding: function (binding) { - var that = this; - var id = this.createTextBindingHole(binding.elementCapture.element.tagName, "class", ++this._textBindingId); - binding.textBindingId = id; - binding.kind = BindingKind.text; - binding.elementCapture.element.classList.add(id); - binding.elementCapture.refCount--; - binding.definition = function () { - return that.formatCode("{htmlEscape}({value})", { - htmlEscape: that._staticVariables.htmlEscape, - value: binding.value(), - }); - }; - }, - - addClassOneTimeTreeBinding: function (binding) { - - var that = this; - binding.pathExpression = this.bindingExpression(binding); - binding.value = function () { - return binding.pathExpression; - }; - binding.kind = BindingKind.tree; - binding.definition = function () { - return that.formatCode("{element}.classList.add({value})", { - element: binding.elementCapture, - value: binding.value(), - }); - }; - - }, - - analyze: function () { - - if (this._stage > Stage.analyze) { - throw "Illegal: once we have moved past analyze we cannot revist it"; - } - this._stage = Stage.analyze; - - // find activatable and bound elements - this._controls = this.gatherControls(); - this._bindings = this.gatherBindings(); - this._children = this.gatherChildren(); - - // remove attributes which are no longer needed since we will inline bindings and controls - this.cleanControlAndBindingAttributes(); - - if (this.async) { - this.createAsyncParts(); - } - - this.nullableIdentifierAccessTemporary = this.defineInstance(InstanceKind.temporary); - - // snapshot html - var html = this._templateContent.innerHTML; - this._html = function () { return multiline(literal(html)); }; - this._html.text = html; - - }, - - bindingExpression: function (binding) { - - return this._dataCSE.createPathExpression(binding.source, binding.source.join("_")); - - }, - - capture: function (element) { - - var capture = element.capture; - if (capture) { - capture.refCount++; - return capture; - } - - // Find the path to the captured element - // - var path = [element]; - var e = element.parentNode; - var name = element.tagName; - while (e !== this._templateContent) { - name = e.tagName + "_" + name; - path.unshift(e); - e = e.parentNode; - } - // Identify which child each path member is so we can form an indexed lookup - // - for (var i = 0, len = path.length; i < len; i++) { - var child = path[i]; - path[i] = Array.prototype.indexOf.call(e.children, child); - e = child; - } - // Create the capture and put it on the - // - capture = this._captureCSE.createPathExpression(path, name.toLowerCase()); - capture.element = element; - capture.element.capture = capture; - capture.refCount = 1; - return capture; - - }, - - cleanControlAndBindingAttributes: function () { - var selector = "[data-win-bind],[data-win-control]"; - var elements = this._templateContent.querySelectorAll(selector); - for (var i = 0, len = elements.length; i < len; i++) { - var element = elements[i]; - if (element.isDeclarativeControlContainer) { - i += element.querySelectorAll("[data-win-bind],[data-win-control]").length; - } - element.removeAttribute("data-win-bind"); - element.removeAttribute("data-win-control"); - element.removeAttribute("data-win-options"); - } - }, - - compile: function (bodyTemplate, replacements, supportDelayBindings) { - - if (this._stage > Stage.compile) { - throw "Illegal: once we have moved past compile we cannot revist it"; - } - this._stage = Stage.compile; - - var that = this; - - this._returnedElement = this._extractChild ? "container.firstElementChild" : "container"; - - var control_processing = this._controls.map(function (control) { - var constructionFormatString; - if (control.async) { - constructionFormatString = "{target}.winControl = {target}.winControl || new {SafeConstructor}({target}, {options}, controlDone)"; - } else { - constructionFormatString = "{target}.winControl = {target}.winControl || new {SafeConstructor}({target}, {options})"; - } - var construction = that.formatCode( - constructionFormatString, - { - target: control.elementCapture, - SafeConstructor: control.SafeConstructor, - options: that.generateOptionsLiteral(control.optionsParsed, control.elementCapture), - } - ); - if (control.isDeclarativeControlContainer && typeof control.isDeclarativeControlContainer.import === "function") { - var result = [construction]; - result.push(that.formatCode( - "{isDeclarativeControlContainer}({target}.winControl, {delayedControlProcessing})", - { - target: control.elementCapture, - isDeclarativeControlContainer: control.isDeclarativeControlContainer, - delayedControlProcessing: that._staticVariables.ui_processAll - } - )); - result.push(that.formatCode( - "{isDeclarativeControlContainer}({target}.winControl, {delayedBindingProcessing}(data, {templateDefaultInitializer}))", - { - target: control.elementCapture, - isDeclarativeControlContainer: control.isDeclarativeControlContainer, - delayedBindingProcessing: that._staticVariables.delayedBindingProcessing, - templateDefaultInitializer: that._staticVariables.templateDefaultInitializer || literal(null), - } - )); - return result.join(";\n"); - } else { - return construction; - } - }); - - var all_binding_processing = this._bindings.map(function (binding) { - switch (binding.kind) { - case BindingKind.template: - return that.formatCode( - "({nestedTemplates}[{nestedTemplate}] = {template}.render({path}, {dest}))", - { - nestedTemplates: that._nestedTemplates, - nestedTemplate: literal(binding.nestedTemplate), - template: binding.template, - path: binding.pathExpression, - dest: binding.elementCapture, - } - ); - - case BindingKind.initializer: - var formatString; - if (binding.initialValue) { - formatString = "({bindTokens}[{bindToken}] = {initializer}(data, {sourceProperties}, {dest}, {destProperties}, {initialValue}))"; - } else { - formatString = "({bindTokens}[{bindToken}] = {initializer}(data, {sourceProperties}, {dest}, {destProperties}))"; - } - return that.formatCode( - formatString, - { - bindTokens: that._bindTokens, - bindToken: literal(binding.bindToken), - initializer: binding.initializer, - sourceProperties: literal(binding.source), - destProperties: literal(binding.destination), - dest: binding.elementCapture, - initialValue: binding.initialValue, - } - ); - - case BindingKind.tree: - return binding.definition(); - - case BindingKind.text: - // do nothing, text bindings are taken care of seperately - break; - - case BindingKind.error: - // do nothing, errors are reported and ignored - break; - - default: - throw "NYI"; - } - }); - var binding_processing, delayed_binding_processing; - if (supportDelayBindings) { - binding_processing = all_binding_processing.filter(function (unused, index) { - return !that._bindings[index].delayable; - }); - delayed_binding_processing = all_binding_processing.filter(function (unused, index) { - return that._bindings[index].delayable; - }); - } else { - binding_processing = all_binding_processing; - delayed_binding_processing = []; - } - - var instances = values(this._instanceVariables); - - var instanceDefinitions = instances - .filter(function (instance) { return instance.kind === InstanceKind.variable; }) - .map(function (variable) { return variable.definition(); }); - - var captures = this._captureCSE.definitions(); - var globals = this._globalCSE.definitions(); - var data = this._dataCSE.definitions(); - - var set_msParentSelectorScope = this._children.map(function (child) { - return that.formatCodeN("{0}.msParentSelectorScope = true", child); - }); - var suffix = this._suffix.map(function (statement) { - return statement(); - }); - - var renderComplete = ""; - if (supportDelayBindings && delayed_binding_processing.length) { - renderComplete = that.formatCode( - renderItemImplRenderCompleteTemplate, - { - delayed_binding_processing: statements(delayed_binding_processing) - } - ); - } - - var result = that.formatCode( - bodyTemplate, - mergeAll([ - this._staticVariables, - replacements || {}, - { - profilerMarkIdentifierStart: literal("WinJS.Binding.Template:render" + this._profilerMarkIdentifier + ",StartTM"), - profilerMarkIdentifierStop: literal("WinJS.Binding.Template:render" + this._profilerMarkIdentifier + ",StopTM"), - html: this._html(), - tagName: literal(this._templateElement.tagName), - instance_variable_declarations: declarationList(instances), - global_definitions: statements(globals), - data_definitions: statements(data), - instance_variable_definitions: statements(instanceDefinitions), - capture_definitions: statements(captures), - set_msParentSelectorScope: statements(set_msParentSelectorScope), - debug_break: this.generateDebugBreak(), - control_processing: statements(control_processing), - control_counter: this._controlCounter, - binding_processing: statements(binding_processing), - renderComplete: renderComplete, - suffix_statements: statements(suffix), - nestedTemplates: this._nestedTemplates, - returnedElement: this._returnedElement, - }, - ]) - ); - - return this.prettify(result); - - }, - - createAsyncParts: function () { - - this._nestedTemplates = this._nestedTemplates || this.defineInstance( - InstanceKind.variable, - "nestedTemplates", - function () { return newArray(0); } - ); - - this._controlCounter = this._controlCounter || this.defineInstance( - InstanceKind.variable, - "controlCounter", - function () { return literal(1); } - ); - - }, - - createTextBindingHole: function (tagName, attribute, id) { - if (!this._textBindingPrefix) { - var c = ""; - while (this._html.text.indexOf("textbinding" + c) !== -1) { - c = c || 0; - c++; - } - this._textBindingPrefix = "textbinding" + c; - // NOTE: the form of this regex needs to be coordinated with any special cases which - // are introduced by the switch below. - this._textBindingRegex = new RegExp("(#?" + this._textBindingPrefix + "_\\d+)"); - } - - // Sometimes text bindings need to be of a particular form to suppress warnings from - // the host, specifically there is a case with IMG/src attribute where if you assign - // a naked textbinding_X to it you get a warning in the console of an unresolved image - // instead we prefix it with a # which is enough to suppress that message. - // - var result = this._textBindingPrefix + "_" + id; - if (tagName === "IMG" && attribute === "src") { - result = "#" + result; - } - - return result; - }, - - deadCodeElimination: function () { - var that = this; - - // Eliminate all captured elements which are no longer in the tree, this can happen if - // these captured elements are children of a node which had a text binding to 'innerText' - // or 'textContent' as those kill the subtree. - // - Object.keys(this._instanceVariables).forEach(function (key) { - var iv = that._instanceVariables[key]; - if (iv.kind === InstanceKind.capture) { - if (!that._templateContent.contains(iv.element)) { - iv.dead = true; - } - if (iv.refCount === 0) { - iv.dead = true; - } - if (iv.dead) { - // This dead instance variable returns a blank definition which will then get - // cleaned up by prettify. - iv.definition = function () { }; - iv.name = null; - delete that._instanceVariables[key]; - } - } - }); - - // Eliminate all control activations which target elements which are no longer in the tree - // - this._controls = this._controls.filter(function (c) { return !c.elementCapture.dead; }); - - // Eliminate all bindings which target elements which are no longer in the tree - // - this._bindings = this._bindings.filter(function (b) { return !b.elementCapture.dead; }); - - // Cleanup the capture CSE tree now that we know dead nodes are marked as such. - // - this._captureCSE.deadNodeElimination(); - - }, - - defineInstance: function (kind, name, definition) { - - if (this._stage >= Stage.compile) { - throw "Illegal: define instance variable after compilation stage has started"; - } - - var variableCount = this._instanceVariablesCount[kind] || 0; - var suffix = name ? name.replace(identifierCharacterRegEx, "_") : ""; - var identifier = createIdentifier(InstanceKindPrefixes[kind], variableCount, suffix); - identifier.definition = function () { return assignment(identifier, definition()); }; - identifier.kind = kind; - this._instanceVariables[identifier] = identifier; - this._instanceVariablesCount[kind] = variableCount + 1; - return identifier; - - }, - - defineStatic: function (kind, name, definition) { - - if (this._stage >= Stage.link) { - throw "Illegal: define static variable after link stage has started"; - } - - if (name) { - var known = this._staticVariables[name]; - if (known) { - return known; - } - } - var suffix = name ? name.replace(identifierCharacterRegEx, "_") : ""; - var identifier = createIdentifier(StaticKindPrefixes[kind], this._staticVariablesCount, suffix); - var that = this; - identifier.definition = function () { return assignment(identifier, definition()); } - identifier.kind = kind; - this._staticVariables[name || identifier] = identifier; - this._staticVariablesCount++; - return identifier; - - }, - - done: function () { - - if (this._stage > Stage.done) { - throw "Illegal: once we have moved past done we cannot revist it"; - } - this._stage = Stage.done; - - }, - - emitScopedSelect: function (selector, elementCapture) { - return this.formatCode( - "{scopedSelect}({selector}, {element})", - { - scopedSelect: this._staticVariables.scopedSelect, - selector: literal(selector), - element: elementCapture, - } - ); - }, - - emitOptionsNode: function (node, parts, elementCapture) { - - var that = this; - if (node) { - switch (typeof node) { - case "object": - if (Array.isArray(node)) { - parts.push("["); - for (var i = 0, len = node.length; i < len; i++) { - this.emitOptionsNode(node[i], parts, elementCapture); - parts.push(","); - } - parts.push("]"); - } else if (node instanceof CallExpression) { - parts.push(node.target === "select" ? this.emitScopedSelect(node.arg0Value, elementCapture) : literal(null)); - } else if (node instanceof IdentifierExpression && node.parts[0] instanceof CallExpression) { - var call = node.parts[0]; - parts.push( - nullableFilteredIdentifierAccessExpression( - call.target === "select" ? this.emitScopedSelect(call.arg0Value, elementCapture) : literal(null), - node.parts.slice(1), - this.nullableIdentifierAccessTemporary, - this.importSafe("requireSupportedForProcessing", requireSupportedForProcessing) - ) - ); - } else if (node instanceof IdentifierExpression) { - parts.push(node.pathExpression); - } else { - parts.push("{"); - Object.keys(node).forEach(function (key) { - - parts.push(propertyName(key)); - parts.push(":"); - that.emitOptionsNode(node[key], parts, elementCapture); - parts.push(","); - - }); - parts.push("}"); - } - break; - - default: - parts.push(literal(node)); - break; - } - } else { - parts.push(literal(null)); - } - - }, - - findGlobalIdentifierExpressions: function (obj, results) { - - results = results || []; - var that = this; - Object.keys(obj).forEach(function (key) { - var prop = obj[key]; - if (typeof prop === "object") { - if (prop instanceof IdentifierExpression) { - if (!(prop.parts[0] instanceof CallExpression)) { - results.push(prop); - } - } else { - that.findGlobalIdentifierExpressions(prop, results); - } - } - }); - return results; - - }, - - formatCodeN: function () { - - if (this._stage < Stage.compile) { - throw "Illegal: format code at before compilation stage has started"; - } - return format.apply(null, arguments); - - }, - - formatCode: function (string, parts) { - - if (this._stage < Stage.compile) { - throw "Illegal: format code at before compilation stage has started"; - } - return format(string, parts); - - }, - - gatherBindings: function () { - - var bindTokens = -1; - var that = this; - var nestedTemplates = -1; - var bindings = []; - var selector = "[data-win-bind],[data-win-control]"; - var elements = this._templateContent.querySelectorAll(selector); - for (var i = 0, len = elements.length; i < len; i++) { - var element = elements[i]; - - // If we run into a declarative control container (e.g. Binding.Template) we don't - // bind its children, but we will give it an opportunity to process later using the - // same data context. - if (element.isDeclarativeControlContainer) { - i += element.querySelectorAll(selector).length; - } - - // Since we had to look for controls as well as bindings in order to skip controls - // which are declarative control containers we have to check if this element is bound - if (!element.hasAttribute("data-win-bind")) { - continue; - } - - var bindingText = element.getAttribute("data-win-bind"); - var elementBindings = binding_parser(bindingText, global); - elementBindings.forEach(function (binding) { - if (binding.initializer) { - // If an initializer is specified it may be a nested template - var initializerName = binding.initializer.join("."); - var initializer = globalLookup(binding.initializer); - if (initializer.render) { - requireSupportedForProcessing(initializer.render); - // We have already chceked this to be safe for import - binding.template = that.importSafe(initializerName, initializer); - binding.pathExpression = that.bindingExpression(binding); - binding.nestedTemplate = ++nestedTemplates; - binding.kind = BindingKind.template; - } else if (initializer.winControl && initializer.winControl.render) { - requireSupportedForProcessing(initializer.winControl.render); - // We have already checked this to be safe to import - binding.template = that.importSafe(initializerName, initializer.winControl); - binding.pathExpression = that.bindingExpression(binding); - binding.nestedTemplate = ++nestedTemplates; - binding.kind = BindingKind.template; - } else { - // Don't get the path expression here, we will do it if needed in optimize - binding.initializer = that.import(initializerName, initializer); - binding.bindToken = ++bindTokens; - binding.kind = BindingKind.initializer; - } - } else { - // Don't get the path expression here, we will do it if needed in optimize - // We have already checked this to be safe to import - binding.initializer = that.importSafe("templateDefaultInitializer", that._defaultInitializer); - binding.bindToken = ++bindTokens; - binding.kind = BindingKind.initializer; - } - binding.elementCapture = that.capture(element); - binding.bindingText = bindingText; - }); - bindings.push.apply(bindings, elementBindings); - } - - var nestedTemplateCount = nestedTemplates + 1; - if (nestedTemplateCount > 0) { - this.async = true; - this._nestedTemplates = this.defineInstance( - InstanceKind.variable, - "nestedTemplates", - function () { return newArray(nestedTemplateCount); } - ); - } - - var bindTokenCount = bindTokens + 1; - if (bindTokenCount > 0) { - this._bindTokens = this.defineInstance( - InstanceKind.variable, - "bindTokens", - function () { return newArray(bindTokenCount); } - ); - this._suffix.push(function () { - // NOTE: returnedElement is a local in the template which is set to either be the container - // or in the extractChild: true case the first child. - return that.formatCode( - "{utilities_data}(returnedElement).bindTokens = {bindTokens}", - { - utilities_data: that._staticVariables.utilities_data, - bindTokens: that._bindTokens, - } - ); - }); - } - - return bindings; - - }, - - gatherChildren: function () { - - var that = this; - return Array.prototype.map.call(this._templateContent.children, function (child) { return that.capture(child); }); - - }, - - gatherControls: function () { - - var that = this; - var asyncCount = 0; - var controls = []; - var selector = "[data-win-control]"; - var elements = this._templateContent.querySelectorAll(selector); - for (var i = 0, len = elements.length; i < len; i++) { - var element = elements[i]; - var name = element.getAttribute("data-win-control"); - // Control constructors are checked along the entirety of their path to be supported - // for processing when they are bound - var ControlConstructor = WinJS.Utilities._getMemberFiltered(name.trim(), global, requireSupportedForProcessing); - if (!ControlConstructor) { - continue; - } - - var optionsText = element.getAttribute("data-win-options") || literal({}); - var async = ControlConstructor.length > 2; - if (async) { - asyncCount++; - this.async = true; - } - - var isDeclarativeControlContainer = ControlConstructor.isDeclarativeControlContainer; - if (isDeclarativeControlContainer) { - if (typeof isDeclarativeControlContainer === "function") { - isDeclarativeControlContainer = this.import(name + "_isDeclarativeControlContainer", isDeclarativeControlContainer); - } - - element.isDeclarativeControlContainer = isDeclarativeControlContainer; - i += element.querySelectorAll(selector).length; - } - - var control = { - elementCapture: this.capture(element), - name: name, - // We have already checked this for requireSupportedForProcessing - SafeConstructor: this.importSafe(name, ControlConstructor), - async: async, - optionsText: literal(optionsText), - optionsParsed: options_parser(optionsText), - isDeclarativeControlContainer: isDeclarativeControlContainer, - }; - controls.push(control); - - var globalReferences = this.findGlobalIdentifierExpressions(control.optionsParsed); - globalReferences.forEach(function (identifierExpression) { - identifierExpression.pathExpression = that.globalExpression(identifierExpression.parts); - }); - } - - if (asyncCount > 0) { - this._controlCounter = this.defineInstance( - InstanceKind.variable, - "controlCounter", - // +1 because we call it once to start in case we have no async controls in the async template - function () { return literal(asyncCount + 1); } - ); - } - - return controls; - - }, - - generateElementCaptureAccess: function (l, r, root, filter) { - - if (root) { - // Clean up the right hand side so we don't end up with "startIndex + 0" - var right = ("" + r === "0" ? "" : " + " + r); - - return this.formatCodeN("{0}.children[startIndex{1}]", l, right); - } - return this.formatCodeN("{0}.children[{1}]", l, r); - - }, - - generateNormalAccess: function (left, right, root, filter, last) { - - // The 'last' parameter indicates that this path access is the last part of a greater - // access expression and therefore does not need to be further assigned to the temp. - - if (left.indexOf(this.nullableIdentifierAccessTemporary) >= 0) { - // If the nullableIdentifierAccessTemporary is on the LHS then the - // LHS is already an access expression and does not need to be null-checked again - var formatString; - if (last) { - formatString = "{left} && {filter}({temp}{right})"; - } else { - formatString = "{left} && ({temp} = {filter}({temp}{right}))"; - } - return this.formatCode(formatString, { - temp: this.nullableIdentifierAccessTemporary, - left: left, - right: identifierAccessExpression([right]), - filter: filter - }); - } - var formatString; - if (last) { - formatString = "({temp} = {left}) && {filter}({temp}{right})"; - } else { - formatString = "({temp} = {left}) && ({temp} = {filter}({temp}{right}))"; - } - return this.formatCode(formatString, { - temp: this.nullableIdentifierAccessTemporary, - left: left, - right: identifierAccessExpression([right]), - filter: filter - }); - - }, - - generateOptionsLiteral: function (optionsParsed, elementCapture) { - - var parts = []; - this.emitOptionsNode(optionsParsed, parts, elementCapture); - return parts.join(" "); - - }, - - generateDebugBreak: function () { - - if (this._debugBreak) { - var counter = this.defineStatic( - StaticKind.variable, - "debugCounter", - function () { return literal(0); } - ); - return this.formatCodeN("if (++{0} === 1) {{ debugger; }}", counter); - } - return ""; - - }, - - globalExpression: function (path) { - - return this._globalCSE.createPathExpression(path, path.join("_")); - - }, - - import: function (name, i) { - - // Used for functions which are gathered from user code (e.g. binding initializers and - // control constructors). For these functions we need to assert that they are safe for - // use in a declarative context, however since the values are known at compile time we - // can do that check once. - // - return this.importSafe(name, requireSupportedForProcessing(i)); - - }, - - importSafe: function (name, i) { - - // Used for functions and objects which are intrinsic to the template compiler and are safe - // for their intended usages and don't need to be marked requireSupportedForProcessing. - // - var that = this; - var identifier = this.defineStatic( - StaticKind.import, - name, - function () { return that.formatCodeN("({0}{1})", IMPORTS_ARG_NAME, identifierAccessExpression([name])) } - ); - if (identifier.import && identifier.import !== i) { - throw "Duplicate import: '" + name + "'"; - } - identifier.import = i; - return identifier; - - }, - - importAll: function (imports) { - Object.keys(imports).forEach(function (key) { - requireSupportedForProcessing(imports[key]); - }); - return this.importAllSafe(imports); - }, - - importAllSafe: function (imports) { - - var that = this; - var result = Object.keys(imports).reduce( - function (o, key) { - o[key] = that.importSafe(key, imports[key]); - return o; - }, - {} - ); - return result; - - }, - - link: function (body) { - - if (this._stage > Stage.link) { - throw "Illegal: once we have moved past link we cannot revist it"; - } - this._stage = Stage.link; - - var that = this; - - // Gather the set of imported instances (functions mostly). All of these are runtime values which - // are already safety checked for things like requireSupportedForProcessing. - // - var imports = keys(this._staticVariables) - .filter(function (key) { return that._staticVariables[key].kind === StaticKind.import; }) - .reduce( - function (o, key) { - o[key] = that._staticVariables[key].import; - return o; - }, - {} - ); - - var statics = values(this._staticVariables); - - return new Function(IMPORTS_ARG_NAME, - this.formatCode( - linkerCodeTemplate, - { - static_variable_declarations: declarationList(statics), - static_variable_definitions: statements(statics.map(function (s) { return s.definition(); })), - body: body.trim(), - } - ) - )(imports); - - }, - - lower: function () { - - if (this._stage > Stage.lower) { - throw "Illegal: once we have moved past lower we cannot revist it"; - } - this._stage = Stage.lower; - - this._captureCSE.lower(); - this._dataCSE.lower(); - this._globalCSE.lower(); - - }, - - markBindingAsError: function (binding) { - if (binding) { - binding.kind = BindingKind.error; - this.markBindingAsError(binding.original); - } - }, - - oneTimeTextBinding: function (binding) { - - var that = this; - var result = this.oneTimeTextBindingAnalyze(binding); - if (result) { - var initialValue; - if (binding.original) { - initialValue = binding.original.initialValue; - } - var id = this.createTextBindingHole(binding.elementCapture.element.tagName, result.attribute, ++this._textBindingId); - binding.textBindingId = id; - binding.kind = BindingKind.text; - binding.elementCapture.refCount--; - binding.definition = function () { - var formatString; - if (initialValue) { - formatString = "{htmlEscape}({initialValue})"; - } else { - formatString = "{htmlEscape}({getter})"; - } - return that.formatCode( - formatString, - { - htmlEscape: that._staticVariables.htmlEscape, - getter: binding.value(), - initialValue: initialValue, - } - ); - }; - - switch (result.kind) { - case TextBindingKind.attribute: - binding.elementCapture.element.setAttribute(result.attribute, id); - break; - - case TextBindingKind.booleanAttribute: - // Boolean attributes work differently, the presence of the attribute in any - // form means true and its absence means false. This means that we need to - // add or remove the whole thing and make the definition of the binding - // expression at runtime add it back. - // - binding.elementCapture.element.setAttribute(result.attribute, id); - - // Wrap the definition in a ternary expression which yields either the attribute - // name or an empty string. - // - var definition = binding.definition; - binding.definition = function () { - var formatString; - if (initialValue) { - formatString = "({initialValue} ? {attribute} : \"\")"; - } else { - formatString = "({value} ? {attribute} : \"\")"; - } - return that.formatCode( - formatString, - { - value: binding.value(), - attribute: literal(result.attribute), - initialValue: initialValue - } - ); - }; - - // Arrange for the attribute in the HTML with the 'id' as a value to be wholy - // replaced by the ID. - // - this._htmlProcessors.push(function (html) { - return html.replace(new RegExp(result.attribute + "=\"" + id + "\"", "i"), id); - }); - break; - - case TextBindingKind.textContent: - binding.elementCapture.element.textContent = id; - break; - - case TextBindingKind.inlineStyle: - var element = binding.elementCapture.element; - // Inline styles require a little finesseing, their form always needs to be - // legal CSS include in the value space. We could attempt to special case - // all CSS properties and produce something which is legal in their value - // space but instead we wholesale replace the inline CSS with a extension - // property temporarially in order to get valid HTML. Later we go replace - // that well-known hole with the original inline CSS text as well as any - // new properties we are setting as a result of data binding. - // - if (!element.msReplaceStyle) { - element.msReplaceStyle = element.getAttribute("style") || ""; - // Ensure that there is always a trailing ';' - if (element.msReplaceStyle !== "" && element.msReplaceStyle[element.msReplaceStyle.length - 1] !== ";") { - element.msReplaceStyle = element.msReplaceStyle + ";"; - } - element.setAttribute("style", "msReplaceStyle:\"" + id + "\""); - var temp = element.getAttribute("style"); - this._htmlProcessors.push(function (html) { - return html.replace(temp, element.msReplaceStyle); - }); - } - element.msReplaceStyle = element.msReplaceStyle + result.property + ":" + id + ";"; - break; - - default: - throw "NYI"; - } - } - - }, - - oneTimeTextBindingAnalyze: function (binding) { - var element = binding.elementCapture.element; - var elementType = element.tagName; - var targetProperty = binding.destination[0]; - - // Properties which can only be optimized for a given element types - // - switch (elementType) { - case "A": - switch (targetProperty) { - case "href": - return { kind: TextBindingKind.attribute, attribute: targetProperty }; - } - break; - - case "IMG": - switch (targetProperty) { - case "alt": - case "src": - case "width": - case "height": - return { kind: TextBindingKind.attribute, attribute: targetProperty }; - } - break; - - case "SELECT": - switch (targetProperty) { - case "disabled": - case "multiple": - case "required": - return { kind: TextBindingKind.booleanAttribute, attribute: targetProperty }; - - case "size": - return { kind: TextBindingKind.attribute, attribute: targetProperty }; - } - break; - - case "OPTION": - switch (targetProperty) { - case "label": - case "value": - return { kind: TextBindingKind.attribute, attribute: targetProperty }; - - case "disabled": - case "selected": - return { kind: TextBindingKind.booleanAttribute, attribute: targetProperty }; - } - break; - - case "INPUT": - switch (targetProperty) { - case "checked": - switch (element.type) { - case "checkbox": - case "radio": - return { kind: TextBindingKind.booleanAttribute, attribute: targetProperty }; - } - break; - - case "disabled": - return { kind: TextBindingKind.booleanAttribute, attribute: targetProperty }; - - case "max": - case "maxLength": - case "min": - case "step": - case "value": - return { kind: TextBindingKind.attribute, attribute: targetProperty }; - - case "size": - switch (element.type) { - case "text": - case "search": - case "tel": - case "url": - case "email": - case "password": - return { kind: TextBindingKind.attribute, attribute: targetProperty }; - } - break; - - case "readOnly": - switch (element.type) { - case "hidden": - case "range": - case "color": - case "checkbox": - case "radio": - case "file": - case "button": - // not supported: - break; - - default: - return { kind: TextBindingKind.attribute, attribute: targetProperty }; - } - break; - } - break; - - case "BUTTON": - switch (targetProperty) { - case "disabled": - return { kind: TextBindingKind.booleanAttribute, attribute: targetProperty }; - - case "value": - return { kind: TextBindingKind.attribute, attribute: targetProperty }; - } - break; - - case "TEXTAREA": - switch (targetProperty) { - case "disabled": - case "readOnly": - case "required": - return { kind: TextBindingKind.booleanAttribute, attribute: targetProperty }; - - case "cols": - case "maxLength": - case "placeholder": - case "rows": - case "wrap": - return { kind: TextBindingKind.attribute, attribute: targetProperty }; - } - break; - } - - // Properties which can be optimized for all element types - // - switch (targetProperty) { - case "className": - return { kind: TextBindingKind.attribute, attribute: "class" }; - - case "dir": - case "lang": - case "name": - case "title": - case "tabIndex": - return { kind: TextBindingKind.attribute, attribute: targetProperty }; - - case "style": - if (binding.destination.length > 1) { - var targetCssProperty = binding.destination[1]; - if (targetCssProperty === "cssText") { - // We don't support optimizing the cssText property on styles - // - return; - } - // If this is a supported css property we will get a string (frequently empty) - // from the style object. - // - var supported = typeof element.style[targetCssProperty] === "string"; - if (supported) { - // The mapping from css property name to JS property name is regular: - // - // 1) -ms- prefix -> ms prefix - // 2) split on interior '-' and make the next word uppercase - // - // We can reverse this to make css property names. - // - if (targetCssProperty[0] === "m" && targetCssProperty[1] === "s") { - targetCssProperty = "-" + targetCssProperty; - } - targetCssProperty = targetCssProperty.replace(capitalRegEx, function (l) { - return "-" + l.toLowerCase(); - }); - return { kind: TextBindingKind.inlineStyle, property: targetCssProperty, attribute: "style" }; - } - } - break; - - case "innerText": - case "textContent": - return { kind: TextBindingKind.textContent, attribute: "textContent" }; - } - }, - - oneTimeTreeBinding: function (binding) { - - if (binding.destination.length === 1 && binding.destination[0] === "id") { - if (WinJS.validation) { - throw new WinJS.ErrorFromName("WinJS.Binding.IdBindingNotSupported", WinJS.Resources._formatString(strings.idBindingNotSupported, binding.bindingText)); - } - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.idBindingNotSupported, binding.bindingText), "winjs binding", "error"); - this.markBindingAsError(binding); - return; - } - - if (binding.destination.length === 0) { - WinJS.log && WinJS.log(strings.cannotBindToThis, "winjs binding", "error"); - this.markBindingAsError(binding); - return; - } - - var that = this; - var initialValue; - binding.pathExpression = this.bindingExpression(binding); - binding.value = function () { - return binding.pathExpression; - }; - if (binding.original) { - initialValue = binding.pathExpression; - binding.original.initialValue = initialValue; - } - binding.kind = BindingKind.tree; - binding.definition = function () { - var formatString; - if (initialValue) { - formatString = "({targetPath} || {{}}){prop} = {initialValue}"; - } else { - formatString = "({targetPath} || {{}}){prop} = {sourcePath}"; - } - return that.formatCode( - formatString, - { - targetPath: nullableFilteredIdentifierAccessExpression( - binding.elementCapture, - binding.destination.slice(0, -1), - that.nullableIdentifierAccessTemporary, - that.importSafe("targetSecurityCheck", targetSecurityCheck) - ), - prop: identifierAccessExpression(binding.destination.slice(-1)), - sourcePath: binding.value(), - initialValue: initialValue, - } - ); - }; - - }, - - optimize: function () { - - if (this._stage > Stage.optimze) { - throw "Illegal: once we have moved past link we cannot revist it"; - } - this._stage = Stage.optimze; - - var that = this; - - // Identify all bindings which can be turned into tree bindings, in some cases this consists - // of simply changing their type and providing a definition, in other cases it involves - // adding a new tree binding to complement the other binding - // - for (var i = 0; i < this._bindings.length; i++) { - var binding = this._bindings[i]; - if (binding.template) { - continue; - } - - switch (binding.initializer.import) { - case init_defaultBind: - // Add a new tree binding for one-time binding and mark the defaultBind as delayable - var newBinding = merge(binding, { - kind: BindingKind.tree, - initializer: this.importSafe("init_oneTime", init_oneTime), - original: binding, - }); - newBinding.elementCapture.refCount++; - this.oneTimeTreeBinding(newBinding); - this._bindings.splice(i, 0, newBinding); - binding.delayable = true; - i++; - break; - - case init_setAttribute: - // Add a new tree binding for one-time setAttribute and mark the setAttribute as delayable - var newBinding = merge(binding, { - kind: BindingKind.tree, - initializer: this.importSafe("init_setAttributeOneTime", init_setAttributeOneTime), - original: binding, - }); - newBinding.elementCapture.refCount++; - this.setAttributeOneTimeTreeBinding(newBinding); - this._bindings.splice(i, 0, newBinding); - binding.delayable = true; - i++; - break; - - case init_oneTime: - this.oneTimeTreeBinding(binding); - break; - - case init_setAttributeOneTime: - this.setAttributeOneTimeTreeBinding(binding); - break; - - case init_addClassOneTime: - this.addClassOneTimeTreeBinding(binding); - break; - - default: - if (binding.initializer) { - binding.delayable = !!binding.initializer.import.delayable; - } - break; - } - } - - if (this._optimizeTextBindings) { - - // Identifiy all potential text bindings and generate text replacement expressions - // - var textBindings = {}; - for (var i = 0; i < this._bindings.length; i++) { - var binding = this._bindings[i]; - if (binding.template) { - continue; - } - if (binding.kind === BindingKind.error) { - continue; - } - - switch (binding.initializer.import) { - case init_oneTime: - this.oneTimeTextBinding(binding); - break; - - case init_setAttributeOneTime: - this.setAttributeOneTimeTextBinding(binding); - break; - - case init_addClassOneTime: - this.addClassOneTimeTextBinding(binding); - break; - - default: - break; - } - if (binding.textBindingId) { - textBindings[binding.textBindingId] = binding; - } - } - - if (Object.keys(textBindings).length) { - var newHtml = this._templateContent.innerHTML; - - // Perform any adjustments to the HTML that are needed for things like styles and - // boolean attributes - // - newHtml = this._htmlProcessors.reduce( - function (html, replacer) { - return replacer(html); - }, - newHtml - ); - - // All the even indexes are content and all the odds are replacements - // - // NOTE: this regular expression is - var parts = newHtml.split(this._textBindingRegex); - for (var i = 1; i < parts.length; i += 2) { - var binding = textBindings[parts[i]]; - parts[i] = binding.definition; - } - - // Generate the function which will code-gen the HTML replacements. - // - this._html = function () { - var result = parts.map(function (p) { - // the strings are the literal parts of the HTML that came directly from the DOM - // the functions are the definitions for string replacements - return typeof p === "string" ? literal(p) : p(); - }).join(" + "); - return multiline(result); - }; - } - - } - - }, - - prettify: function (result) { - - // remove all lines which contain nothing but a semi-colon - var lines = result.split("\n"); - return lines.filter(function (line) { return !semiColonOnlyLineRegEx.test(line); }).join("\n"); - - }, - - setAttributeOneTimeTextBinding: function (binding) { - - var that = this; - var attribute = binding.destination[0]; - var id = this.createTextBindingHole(binding.elementCapture.element.tagName, attribute, ++this._textBindingId); - var initialValue; - if (binding.original) { - initialValue = binding.original.initialValue; - } - binding.textBindingId = id; - binding.kind = BindingKind.text; - binding.elementCapture.element.setAttribute(attribute, id); - binding.elementCapture.refCount--; - binding.definition = function () { - var formatString; - if (initialValue) { - formatString = "{htmlEscape}({initialValue})"; - } else { - formatString = "{htmlEscape}({value})"; - } - return that.formatCode( - formatString, - { - htmlEscape: that._staticVariables.htmlEscape, - initialValue: initialValue, - value: binding.value(), - } - ); - }; - - }, - - setAttributeOneTimeTreeBinding: function (binding) { - - if (binding.destination.length === 1 && binding.destination[0] === "id") { - if (WinJS.validation) { - throw new WinJS.ErrorFromName("WinJS.Binding.IdBindingNotSupported", WinJS.Resources._formatString(strings.idBindingNotSupported, binding.bindingText)); - } - WinJS.log && WinJS.log(WinJS.Resources._formatString(strings.idBindingNotSupported, binding.bindingText), "winjs binding", "error"); - this.markBindingAsError(binding); - return; - } - - if (binding.destination.length !== 1 || !binding.destination[0]) { - WinJS.log && WinJS.log(strings.attributeBindingSingleProperty, "winjs binding", "error"); - this.markBindingAsError(binding); - return; - } - - var that = this; - var initialValue; - binding.pathExpression = this.bindingExpression(binding); - binding.value = function () { - return binding.pathExpression; - }; - if (binding.original) { - initialValue = this.defineInstance(InstanceKind.variable, "", binding.value); - binding.original.initialValue = initialValue; - } - binding.kind = BindingKind.tree; - binding.definition = function () { - var formatString; - if (initialValue) { - formatString = "{element}.setAttribute({attribute}, \"\" + {initialValue})"; - } else { - formatString = "{element}.setAttribute({attribute}, \"\" + {value})"; - } - return that.formatCode( - formatString, - { - element: binding.elementCapture, - attribute: literal(binding.destination[0]), - initialValue: initialValue, - value: binding.value(), - } - ); - }; - - }, - - }, { - _TreeCSE: TreeCSE, - - compile: function TemplateCompiler_compile(template, templateElement, options) { - - if (!(templateElement instanceof HTMLElement)) { - throw "Illegal"; - } - - msWriteProfilerMark("WinJS.Binding.Template:compile" + options.profilerMarkIdentifier + ",StartTM"); - - var compiler = new TemplateCompiler(templateElement, options); - - compiler.analyze(); - - var importAliases = compiler.importAllSafe({ - Signal: WinJS._Signal, - global: global, - document: document, - cancelBlocker: cancelBlocker, - promise_as: promise_as, - disposeInstance: disposeInstance, - markDisposable: markDisposable, - ui_processAll: ui_processAll, - binding_processAll: binding_processAll, - insertAdjacentHTMLUnsafe: insertAdjacentHTMLUnsafe, - promise: Promise, - utilities_data: utilities_data, - requireSupportedForProcessing: requireSupportedForProcessing, - htmlEscape: htmlEscape, - scopedSelect: scopedSelect, - delayedBindingProcessing: delayedBindingProcessing, - }); - - compiler.optimize(); - - compiler.deadCodeElimination(); - - compiler.lower(); - - var codeTemplate; - var delayBindings; - switch (options.target) { - case "render": - codeTemplate = compiler.async ? renderImplCodeAsyncTemplate : renderImplCodeTemplate; - delayBindings = false; - break; - - case "renderItem": - codeTemplate = compiler.async ? renderItemImplCodeAsyncTemplate : renderItemImplCodeTemplate; - delayBindings = true; - break; - } - - var body = compiler.compile(codeTemplate, importAliases, delayBindings); - var render = compiler.link(body); - - compiler.done(); - - msWriteProfilerMark("WinJS.Binding.Template:compile" + options.profilerMarkIdentifier + ",StopTM"); - - return render; - } - }); - - // - // Templates - // - - function trimLinesRight(string) { - // Replace all empty lines with just a newline - // Remove all trailing spaces - return string.replace(/^\s*$/gm, "").replace(/^(.*[^\s])( *)$/gm, function (unused, content) { - return content; - }); - } - - var renderImplMainCodePrefixTemplate = trimLinesRight("\ -container.classList.add(\"win-template\"); \n\ -var html = {html}; \n\ -{insertAdjacentHTMLUnsafe}(container, \"beforeend\", html); \n\ -returnedElement = {returnedElement}; \n\ - \n\ -// Capture Definitions \n\ -{capture_definitions}; \n\ -{set_msParentSelectorScope}; \n\ - \n\ -"); - - var renderImplControlAndBindingProcessing = trimLinesRight("\ -// Control Processing \n\ -{control_processing}; \n\ - \n\ -// Binding Processing \n\ -{binding_processing}; \n\ - \n\ -var result = {promise_as}(returnedElement); \n\ -"); - - var renderImplAsyncControlAndBindingProcessing = trimLinesRight("\ -var controlSignal = new {Signal}(); \n\ -var controlDone = function () {{ if (--{control_counter} === 0) {{ controlSignal.complete(); }} }}; \n\ -controlDone(); \n\ - \n\ -// Control Processing \n\ -{control_processing}; \n\ - \n\ -var result = controlSignal.promise.then(function () {{ \n\ - // Binding Processing \n\ - {binding_processing}; \n\ - return {promise}.join({nestedTemplates}); \n\ -}}).then(function () {{ \n\ - return returnedElement; \n\ -}}).then(null, function (e) {{ \n\ - if (typeof e === \"object\" && e.name === \"Canceled\") {{ returnedElement.dispose(); }} \n\ - return {promise}.wrapError(e); \n\ -}}); \n\ -"); - - var renderImplMainCodeSuffixTemplate = trimLinesRight("\ -{markDisposable}(returnedElement, function () {{ {disposeInstance}(returnedElement, result); }}); \n\ -{suffix_statements}; \n\ -"); - - var renderImplCodeTemplate = trimLinesRight("\ -function render(data, container) {{ \n\ - {debug_break} \n\ - if (typeof data === \"object\" && typeof data.then === \"function\") {{ \n\ - // async data + a container falls back to interpreted path \n\ - if (container) {{ \n\ - var result = this._renderInterpreted(data, container); \n\ - return result.element.then(function () {{ return result.renderComplete; }}); \n\ - }} \n\ - return {cancelBlocker}(data).then(function(data) {{ return render(data); }}); \n\ - }} \n\ - \n\ - msWriteProfilerMark({profilerMarkIdentifierStart}); \n\ - \n\ - // Declarations \n\ - var {instance_variable_declarations}; \n\ - var returnedElement; \n\ - \n\ - // Global Definitions \n\ - {global_definitions}; \n\ - \n\ - // Data Definitions \n\ - data = (data === {global} ? data : {requireSupportedForProcessing}(data)); \n\ - {data_definitions}; \n\ - \n\ - // Instance Variable Definitions \n\ - {instance_variable_definitions}; \n\ - \n\ - // HTML Processing \n\ - container = container || {document}.createElement({tagName}); \n\ - var startIndex = container.childElementCount; \n\ - " + trim(indent(4, renderImplMainCodePrefixTemplate)) + " \n\ - \n\ - " + trim(indent(4, renderImplControlAndBindingProcessing)) + " \n\ - " + trim(indent(4, renderImplMainCodeSuffixTemplate)) + " \n\ - \n\ - msWriteProfilerMark({profilerMarkIdentifierStop}); \n\ - \n\ - return result; \n\ -}} \n\ -"); - - var renderImplCodeAsyncTemplate = trimLinesRight("\ -function render(data, container) {{ \n\ - {debug_break} \n\ - if (typeof data === \"object\" && typeof data.then === \"function\") {{ \n\ - // async data + a container falls back to interpreted path \n\ - if (container) {{ \n\ - var result = this._renderInterpreted(data, container); \n\ - return result.element.then(function () {{ return result.renderComplete; }}); \n\ - }} \n\ - return {cancelBlocker}(data).then(function(data) {{ return render(data, container); }}); \n\ - }} \n\ - \n\ - msWriteProfilerMark({profilerMarkIdentifierStart}); \n\ - \n\ - // Declarations \n\ - var {instance_variable_declarations}; \n\ - var returnedElement; \n\ - \n\ - // Global Definitions \n\ - {global_definitions}; \n\ - \n\ - // Data Definitions \n\ - data = (data === {global} ? data : {requireSupportedForProcessing}(data)); \n\ - {data_definitions}; \n\ - \n\ - // Instance Variable Definitions \n\ - {instance_variable_definitions}; \n\ - \n\ - // HTML Processing \n\ - container = container || {document}.createElement({tagName}); \n\ - var startIndex = container.childElementCount; \n\ - " + trim(indent(4, renderImplMainCodePrefixTemplate)) + " \n\ - \n\ - " + trim(indent(4, renderImplAsyncControlAndBindingProcessing)) + " \n\ - " + trim(indent(4, renderImplMainCodeSuffixTemplate)) + " \n\ - \n\ - msWriteProfilerMark({profilerMarkIdentifierStop}); \n\ - \n\ - return result; \n\ -}} \n\ -"); - - var renderItemImplMainCodeSuffixTemplate = trimLinesRight("\ -{markDisposable}(returnedElement, function () {{ {disposeInstance}(returnedElement, result, renderComplete); }});\n\ -{suffix_statements}; \n\ -"); - - var renderItemImplCodeTemplate = trimLinesRight("\ -function renderItem(itemPromise) {{ \n\ - {debug_break} \n\ - // Declarations \n\ - var {instance_variable_declarations}; \n\ - var element, renderComplete, data, returnedElement; \n\ - \n\ - element = itemPromise.then(function renderItem(item) {{ \n\ - if (typeof item.data === \"object\" && typeof item.data.then === \"function\") {{ \n\ - return {cancelBlocker}(item.data).then(function (data) {{ return renderItem({{ data: data }}); }});\n\ - }} \n\ - \n\ - msWriteProfilerMark({profilerMarkIdentifierStart}); \n\ - \n\ - // Global Definitions \n\ - {global_definitions}; \n\ - \n\ - // Data Definitions \n\ - data = item.data; \n\ - data = (data === {global} ? data : {requireSupportedForProcessing}(data)); \n\ - {data_definitions}; \n\ - \n\ - // Instance Variable Definitions \n\ - {instance_variable_definitions}; \n\ - \n\ - // HTML Processing \n\ - var container = {document}.createElement({tagName}); \n\ - var startIndex = 0; \n\ - " + trim(indent(8, renderImplMainCodePrefixTemplate)) + " \n\ - \n\ - " + trim(indent(8, renderImplControlAndBindingProcessing)) + " \n\ - " + trim(indent(8, renderItemImplMainCodeSuffixTemplate)) + " \n\ - \n\ - msWriteProfilerMark({profilerMarkIdentifierStop}); \n\ - \n\ - return result; \n\ - }}); \n\ - {renderComplete}; \n\ - return {{ \n\ - element: element, \n\ - renderComplete: renderComplete || element, \n\ - }}; \n\ -}} \n\ -"); - - var renderItemImplRenderCompleteTemplate = trimLinesRight("\ -renderComplete = element.then(function () {{ \n\ - return itemPromise; \n\ -}}).then(function (item) {{ \n\ - return item.ready || item; \n\ -}}).then(function (item) {{ \n\ - {delayed_binding_processing}; \n\ - return element; \n\ -}}); \n\ -"); - - var renderItemImplCodeAsyncTemplate = trimLinesRight("\ -function renderItem(itemPromise) {{ \n\ - {debug_break} \n\ - // Declarations \n\ - var {instance_variable_declarations}; \n\ - var element, renderComplete, data, returnedElement; \n\ - \n\ - element = itemPromise.then(function renderItem(item) {{ \n\ - if (typeof item.data === \"object\" && typeof item.data.then === \"function\") {{ \n\ - return {cancelBlocker}(item.data).then(function (data) {{ return renderItem({{ data: data }}); }});\n\ - }} \n\ - \n\ - msWriteProfilerMark({profilerMarkIdentifierStart}); \n\ - \n\ - // Global Definitions \n\ - {global_definitions}; \n\ - \n\ - // Data Definitions \n\ - data = item.data; \n\ - data = (data === {global} ? data : {requireSupportedForProcessing}(data)); \n\ - {data_definitions}; \n\ - \n\ - // Instance Variable Definitions \n\ - {instance_variable_definitions}; \n\ - \n\ - // HTML Processing \n\ - var container = {document}.createElement({tagName}); \n\ - var startIndex = 0; \n\ - " + trim(indent(8, renderImplMainCodePrefixTemplate)) + " \n\ - \n\ - " + trim(indent(8, renderImplAsyncControlAndBindingProcessing)) + " \n\ - " + trim(indent(8, renderItemImplMainCodeSuffixTemplate)) + " \n\ - \n\ - msWriteProfilerMark({profilerMarkIdentifierStop}); \n\ - \n\ - return result; \n\ - }}); \n\ - {renderComplete}; \n\ - return {{ \n\ - element: element, \n\ - renderComplete: renderComplete || element, \n\ - }}; \n\ -}} \n\ -"); - - var linkerCodeTemplate = trimLinesRight("\ -\"use strict\"; \n\ - \n\ -// statics \n\ -var {static_variable_declarations}; \n\ -{static_variable_definitions}; \n\ - \n\ -// generated template rendering function \n\ -return {body}; \n\ -"); - - // - // End Templates - // - - return TemplateCompiler; - }) - }); - - -}(this)); - -(function resInit(WinJS, undefined) { - "use strict"; - - var readyComplete = false; - var resourceMap; - var resourceLoader; - - var requireSupportedForProcessing = WinJS.Utilities.requireSupportedForProcessing - - function processAllImpl(rootElement, count) { - rootElement = rootElement || document.body; - - var count = count || 0; - - if (count < 4) { - // Only 3 depth is supported in the innerHTML - if (count == 0) { - if (rootElement.getAttribute) { - // Fragment-loaded root element isn't caught by querySelectorAll - var rootElementNode = rootElement.getAttribute('data-win-res'); - if (rootElementNode) { - var decls = WinJS.UI.optionsParser(rootElementNode); - setMembers(rootElement, rootElement, decls, count); - } - } - } - - var selector = "[data-win-res],[data-win-control]"; - var elements = rootElement.querySelectorAll(selector); - if (elements.length === 0) { - return WinJS.Promise.as(rootElement); - } - - for (var i = 0, len = elements.length; i < len; i++) { - var e = elements[i]; - - if (e.winControl && e.winControl.constructor && e.winControl.constructor.isDeclarativeControlContainer) { - var idcc = e.winControl.constructor.isDeclarativeControlContainer; - if (typeof idcc === "function") { - idcc = requireSupportedForProcessing(idcc); - idcc(e.winControl, WinJS.Resources.processAll); - - // Skip all children of declarative control container - i += e.querySelectorAll(selector).length; - } - } - - if (!e.hasAttribute("data-win-res")) { - continue; - } - // Use optionsParser that accept string format - // {name="value", name2="value2"} - var decls = WinJS.UI.optionsParser(e.getAttribute('data-win-res')); - setMembers(e, e, decls, count); - } - - } - else if (WinJS.validation) { - throw new WinJS.ErrorFromName("WinJS.Res.NestingExceeded", WinJS.Resources._getWinJSString("base/nestingExceeded").value); - } - - return WinJS.Promise.as(rootElement); - }; - - function setAttributes(root, descriptor) { - var names = Object.keys(descriptor); - - for (var k = 0, l = names.length ; k < l; k++) { - var name = names[k]; - var value = descriptor[name]; - - var data = WinJS.Resources.getString(value); - - if (!data || !data.empty) { - root.setAttribute(name, data.value); - - if ((data.lang !== undefined) && - (root.lang !== undefined) && - (root.lang !== data.lang)) { - - root.lang = data.lang; - } - } - else if (WinJS.validation) { - notFound(value); - } - } - } - - function notFound(name) { - throw new WinJS.ErrorFromName("WinJS.Res.NotFound", WinJS.Resources._formatString(WinJS.Resources._getWinJSString("base/notFound").value, name)); - } - - function setMembers(root, target, descriptor, count) { - var names = Object.keys(descriptor); - target = requireSupportedForProcessing(target); - - for (var k = 0, l = names.length ; k < l; k++) { - var name = names[k]; - var value = descriptor[name]; - - if (typeof value === "string") { - var data = WinJS.Resources.getString(value); - - if (!data || !data.empty) { - target[name] = data.value; - - if ((data.lang !== undefined) && - (root.lang !== undefined) && - (root.lang !== data.lang)) { - // When lang property is different, we set the language with selected string's language - root.lang = data.lang; - } - - if (name === "innerHTML") { - processAllImpl(target, count + 1); - } - } - else if (WinJS.validation) { - notFound(value); - } - } - else if (root === target && name === "attributes") { - //Exposing setAttribute for attributes that don't have HTML properties, like aria, through a fake 'attributes' property - setAttributes(root, value); - } - else { - setMembers(root, target[name], value, count); - } - } - } - - WinJS.Namespace.define("WinJS.Resources", { - processAll: function (rootElement) { - /// - /// - /// Processes resources tag and replaces strings - /// with localized strings. - /// - /// - /// The DOM element at which to start processing. processAll processes the element and its child elements. - /// If you don't specify root element, processAll processes the entire document. - /// - /// - - if (!readyComplete) { - return WinJS.Utilities.ready().then(function () { - readyComplete = true; - return processAllImpl(rootElement); - }); - } - else { - try { - return processAllImpl(rootElement); - } - catch (e) { - return WinJS.Promise.wrapError(e); - } - } - } - }); -})(WinJS); - -msWriteProfilerMark("Microsoft.WinJS.2.0 1.0.9600.17018.winblue_gdr.140204-1946 base.js,StopTM"); - diff --git a/shared/html/libs/winjs/2.0/js/en-us/base.strings.js b/shared/html/libs/winjs/2.0/js/en-us/base.strings.js deleted file mode 100644 index e65d032..0000000 --- a/shared/html/libs/winjs/2.0/js/en-us/base.strings.js +++ /dev/null @@ -1,63 +0,0 @@ -/// -/*! - © Microsoft. All rights reserved. - - This library is supported for use in Windows Store apps only. - - Build: 1.0.9600.17018.winblue_gdr.140204-1946 - - Version: Microsoft.WinJS.2.0 -*/ - -(function (global) { - global.strings = global.strings || {}; - - var appxVersion = "Microsoft.WinJS.2.0"; - var developerPrefix = "Developer."; - if (appxVersion.indexOf(developerPrefix) === 0) { - appxVersion = appxVersion.substring(developerPrefix.length); - } - - function addStrings(keyPrefix, strings) { - Object.keys(strings).forEach(function (key) { - global.strings[keyPrefix + key.replace("\\", "/")] = strings[key]; - }); - } - -addStrings( -"ms-resource://"+appxVersion+"/base/", - -{ - "attributeBindingSingleProperty": "Attribute binding requires a single destination attribute name, often in the form \"this['aria-label']\" or \"width\".", - "bindingInitializerNotFound": "Initializer not found:'{0}'", - "cannotBindToThis": "Can't bind to 'this'.", - "creatingNewProperty": "Creating new property {0}. Full path:{1}", - "duplicateBindingDetected": "Binding against element with id {0} failed because a duplicate id was detected.", - "elementNotFound": "Element not found:{0}", - "errorActivatingControl": "Error activating control: {0}", - "errorInitializingBindings": "Error initializing bindings: {0}", - "exceptionFromBindingInitializer": "Exception thrown from binding initializer: {0}", - "idBindingNotSupported": "Declarative binding to ID field is not supported. Initializer: {0}", - "illegalListLength": "List length must be assigned a finite positive number", - "invalidBinding": "Invalid binding:'{0}'. Expected to be ':;'. {1}", - "invalidFragmentUri": "Unsupported uri for fragment loading. Fragments in the local context can only load from package content or local sources. To load fragments from other sources, use a web context.", - "invalidOptionsRecord": "Invalid options record: '{0}', expected to be in the format of an object literal. {1}", - "jobInfoIsNoLongerValid": "The job info object can only be used while the job is running", - "malformedFormatStringInput": "Malformed, did you mean to escape your '{0}'?", - "nestedDOMElementBindingNotSupported": "Binding through a property {0} of type HTMLElement is not supported, Full path:{1}.", - "nestingExceeded": "NestingExceeded", - "notFound": "NotFound: {0}", - "notSupportedForProcessing": "Value is not supported within a declarative processing context, if you want it to be supported mark it using WinJS.Utilities.markSupportedForProcessing. The value was: '{0}'", - "nonStaticHTML": "Unable to add dynamic content. A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property or the document.write method to add a script element will generate this exception. If the content is safe and from a trusted source, use a method to explicitly manipulate elements and attributes, such as createElement, or use setInnerHTMLUnsafe (or other unsafe method).", - "propertyDoesNotExist": "{0} doesn't exist. Full path:{1}", - "propertyIsUndefined": "{0} is undefined", - "sparseArrayNotSupported": "Sparse arrays are not supported with proxy: true", - "unexpectedTokenExpectedToken": "Unexpected token: {0}, expected token: {1}, at offset {2}", - "unexpectedTokenExpectedTokens": "Unexpected token: {0}, expected one of: {1}, at offset {2}", - "unexpectedTokenGeneric": "Unexpected token: {0}, at offset {1}", - "unsupportedDataTypeForBinding": "Unsupported data type" -} - -); - -}(this)); diff --git a/shared/html/libs/winjs/2.0/js/en-us/ui.strings.js b/shared/html/libs/winjs/2.0/js/en-us/ui.strings.js deleted file mode 100644 index e6dd19c..0000000 --- a/shared/html/libs/winjs/2.0/js/en-us/ui.strings.js +++ /dev/null @@ -1,530 +0,0 @@ -/// -/*! - © Microsoft. All rights reserved. - - This library is supported for use in Windows Store apps only. - - Build: 1.0.9600.17018.winblue_gdr.140204-1946 - - Version: Microsoft.WinJS.2.0 -*/ - -(function (global) { - global.strings = global.strings || {}; - - var appxVersion = "Microsoft.WinJS.2.0"; - var developerPrefix = "Developer."; - if (appxVersion.indexOf(developerPrefix) === 0) { - appxVersion = appxVersion.substring(developerPrefix.length); - } - - function addStrings(keyPrefix, strings) { - Object.keys(strings).forEach(function (key) { - global.strings[keyPrefix + key.replace("\\", "/")] = strings[key]; - }); - } - -addStrings( -"ms-resource://"+appxVersion+"/ui/", - -{ - "appBarAriaLabel": "App Bar", - "appBarCommandAriaLabel": "App Bar Item", - "asynchronousRender" : "Top level items must render synchronously", - "automaticallyLoadPagesIsDeprecated": "Invalid configuration: automaticallyLoadPages is deprecated. The control will default this property to false. Please refer to the 'ListView loading behaviors' SDK Sample for guidance on how to implement incremental load behavior.", - "averageRating": "Average Rating", - "backbuttonarialabel": "Back", - "badAlignment": "Invalid argument: Flyout alignment should be 'center' (default), 'left', or 'right'.", - "badAxis": "Invalid argument: orientation must be a string, either 'horizontal' or 'vertical'", - "badButtonElement": "Invalid argument: For a button, toggle, or flyout command, the element must be null or a button element", - "badClick": "Invalid argument: The onclick property for an {0} must be a function", - "badCurrentPage": "Invalid argument: currentPage must be a number greater than or equal to zero and be within the bounds of the datasource", - "badDivElement": "Invalid argument: For a content command, the element must be null or a div element", - "badFlyout": "Invalid argument: The flyout property for an {0} must be a Flyout or String id of a Flyout", - "badHrElement": "Invalid argument: For a separator, the element must be null or an hr element", - "badItemSpacingAmount": "Invalid argument: itemSpacing must be a number greater than or equal to zero", - "badLayout": "Invalid argument: The layout property must be 'custom' or 'commands'", - "badPlacement": "Invalid argument: Flyout placement should be 'top' (default), 'bottom', 'left', 'right', or 'auto'.", - "badReference": "Invalid argument: Invalid href to settings flyout fragment", - "cannotChangeCommandsWhenVisible": "Invalid argument: You must call hide() before changing {0} commands", - "cannotChangeHiddenProperty": "Unable to set hidden property while parent {0} is visible.", - "cannotChangeLayoutWhenVisible": "Invalid argument: The layout property cannot be set when the AppBar is visible, call hide() first", - "cannotChangePlacementWhenVisible": "Invalid argument: The placement property cannot be set when the AppBar is visible, call hide() first", - "clearYourRating" : "Clear your rating", - "closeOverlay" : "Close", - "datePicker": "Date Picker", - "disableBackdropIsDeprecated" : "Invalid configuration: disableBackdrop is deprecated. Style: .win-listview .win-container.win-backdrop { background-color:transparent; } instead.", - "duplicateConstruction": "Invalid argument: Controls may only be instantiated one time for each DOM element", - "duplicateSection": "Hub duplicate sections: Each HubSection must be unique", - "backdropColorIsDeprecated" : "Invalid configuration: backdropColor is deprecated. Style: .win-listview .win-container.win-backdrop { rgba(155,155,155,0.23); } instead.", - "flipViewNavigationDuringStateChange": "Error: After changing itemDataSource or itemTemplate, any navigation in the FlipView control should be delayed until the pageselected event is fired.", - "flipViewPanningContainerAriaLabel": "Scrolling Container", - "flyoutAriaLabel": "Flyout", - "groupInfoIsDeprecated": "GridLayout.groupInfo may be altered or unavailable in future versions. Instead, use CellSpanningLayout.", - "groupInfoResultIsInvalid": "Invalid result: groupInfo result for cell spanning groups must include the following numeric properties: cellWidth and cellHeight.", - "hubViewportAriaLabel": "Scrolling Container", - "indexIsInvalid": "Invalid argument: index must be a non-negative integer.", - "invalidHubContent": "Invalid content: Hub content must be made up of HubSections.", - "invalidCountReturned": "Error: data adapter should return undefined, null, CountResult.unknown, or a non-negative integer for the count.", - "invalidIndexReturned": "Error: data adapter should return undefined, null or a non-negative integer for the index.", - "invalidItemReturned": "Error: data adapter returned item that is not an object.", - "invalidItemsManagerCallback": "Invalid argument: {0} must be a function.", - "invalidKeyReturned": "Error: data adapter returned item with undefined or null key.", - "invalidSearchBoxSuggestionKind": "Error: Invalid search suggestion kind.", - "invalidTemplate": "Invalid template: Templates must be created before being passed to the ListView, and must contain a valid tree of elements.", - "invalidViewBoxChildren": "ViewBox expects to only have one child element", - "invalidZoomFactor": "Invalid zoomFactor", - "invalidRequestedCountReturned": "Error: data adapter should return CountResult.unknown, CountResult.failure, or a non-negative integer for the count.", - "itemInfoIsDeprecated": "GridLayout.itemInfo may be altered or unavailable in future versions. Instead, use CellSpanningLayout.", - "itemInfoIsInvalid": "Invalid argument: An itemInfo function must be provided which returns an object with numeric width and height properties.", - "itemIsInvalid": "Invalid argument: item must be a DOM element that was returned by the Items Manager, and has not been replaced or released.", - "itemRendererIsInvalid": "Invalid argument: itemRenderer must be a function.", - "keyIsInvalid": "Invalid argument: key must be a string.", - "listDataAdapterIsInvalid": "Invalid argument: listDataAdapter must be an object or an array.", - "listDataSourceIsInvalid": "Invalid argument: dataSource must be an object.", - "listViewInvalidItem": "Item must provide index, key or description of corresponding item.", - "listViewViewportAriaLabel": "Scrolling Container", - "loadingBehaviorIsDeprecated": "Invalid configuration: loadingBehavior is deprecated. The control will default this property to 'randomAccess'. Please refer to the 'ListView loading behaviors' SDK Sample for guidance on how to implement incremental load behavior.", - "maxRowsIsDeprecated": "GridLayout.maxRows may be altered or unavailable in future versions. Instead, use the maximumRowsOrColumns property.", - "menuCommandAriaLabel": "Menu Item", - "menuAriaLabel": "Menu", - "modeIsInvalid": "Invalid argument: mode must be one of following values: 'none', 'single' or 'multi'.", - "mustContainCommands": "Invalid HTML: AppBars/Menus must contain only AppBarCommands/MenuCommands", - "navBarContainerViewportAriaLabel": "Scrolling Container", - "noAnchor": "Invalid argument: Showing flyout requires a DOM element as its parameter.", - "noitemsManagerForCount": "Invalid operation: can't get count if no dataSource has been set", - "notCompatibleWithSemanticZoom": "ListView can only be used with SemanticZoom if randomAccess loading behavior is specified.", - "nullCommand": "Invalid argument: command must not be null", - "off" : "Off", - "on" : "On", - "loadMorePagesIsDeprecated": "loadMorePages is deprecated. Invoking this function will not have any effect. Please refer to the 'ListView loading behaviors' SDK Sample for guidance on how to implement incremental load behavior.", - "pagesToLoadIsDeprecated": "Invalid configuration: pagesToLoad is deprecated. The control will not use this property. Please refer to the 'ListView loading behaviors' SDK Sample for guidance on how to implement incremental load behavior.", - "pagesToLoadThresholdIsDeprecated": "Invalid configuration: pagesToLoadThreshold is deprecated. The control will not use this property. Please refer to the 'ListView loading behaviors' SDK Sample for guidance on how to implement incremental load behavior.", - "refreshCycleIdentified": "refresh cycle found, likely data inconsistency", - "requiresCommands": "Invalid argument: commands must not be empty", - "repeaterReentrancy":"Cannot modify Repeater data until Repeater has commited previous modification.", - "resetGroupHeaderIsDeprecated": "resetGroupHeader may be altered or unavailable in future versions. Instead, mark the header element as disposable using WinJS.Utilities.markDisposable.", - "resetItemIsDeprecated": "resetItem may be altered or unavailable in future versions. Instead, mark the element as disposable using WinJS.Utilities.markDisposable.", - "searchBoxAriaLabel": "Searchbox", - "searchBoxAriaLabelInputNoPlaceHolder": "Searchbox, enter to submit query, esc to clear text", - "searchBoxAriaLabelInputPlaceHolder": "Searchbox, {0}, enter to submit query, esc to clear text", - "searchBoxAriaLabelButton": "Click to submit query", - "searchBoxAriaLabelQuery": "Suggestion: {0}", - "_searchBoxAriaLabelQuery.comment": "Suggestion: query text (example: Suggestion: contoso)", - "searchBoxAriaLabelSeparator": "Separator: {0}", - "_searchBoxAriaLabelSeparator.comment": "Separator: separator text (example: Separator: People or Separator: Apps)", - "searchBoxAriaLabelResult": "Result: {0}, {1}", - "_searchBoxAriaLabelResult.comment": "Result: text, detailed text (example: Result: contoso, www.contoso.com)", - "selectAMPM": "Select A.M P.M", - "selectDay": "Select Day", - "selectHour": "Select Hour", - "selectMinute": "Select Minute", - "selectMonth": "Select Month", - "selectYear": "Select Year", - "settingsFlyoutAriaLabel": "Settings Flyout", - "settingsFlyoutWidthIsDeprecated": "SettingsFlyout.width may be altered or unavailable in future versions. Instead, style the CSS width property on elements with the .win-settingsflyout class.", - "tentativeRating": "Tentative Rating", - "timePicker": "Time Picker", - "tooltipStringsIsInvalid": "Invalid argument: tooltipStrings must be null or an array of strings.", - "unrated": "Unrated", - "userRating": "User Rating", - // AppBar Icons follow, the format of the ui.js and ui.resjson differ for - // the AppBarIcon namespace. The remainder of the file therefore differs. - // Code point comments are the icon glyphs in the 'Segoe UI Symbol' font. - "appBarIcons\\previous": "\uE100", //  group:Media - "_appBarIcons\\previous.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\next": "\uE101", //  group:Media - "_appBarIcons\\next.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\play": "\uE102", //  group:Media - "_appBarIcons\\play.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\pause": "\uE103", //  group:Media - "_appBarIcons\\pause.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\edit": "\uE104", //  group:File - "_appBarIcons\\edit.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\save": "\uE105", //  group:File - "_appBarIcons\\save.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\clear": "\uE106", //  group:File - "_appBarIcons\\clear.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\delete": "\uE107", //  group:File - "_appBarIcons\\delete.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\remove": "\uE108", //  group:File - "_appBarIcons\\remove.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\add": "\uE109", //  group:File - "_appBarIcons\\add.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\cancel": "\uE10A", //  group:Editing - "_appBarIcons\\cancel.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\accept": "\uE10B", //  group:General - "_appBarIcons\\accept.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\more": "\uE10C", //  group:General - "_appBarIcons\\more.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\redo": "\uE10D", //  group:Editing - "_appBarIcons\\redo.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\undo": "\uE10E", //  group:Editing - "_appBarIcons\\undo.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\home": "\uE10F", //  group:General - "_appBarIcons\\home.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\up": "\uE110", //  group:General - "_appBarIcons\\up.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\forward": "\uE111", //  group:General - "_appBarIcons\\forward.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\right": "\uE111", //  group:General - "_appBarIcons\\right.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\back": "\uE112", //  group:General - "_appBarIcons\\back.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\left": "\uE112", //  group:General - "_appBarIcons\\left.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\favorite": "\uE113", //  group:Media - "_appBarIcons\\favorite.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\camera": "\uE114", //  group:System - "_appBarIcons\\camera.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\settings": "\uE115", //  group:System - "_appBarIcons\\settings.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\video": "\uE116", //  group:Media - "_appBarIcons\\video.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\sync": "\uE117", //  group:Media - "_appBarIcons\\sync.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\download": "\uE118", //  group:Media - "_appBarIcons\\download.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\mail": "\uE119", //  group:Mail and calendar - "_appBarIcons\\mail.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\find": "\uE11A", //  group:Data - "_appBarIcons\\find.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\help": "\uE11B", //  group:General - "_appBarIcons\\help.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\upload": "\uE11C", //  group:Media - "_appBarIcons\\upload.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\emoji": "\uE11D", //  group:Communications - "_appBarIcons\\emoji.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\twopage": "\uE11E", //  group:Layout - "_appBarIcons\\twopage.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\leavechat": "\uE11F", //  group:Communications - "_appBarIcons\\leavechat.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\mailforward": "\uE120", //  group:Mail and calendar - "_appBarIcons\\mailforward.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\clock": "\uE121", //  group:General - "_appBarIcons\\clock.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\send": "\uE122", //  group:Mail and calendar - "_appBarIcons\\send.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\crop": "\uE123", //  group:Editing - "_appBarIcons\\crop.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\rotatecamera": "\uE124", //  group:System - "_appBarIcons\\rotatecamera.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\people": "\uE125", //  group:Communications - "_appBarIcons\\people.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\closepane": "\uE126", //  group:Layout - "_appBarIcons\\closepane.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\openpane": "\uE127", //  group:Layout - "_appBarIcons\\openpane.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\world": "\uE128", //  group:General - "_appBarIcons\\world.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\flag": "\uE129", //  group:Mail and calendar - "_appBarIcons\\flag.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\previewlink": "\uE12A", //  group:General - "_appBarIcons\\previewlink.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\globe": "\uE12B", //  group:Communications - "_appBarIcons\\globe.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\trim": "\uE12C", //  group:Editing - "_appBarIcons\\trim.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\attachcamera": "\uE12D", //  group:System - "_appBarIcons\\attachcamera.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\zoomin": "\uE12E", //  group:Layout - "_appBarIcons\\zoomin.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\bookmarks": "\uE12F", //  group:Editing - "_appBarIcons\\bookmarks.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\document": "\uE130", //  group:File - "_appBarIcons\\document.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\protecteddocument": "\uE131", //  group:File - "_appBarIcons\\protecteddocument.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\page": "\uE132", //  group:Layout - "_appBarIcons\\page.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\bullets": "\uE133", //  group:Editing - "_appBarIcons\\bullets.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\comment": "\uE134", //  group:Communications - "_appBarIcons\\comment.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\mail2": "\uE135", //  group:Mail and calendar - "_appBarIcons\\mail2.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\contactinfo": "\uE136", //  group:Communications - "_appBarIcons\\contactinfo.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\hangup": "\uE137", //  group:Communications - "_appBarIcons\\hangup.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\viewall": "\uE138", //  group:Data - "_appBarIcons\\viewall.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\mappin": "\uE139", //  group:General - "_appBarIcons\\mappin.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\phone": "\uE13A", //  group:Communications - "_appBarIcons\\phone.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\videochat": "\uE13B", //  group:Communications - "_appBarIcons\\videochat.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\switch": "\uE13C", //  group:Communications - "_appBarIcons\\switch.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\contact": "\uE13D", //  group:Communications - "_appBarIcons\\contact.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\rename": "\uE13E", //  group:File - "_appBarIcons\\rename.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\pin": "\uE141", //  group:System - "_appBarIcons\\pin.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\musicinfo": "\uE142", //  group:Media - "_appBarIcons\\musicinfo.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\go": "\uE143", //  group:General - "_appBarIcons\\go.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\keyboard": "\uE144", //  group:System - "_appBarIcons\\keyboard.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\dockleft": "\uE145", //  group:Layout - "_appBarIcons\\dockleft.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\dockright": "\uE146", //  group:Layout - "_appBarIcons\\dockright.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\dockbottom": "\uE147", //  group:Layout - "_appBarIcons\\dockbottom.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\remote": "\uE148", //  group:System - "_appBarIcons\\remote.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\refresh": "\uE149", //  group:Data - "_appBarIcons\\refresh.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\rotate": "\uE14A", //  group:Layout - "_appBarIcons\\rotate.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\shuffle": "\uE14B", //  group:Media - "_appBarIcons\\shuffle.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\list": "\uE14C", //  group:Editing - "_appBarIcons\\list.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\shop": "\uE14D", //  group:General - "_appBarIcons\\shop.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\selectall": "\uE14E", //  group:Data - "_appBarIcons\\selectall.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\orientation": "\uE14F", //  group:Layout - "_appBarIcons\\orientation.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\import": "\uE150", //  group:Data - "_appBarIcons\\import.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\importall": "\uE151", //  group:Data - "_appBarIcons\\importall.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\browsephotos": "\uE155", //  group:Media - "_appBarIcons\\browsephotos.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\webcam": "\uE156", //  group:System - "_appBarIcons\\webcam.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\pictures": "\uE158", //  group:Media - "_appBarIcons\\pictures.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\savelocal": "\uE159", //  group:File - "_appBarIcons\\savelocal.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\caption": "\uE15A", //  group:Media - "_appBarIcons\\caption.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\stop": "\uE15B", //  group:Media - "_appBarIcons\\stop.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\showresults": "\uE15C", //  group:Data - "_appBarIcons\\showresults.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\volume": "\uE15D", //  group:Media - "_appBarIcons\\volume.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\repair": "\uE15E", //  group:System - "_appBarIcons\\repair.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\message": "\uE15F", //  group:Communications - "_appBarIcons\\message.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\page2": "\uE160", //  group:Layout - "_appBarIcons\\page2.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\calendarday": "\uE161", //  group:Mail and calendar - "_appBarIcons\\calendarday.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\calendarweek": "\uE162", //  group:Mail and calendar - "_appBarIcons\\calendarweek.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\calendar": "\uE163", //  group:Mail and calendar - "_appBarIcons\\calendar.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\characters": "\uE164", //  group:Editing - "_appBarIcons\\characters.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\mailreplyall": "\uE165", //  group:Mail and calendar - "_appBarIcons\\mailreplyall.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\read": "\uE166", //  group:Mail and calendar - "_appBarIcons\\read.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\link": "\uE167", //  group:Communications - "_appBarIcons\\link.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\accounts": "\uE168", //  group:Communications - "_appBarIcons\\accounts.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\showbcc": "\uE169", //  group:Mail and calendar - "_appBarIcons\\showbcc.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\hidebcc": "\uE16A", //  group:Mail and calendar - "_appBarIcons\\hidebcc.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\cut": "\uE16B", //  group:Editing - "_appBarIcons\\cut.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\attach": "\uE16C", //  group:Mail and calendar - "_appBarIcons\\attach.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\paste": "\uE16D", //  group:Editing - "_appBarIcons\\paste.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\filter": "\uE16E", //  group:Data - "_appBarIcons\\filter.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\copy": "\uE16F", //  group:Editing - "_appBarIcons\\copy.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\emoji2": "\uE170", //  group:Mail and calendar - "_appBarIcons\\emoji2.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\important": "\uE171", //  group:Mail and calendar - "_appBarIcons\\important.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\mailreply": "\uE172", //  group:Mail and calendar - "_appBarIcons\\mailreply.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\slideshow": "\uE173", //  group:Media - "_appBarIcons\\slideshow.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\sort": "\uE174", //  group:Data - "_appBarIcons\\sort.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\manage": "\uE178", //  group:System - "_appBarIcons\\manage.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\allapps": "\uE179", //  group:System - "_appBarIcons\\allapps.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\disconnectdrive": "\uE17A", //  group:System - "_appBarIcons\\disconnectdrive.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\mapdrive": "\uE17B", //  group:System - "_appBarIcons\\mapdrive.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\newwindow": "\uE17C", //  group:System - "_appBarIcons\\newwindow.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\openwith": "\uE17D", //  group:System - "_appBarIcons\\openwith.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\contactpresence": "\uE181", //  group:Communications - "_appBarIcons\\contactpresence.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\priority": "\uE182", //  group:Mail and calendar - "_appBarIcons\\priority.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\uploadskydrive": "\uE183", //  group:File - "_appBarIcons\\uploadskydrive.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\gototoday": "\uE184", //  group:Mail and calendar - "_appBarIcons\\gototoday.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\font": "\uE185", //  group:Editing - "_appBarIcons\\font.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\fontcolor": "\uE186", //  group:Editing - "_appBarIcons\\fontcolor.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\contact2": "\uE187", //  group:Communications - "_appBarIcons\\contact2.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\folder": "\uE188", //  group:File - "_appBarIcons\\folder.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\audio": "\uE189", //  group:Media - "_appBarIcons\\audio.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\placeholder": "\uE18A", //  group:General - "_appBarIcons\\placeholder.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\view": "\uE18B", //  group:Layout - "_appBarIcons\\view.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\setlockscreen": "\uE18C", //  group:System - "_appBarIcons\\setlockscreen.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\settile": "\uE18D", //  group:System - "_appBarIcons\\settile.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\cc": "\uE190", //  group:Media - "_appBarIcons\\cc.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\stopslideshow": "\uE191", //  group:Media - "_appBarIcons\\stopslideshow.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\permissions": "\uE192", //  group:System - "_appBarIcons\\permissions.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\highlight": "\uE193", //  group:Editing - "_appBarIcons\\highlight.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\disableupdates": "\uE194", //  group:System - "_appBarIcons\\disableupdates.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\unfavorite": "\uE195", //  group:Media - "_appBarIcons\\unfavorite.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\unpin": "\uE196", //  group:System - "_appBarIcons\\unpin.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\openlocal": "\uE197", //  group:File - "_appBarIcons\\openlocal.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\mute": "\uE198", //  group:Media - "_appBarIcons\\mute.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\italic": "\uE199", //  group:Editing - "_appBarIcons\\italic.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\underline": "\uE19A", //  group:Editing - "_appBarIcons\\underline.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\bold": "\uE19B", //  group:Editing - "_appBarIcons\\bold.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\movetofolder": "\uE19C", //  group:File - "_appBarIcons\\movetofolder.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\likedislike": "\uE19D", //  group:Data - "_appBarIcons\\likedislike.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\dislike": "\uE19E", //  group:Data - "_appBarIcons\\dislike.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\like": "\uE19F", //  group:Data - "_appBarIcons\\like.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\alignright": "\uE1A0", //  group:Editing - "_appBarIcons\\alignright.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\aligncenter": "\uE1A1", //  group:Editing - "_appBarIcons\\aligncenter.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\alignleft": "\uE1A2", //  group:Editing - "_appBarIcons\\alignleft.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\zoom": "\uE1A3", //  group:Layout - "_appBarIcons\\zoom.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\zoomout": "\uE1A4", //  group:Layout - "_appBarIcons\\zoomout.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\openfile": "\uE1A5", //  group:File - "_appBarIcons\\openfile.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\otheruser": "\uE1A6", //  group:System - "_appBarIcons\\otheruser.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\admin": "\uE1A7", //  group:System - "_appBarIcons\\admin.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\street": "\uE1C3", //  group:General - "_appBarIcons\\street.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\map": "\uE1C4", //  group:General - "_appBarIcons\\map.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\clearselection": "\uE1C5", //  group:Data - "_appBarIcons\\clearselection.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\fontdecrease": "\uE1C6", //  group:Editing - "_appBarIcons\\fontdecrease.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\fontincrease": "\uE1C7", //  group:Editing - "_appBarIcons\\fontincrease.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\fontsize": "\uE1C8", //  group:Editing - "_appBarIcons\\fontsize.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\cellphone": "\uE1C9", //  group:Communications - "_appBarIcons\\cellphone.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\reshare": "\uE1CA", //  group:Communications - "_appBarIcons\\reshare.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\tag": "\uE1CB", //  group:Data - "_appBarIcons\\tag.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\repeatone": "\uE1CC", //  group:Media - "_appBarIcons\\repeatone.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\repeatall": "\uE1CD", //  group:Media - "_appBarIcons\\repeatall.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\outlinestar": "\uE1CE", //  group:Data - "_appBarIcons\\outlinestar.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\solidstar": "\uE1CF", //  group:Data - "_appBarIcons\\solidstar.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\calculator": "\uE1D0", //  group:General - "_appBarIcons\\calculator.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\directions": "\uE1D1", //  group:General - "_appBarIcons\\directions.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\target": "\uE1D2", //  group:General - "_appBarIcons\\target.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\library": "\uE1D3", //  group:Media - "_appBarIcons\\library.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\phonebook": "\uE1D4", //  group:Communications - "_appBarIcons\\phonebook.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\memo": "\uE1D5", //  group:Communications - "_appBarIcons\\memo.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\microphone": "\uE1D6", //  group:System - "_appBarIcons\\microphone.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\postupdate": "\uE1D7", //  group:Communications - "_appBarIcons\\postupdate.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\backtowindow": "\uE1D8", //  group:Layout - "_appBarIcons\\backtowindow.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\fullscreen": "\uE1D9", //  group:Layout - "_appBarIcons\\fullscreen.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\newfolder": "\uE1DA", //  group:File - "_appBarIcons\\newfolder.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\calendarreply": "\uE1DB", //  group:Mail and calendar - "_appBarIcons\\calendarreply.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\unsyncfolder": "\uE1DD", //  group:File - "_appBarIcons\\unsyncfolder.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\reporthacked": "\uE1DE", //  group:Communications - "_appBarIcons\\reporthacked.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\syncfolder": "\uE1DF", //  group:File - "_appBarIcons\\syncfolder.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\blockcontact": "\uE1E0", //  group:Communications - "_appBarIcons\\blockcontact.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\switchapps": "\uE1E1", //  group:System - "_appBarIcons\\switchapps.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\addfriend": "\uE1E2", //  group:Communications - "_appBarIcons\\addfriend.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\touchpointer": "\uE1E3", //  group:System - "_appBarIcons\\touchpointer.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\gotostart": "\uE1E4", //  group:System - "_appBarIcons\\gotostart.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\zerobars": "\uE1E5", //  group:System - "_appBarIcons\\zerobars.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\onebar": "\uE1E6", //  group:System - "_appBarIcons\\onebar.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\twobars": "\uE1E7", //  group:System - "_appBarIcons\\twobars.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\threebars": "\uE1E8", //  group:System - "_appBarIcons\\threebars.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\fourbars": "\uE1E9", //  group:System - "_appBarIcons\\fourbars.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\scan": "\uE294", //  group:General - "_appBarIcons\\scan.comment": "{Locked:qps-ploc,qps-plocm}", - "appBarIcons\\preview": "\uE295", //  group:General - "_appBarIcons\\preview.comment": "{Locked:qps-ploc,qps-plocm}" -} - -); - -}(this)); diff --git a/shared/html/libs/winjs/2.0/js/ui.js b/shared/html/libs/winjs/2.0/js/ui.js deleted file mode 100644 index 497abaa..0000000 --- a/shared/html/libs/winjs/2.0/js/ui.js +++ /dev/null @@ -1,49895 +0,0 @@ -/// -/*! - © Microsoft. All rights reserved. - - This library is supported for use in Windows Store apps only. - - Build: 1.0.9600.17018.winblue_gdr.140204-1946 - - Version: Microsoft.WinJS.2.0 -*/ -msWriteProfilerMark("Microsoft.WinJS.2.0 1.0.9600.17018.winblue_gdr.140204-1946 ui.js,StartTM"); - -/// -/// - - - -(function animationsInit(WinJS) { - "use strict"; - - var thisWinUI = WinJS.UI; - var mstransform = "transform"; - - // Default to 11 pixel from the left (or right if RTL) - var defaultOffset = [{ top: "0px", left: "11px", rtlflip: true }]; - - var OffsetArray = WinJS.Class.define(function OffsetArray_ctor(offset, keyframe, defOffset) { - // Constructor - defOffset = defOffset || defaultOffset; - if (Array.isArray(offset) && offset.length > 0) { - this.offsetArray = offset; - if (offset.length === 1) { - this.keyframe = checkKeyframe(offset[0], defOffset[0], keyframe); - } - } else if (offset && offset.hasOwnProperty("top") && offset.hasOwnProperty("left")) { - this.offsetArray = [offset]; - this.keyframe = checkKeyframe(offset, defOffset[0], keyframe); - } else { - this.offsetArray = defOffset; - this.keyframe = chooseKeyframe(defOffset[0], keyframe); - } - }, { // Public Members - getOffset: function (i) { - if (i >= this.offsetArray.length) { - i = this.offsetArray.length - 1; - } - return this.offsetArray[i]; - } - }, { // Static Members - supportedForProcessing: false, - }); - - function checkKeyframe(offset, defOffset, keyframe) { - if (offset.keyframe) { - return offset.keyframe; - } - - if (!keyframe || - offset.left !== defOffset.left || - offset.top !== defOffset.top || - (offset.rtlflip && !defOffset.rtlflip)) { - return null; - } - - if (!offset.rtlflip) { - return keyframe; - } - - return keyframeCallback(keyframe); - } - - function chooseKeyframe(defOffset, keyframe) { - if (!keyframe || !defOffset.rtlflip) { - return keyframe; - } - - return keyframeCallback(keyframe); - } - - function keyframeCallback(keyframe) { - var keyframeRtl = keyframe + "-rtl"; - return function (i, elem) { - return window.getComputedStyle(elem).direction === "ltr" ? keyframe : keyframeRtl; - } - } - - function makeArray(elements) { - if (Array.isArray(elements) || elements instanceof NodeList || elements instanceof HTMLCollection) { - return elements; - } else if (elements) { - return [elements]; - } else { - return []; - } - } - - function collectOffsetArray(elemArray) { - var offsetArray = []; - for (var i = 0; i < elemArray.length; i++) { - var offset = { - top: elemArray[i].offsetTop, - left: elemArray[i].offsetLeft - }; - var matrix = window.getComputedStyle(elemArray[i], null).transform.split(","); - if (matrix.length === 6) { - offset.left += parseFloat(matrix[4]); - offset.top += parseFloat(matrix[5]); - } - offsetArray.push(offset); - } - return offsetArray; - } - - function staggerDelay(initialDelay, extraDelay, delayFactor, delayCap) { - return function (i) { - var ret = initialDelay; - for (var j = 0; j < i; j++) { - extraDelay *= delayFactor; - ret += extraDelay; - } - if (delayCap) { - ret = Math.min(ret, delayCap); - } - return ret; - }; - } - - function makeOffsetsRelative(elemArray, offsetArray) { - for (var i = 0; i < offsetArray.length; i++) { - offsetArray[i].top -= elemArray[i].offsetTop; - offsetArray[i].left -= elemArray[i].offsetLeft; - } - } - - function animTranslate2DTransform(elemArray, offsetArray, transition) { - makeOffsetsRelative(elemArray, offsetArray); - for (var i = 0; i < elemArray.length; i++) { - if (offsetArray[i].top !== 0 || offsetArray[i].left !== 0) { - elemArray[i].style.transform = "translate(" + offsetArray[i].left + "px, " + offsetArray[i].top + "px)"; - } - } - return thisWinUI.executeTransition(elemArray, transition); - } - - function translateCallback(offsetArray, prefix) { - prefix = prefix || ""; - return function (i, elem) { - var offset = offsetArray.getOffset(i); - var left = offset.left; - if (offset.rtlflip && window.getComputedStyle(elem).direction === "rtl") { - left = left.toString(); - if (left.charAt(0) === "-") { - left = left.substring(1); - } else { - left = "-" + left; - } - } - return prefix + "translate(" + left + ", " + offset.top + ")"; - }; - } - - function translateCallbackAnimate(offsetArray, suffix) { - suffix = suffix || ""; - return function (i, elem) { - var offset = offsetArray[i]; - return "translate(" + offset.left + "px, " + offset.top + "px) " + suffix; - }; - } - - function keyframeCallbackAnimate(offsetArray, keyframe) { - return function (i, elem) { - var offset = offsetArray[i]; - return (offset.left === 0 && offset.top === 0) ? keyframe : null; - }; - } - - function layoutTransition(LayoutTransition, target, affected, extra) { - var targetArray = makeArray(target); - var affectedArray = makeArray(affected); - var offsetArray = collectOffsetArray(affectedArray); - return new LayoutTransition(targetArray, affectedArray, offsetArray, extra); - } - - var ExpandAnimation = WinJS.Class.define(function ExpandAnimation_ctor(revealedArray, affectedArray, offsetArray) { - // Constructor - this.revealedArray = revealedArray; - this.affectedArray = affectedArray; - this.offsetArray = offsetArray; - }, { // Public Members - execute: function () { - var promise1 = thisWinUI.executeAnimation( - this.revealedArray, - { - keyframe: "WinJS-opacity-in", - property: "opacity", - delay: this.affectedArray.length > 0 ? 200 : 0, - duration: 167, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: 0, - to: 1 - }); - var promise2 = animTranslate2DTransform( - this.affectedArray, - this.offsetArray, - { - property: mstransform, - delay: 0, - duration: 367, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - return WinJS.Promise.join([promise1, promise2]); - } - }, { // Static Members - supportedForProcessing: false, - }); - - var CollapseAnimation = WinJS.Class.define(function CollapseAnimation_ctor(hiddenArray, affectedArray, offsetArray) { - // Constructor - this.hiddenArray = hiddenArray; - this.affectedArray = affectedArray; - this.offsetArray = offsetArray; - }, { // Public Members - execute: function () { - var promise1 = thisWinUI.executeAnimation( - this.hiddenArray, - { - keyframe: "WinJS-opacity-out", - property: "opacity", - delay: 0, - duration: 167, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: 1, - to: 0 - }); - var promise2 = animTranslate2DTransform( - this.affectedArray, - this.offsetArray, - { - property: mstransform, - delay: this.hiddenArray.length > 0 ? 167 : 0, - duration: 367, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - return WinJS.Promise.join([promise1, promise2]); - } - }, { // Static Members - supportedForProcessing: false, - }); - - var RepositionAnimation = WinJS.Class.define(function RepositionAnimation_ctor(target, elementArray, offsetArray) { - // Constructor - this.elementArray = elementArray; - this.offsetArray = offsetArray; - }, { // Public Members - execute: function () { - return animTranslate2DTransform( - this.elementArray, - this.offsetArray, - { - property: mstransform, - delay: staggerDelay(0, 33, 1, 250), - duration: 367, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - } - }, { // Static Members - supportedForProcessing: false, - }); - - var AddToListAnimation = WinJS.Class.define(function AddToListAnimation_ctor(addedArray, affectedArray, offsetArray) { - // Constructor - this.addedArray = addedArray; - this.affectedArray = affectedArray; - this.offsetArray = offsetArray; - }, { // Public Members - execute: function () { - var delay = this.affectedArray.length > 0 ? 240 : 0; - var promise1 = thisWinUI.executeAnimation( - this.addedArray, - [{ - keyframe: "WinJS-scale-up", - property: mstransform, - delay: delay, - duration: 120, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: "scale(0.85)", - to: "none" - }, - { - keyframe: "WinJS-opacity-in", - property: "opacity", - delay: delay, - duration: 120, - timing: "linear", - from: 0, - to: 1 - }] - ); - var promise2 = animTranslate2DTransform( - this.affectedArray, - this.offsetArray, - { - property: mstransform, - delay: 0, - duration: 400, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - return WinJS.Promise.join([promise1, promise2]); - } - }, { // Static Members - supportedForProcessing: false, - }); - - var DeleteFromListAnimation = WinJS.Class.define(function DeleteFromListAnimation_ctor(deletedArray, remainingArray, offsetArray) { - // Constructor - this.deletedArray = deletedArray; - this.remainingArray = remainingArray; - this.offsetArray = offsetArray; - }, { // Public Members - execute: function () { - var promise1 = thisWinUI.executeAnimation( - this.deletedArray, - [{ - keyframe: "WinJS-scale-down", - property: mstransform, - delay: 0, - duration: 120, - timing: "cubic-bezier(0.11, 0.5, 0.24, .96)", - from: "none", - to: "scale(0.85)" - }, - { - keyframe: "WinJS-opacity-out", - property: "opacity", - delay: 0, - duration: 120, - timing: "linear", - from: 1, - to: 0 - }]); - var promise2 = animTranslate2DTransform( - this.remainingArray, - this.offsetArray, - { - property: mstransform, - delay: this.deletedArray.length > 0 ? 60 : 0, - duration: 400, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - return WinJS.Promise.join([promise1, promise2]); - } - }, { // Static Members - supportedForProcessing: false, - }); - - var _UpdateListAnimation = WinJS.Class.define(function _UpdateListAnimation_ctor(addedArray, affectedArray, offsetArray, deleted) { - // Constructor - this.addedArray = addedArray; - this.affectedArray = affectedArray; - this.offsetArray = offsetArray; - var deletedArray = makeArray(deleted); - this.deletedArray = deletedArray; - this.deletedOffsetArray = collectOffsetArray(deletedArray); - }, { // Public Members - execute: function () { - makeOffsetsRelative(this.deletedArray, this.deletedOffsetArray); - - var delay = 0; - var promise1 = thisWinUI.executeAnimation( - this.deletedArray, - [{ - keyframe: keyframeCallbackAnimate(this.deletedOffsetArray, "WinJS-scale-down"), - property: mstransform, - delay: 0, - duration: 120, - timing: "cubic-bezier(0.11, 0.5, 0.24, .96)", - from: translateCallbackAnimate(this.deletedOffsetArray), - to: translateCallbackAnimate(this.deletedOffsetArray, "scale(0.85)") - }, - { - keyframe: "WinJS-opacity-out", - property: "opacity", - delay: 0, - duration: 120, - timing: "linear", - from: 1, - to: 0 - }]); - - if (this.deletedArray.length > 0) { - delay += 60; - } - - var promise2 = animTranslate2DTransform( - this.affectedArray, - this.offsetArray, - { - property: mstransform, - delay: delay, - duration: 400, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - - if (this.affectedArray.length > 0) { - delay += 240; - } else if (delay) { - delay += 60; - } - - var promise3 = thisWinUI.executeAnimation( - this.addedArray, - [{ - keyframe: "WinJS-scale-up", - property: mstransform, - delay: delay, - duration: 120, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: "scale(0.85)", - to: "none" - }, - { - keyframe: "WinJS-opacity-in", - property: "opacity", - delay: delay, - duration: 120, - timing: "linear", - from: 0, - to: 1 - }] - ); - return WinJS.Promise.join([promise1, promise2, promise3]); - } - }, { // Static Members - supportedForProcessing: false, - }); - - - var AddToSearchListAnimation = WinJS.Class.define(function AddToSearchListAnimation_ctor(addedArray, affectedArray, offsetArray) { - // Constructor - this.addedArray = addedArray; - this.affectedArray = affectedArray; - this.offsetArray = offsetArray; - }, { // Public Members - execute: function () { - var promise1 = thisWinUI.executeAnimation( - this.addedArray, - { - keyframe: "WinJS-opacity-in", - property: "opacity", - delay: this.affectedArray.length > 0 ? 240 : 0, - duration: 117, - timing: "linear", - from: 0, - to: 1 - }); - var promise2 = animTranslate2DTransform( - this.affectedArray, - this.offsetArray, - { - property: mstransform, - delay: 0, - duration: 400, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - return WinJS.Promise.join([promise1, promise2]); - } - }, { // Static Members - supportedForProcessing: false, - }); - - var DeleteFromSearchListAnimation = WinJS.Class.define(function DeleteFromSearchListAnimation_ctor(deletedArray, remainingArray, offsetArray) { - // Constructor - this.deletedArray = deletedArray; - this.remainingArray = remainingArray; - this.offsetArray = offsetArray; - }, { // Public Members - execute: function () { - var promise1 = thisWinUI.executeAnimation( - this.deletedArray, - { - keyframe: "WinJS-opacity-out", - property: "opacity", - delay: 0, - duration: 93, - timing: "linear", - from: 1, - to: 0 - }); - var promise2 = animTranslate2DTransform( - this.remainingArray, - this.offsetArray, - { - property: mstransform, - delay: this.deletedArray.length > 0 ? 60 : 0, - duration: 400, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - return WinJS.Promise.join([promise1, promise2]); - } - }, { // Static Members - supportedForProcessing: false, - }); - - var PeekAnimation = WinJS.Class.define(function PeekAnimation_ctor(target, elementArray, offsetArray) { - // Constructor - this.elementArray = elementArray; - this.offsetArray = offsetArray; - }, { // Public Members - execute: function () { - return animTranslate2DTransform( - this.elementArray, - this.offsetArray, - { - property: mstransform, - delay: 0, - duration: 2000, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - } - }, { // Static Members - supportedForProcessing: false, - }); - - WinJS.Namespace.define("WinJS.UI.Animation", { - - createExpandAnimation: function (revealed, affected) { - /// - /// - /// Creates an expand animation. - /// After creating the ExpandAnimation object, - /// modify the document to move the elements to their new positions, - /// then call the execute method on the ExpandAnimation object. - /// - /// - /// Single element or collection of elements which were revealed. - /// - /// - /// Single element or collection of elements whose positions were - /// affected by the expand. - /// - /// - /// ExpandAnimation object whose execute method returns - /// a Promise that completes when the animation is complete. - /// - /// - return layoutTransition(ExpandAnimation, revealed, affected); - }, - - createCollapseAnimation: function (hidden, affected) { - /// - /// - /// Creates a collapse animation. - /// After creating the CollapseAnimation object, - /// modify the document to move the elements to their new positions, - /// then call the execute method on the CollapseAnimation object. - /// - /// - /// Single element or collection of elements being removed from view. - /// When the animation completes, the application should hide the elements - /// or remove them from the document. - /// - /// - /// Single element or collection of elements whose positions were - /// affected by the collapse. - /// - /// - /// CollapseAnimation object whose execute method returns - /// a Promise that completes when the animation is complete. - /// - /// - return layoutTransition(CollapseAnimation, hidden, affected); - }, - - createRepositionAnimation: function (element) { - /// - /// - /// Creates a reposition animation. - /// After creating the RepositionAnimation object, - /// modify the document to move the elements to their new positions, - /// then call the execute method on the RepositionAnimation object. - /// - /// - /// Single element or collection of elements which were repositioned. - /// - /// - /// RepositionAnimation object whose execute method returns - /// a Promise that completes when the animation is complete. - /// - /// - return layoutTransition(RepositionAnimation, null, element); - }, - - fadeIn: function (shown) { - /// - /// - /// Execute a fade-in animation. - /// - /// - /// Single element or collection of elements to fade in. - /// At the end of the animation, the opacity of the elements is 1. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - return thisWinUI.executeTransition( - shown, - { - property: "opacity", - delay: 0, - duration: 250, - timing: "linear", - from: 0, - to: 1 - }); - }, - - fadeOut: function (hidden) { - /// - /// - /// Execute a fade-out animation. - /// - /// - /// Single element or collection of elements to fade out. - /// At the end of the animation, the opacity of the elements is 0. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - return thisWinUI.executeTransition( - hidden, - { - property: "opacity", - delay: 0, - duration: 167, - timing: "linear", - to: 0 - }); - }, - - createAddToListAnimation: function (added, affected) { - /// - /// - /// Creates an animation for adding to a list. - /// After creating the AddToListAnimation object, - /// modify the document to move the elements to their new positions, - /// then call the execute method on the AddToListAnimation object. - /// - /// - /// Single element or collection of elements which were added. - /// - /// - /// Single element or collection of elements whose positions were - /// affected by the add. - /// - /// - /// AddToListAnimation object whose execute method returns - /// a Promise that completes when the animation is complete. - /// - /// - return layoutTransition(AddToListAnimation, added, affected); - }, - - createDeleteFromListAnimation: function (deleted, remaining) { - /// - /// - /// Crestes an animation for deleting from a list. - /// After creating the DeleteFromListAnimation object, - /// modify the document to reflect the deletion, - /// then call the execute method on the DeleteFromListAnimation object. - /// - /// - /// Single element or collection of elements which will be deleted. - /// When the animation completes, the application should hide the elements - /// or remove them from the document. - /// - /// - /// Single element or collection of elements whose positions were - /// affected by the deletion. - /// - /// - /// DeleteFromListAnimation object whose execute method returns - /// a Promise that completes when the animation is complete. - /// - /// - return layoutTransition(DeleteFromListAnimation, deleted, remaining); - }, - - _createUpdateListAnimation: function (added, deleted, affected) { - return layoutTransition(_UpdateListAnimation, added, affected, deleted); - }, - - createAddToSearchListAnimation: function (added, affected) { - /// - /// - /// Creates an animation for adding to a list of search results. - /// This is similar to an AddToListAnimation, but faster. - /// After creating the AddToSearchListAnimation object, - /// modify the document to move the elements to their new positions, - /// then call the execute method on the AddToSearchListAnimation object. - /// - /// - /// Single element or collection of elements which were added. - /// - /// - /// Single element or collection of elements whose positions were - /// affected by the add. - /// - /// - /// AddToSearchListAnimation object whose execute method returns - /// a Promise that completes when the animation is complete. - /// - /// - return layoutTransition(AddToSearchListAnimation, added, affected); - }, - - createDeleteFromSearchListAnimation: function (deleted, remaining) { - /// - /// - /// Creates an animation for deleting from a list of search results. - /// This is similar to an DeleteFromListAnimation, but faster. - /// After creating the DeleteFromSearchListAnimation object, - /// modify the document to move the elements to their new positions, - /// then call the execute method on the DeleteFromSearchListAnimation object. - /// - /// - /// Single element or collection of elements which will be deleted. - /// When the animation completes, the application should hide the elements - /// or remove them from the document. - /// - /// - /// Single element or collection of elements whose positions were - /// affected by the deletion. - /// - /// - /// DeleteFromSearchListAnimation object whose execute method returns - /// a Promise that completes when the animation is complete. - /// - /// - return layoutTransition(DeleteFromSearchListAnimation, deleted, remaining); - }, - - - showEdgeUI: function (element, offset, options) { - /// - /// - /// Slides an element or elements into position at the edge of the screen. - /// This animation is designed for a small object like an appbar. - /// - /// - /// Single element or collection of elements to be slid into position. - /// The elements should be at their final positions - /// at the time the function is called. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the starting point of the animation. - /// If the number of offset objects is less than the length of the - /// element parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// Optional object which can specify the mechanism to use to play the animation. By default css - /// animations are used but if { mechanism: "transition" } is provided css transitions will be used. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, "WinJS-showEdgeUI", [{ top: "-70px", left: "0px" }]); - return thisWinUI[((options && options.mechanism === "transition") ? "executeTransition" : "executeAnimation")]( - element, - { - keyframe: offsetArray.keyframe, - property: mstransform, - delay: 0, - duration: 367, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: offsetArray.keyframe || translateCallback(offsetArray), - to: "none" - }); - }, - - showPanel: function (element, offset) { - /// - /// - /// Slides an element or elements into position at the edge of the screen. - /// This animation is designed for a large object like a keyboard. - /// - /// - /// Single element or collection of elements to be slid into position. - /// The elements should be at their final positions - /// at the time the function is called. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the starting point of the animation. - /// If the number of offset objects is less than the length of the - /// element parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// promise object - /// - /// - var offsetArray = new OffsetArray(offset, "WinJS-showPanel", [{ top: "0px", left: "364px", rtlflip: true }]); - return thisWinUI.executeAnimation( - element, - { - keyframe: offsetArray.keyframe, - property: mstransform, - delay: 0, - duration: 550, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: offsetArray.keyframe || translateCallback(offsetArray), - to: "none" - }); - }, - - hideEdgeUI: function (element, offset, options) { - /// - /// - /// Slides an element or elements at the edge of the screen out of view. - /// This animation is designed for a small object like an appbar. - /// - /// - /// Single element or collection of elements to be slid out. - /// The elements should be at their onscreen positions - /// at the time the function is called. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the ending point of the animation. - /// If the number of offset objects is less than the length of the - /// element parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// Optional object which can specify the mechanism to use to play the animation. By default css - /// animations are used but if { mechanism: "transition" } is provided css transitions will be used. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, "WinJS-hideEdgeUI", [{ top: "-70px", left: "0px" }]); - return thisWinUI[((options && options.mechanism === "transition") ? "executeTransition" : "executeAnimation")]( - element, - { - keyframe: offsetArray.keyframe, - property: mstransform, - delay: 0, - duration: 367, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: "none", - to: offsetArray.keyframe || translateCallback(offsetArray) - }); - }, - - hidePanel: function (element, offset) { - /// - /// - /// Slides an element or elements at the edge of the screen out of view. - /// This animation is designed for a large object like a keyboard. - /// - /// - /// Single element or collection of elements to be slid out. - /// The elements should be at their onscreen positions - /// at the time the function is called. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the ending point of the animation. - /// If the number of offset objects is less than the length of the - /// element parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, "WinJS-hidePanel", [{ top: "0px", left: "364px", rtlflip: true }]); - return thisWinUI.executeAnimation( - element, - { - keyframe: offsetArray.keyframe, - property: mstransform, - delay: 0, - duration: 550, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: "none", - to: offsetArray.keyframe || translateCallback(offsetArray) - }); - }, - - showPopup: function (element, offset) { - /// - /// - /// Displays an element or elements in the style of a popup. - /// - /// - /// Single element or collection of elements to be shown like a popup. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the starting point of the animation. - /// If the number of offset objects is less than the length of the - /// element parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, "WinJS-showPopup", [{ top: "50px", left: "0px" }]); - return thisWinUI.executeAnimation( - element, - [{ - keyframe: "WinJS-opacity-in", - property: "opacity", - delay: 83, - duration: 83, - timing: "linear", - from: 0, - to: 1 - }, - { - keyframe: offsetArray.keyframe, - property: mstransform, - delay: 0, - duration: 367, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: offsetArray.keyframe || translateCallback(offsetArray), - to: "none" - }]); - }, - - hidePopup: function (element) { - /// - /// - /// Removes a popup from the screen. - /// - /// - /// Single element or collection of elements to be hidden like a popup. - /// When the animation completes, the application should hide the elements - /// or remove them from the document. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - return thisWinUI.executeAnimation( - element, - { - keyframe: "WinJS-opacity-out", - property: "opacity", - delay: 0, - duration: 83, - timing: "linear", - from: 1, - to: 0 - }); - }, - - pointerDown: function (element) { - /// - /// - /// Execute a pointer-down animation. - /// Use the pointerUp animation to reverse the effect of this animation. - /// - /// - /// Single element or collection of elements responding to the - /// pointer-down event. - /// At the end of the animation, the elements' properties have been - /// modified to reflect the pointer-down state. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - return thisWinUI.executeTransition( - element, - { - property: mstransform, - delay: 0, - duration: 167, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "scale(0.975, 0.975)" - }); - }, - - pointerUp: function (element) { - /// - /// - /// Execute a pointer-up animation. - /// This reverses the effect of a pointerDown animation. - /// - /// - /// Single element or collection of elements responding to - /// the pointer-up event. - /// At the end of the animation, the elements' properties have been - /// returned to normal. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - return thisWinUI.executeTransition( - element, - { - property: mstransform, - delay: 0, - duration: 167, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - }, - - dragSourceStart: function (dragSource, affected) { - /// - /// - /// Execute a drag-start animation. - /// Use the dragSourceEnd animation to reverse the effects of this animation. - /// - /// - /// Single element or collection of elements being dragged. - /// At the end of the animation, the elements' properties have been - /// modified to reflect the drag state. - /// - /// - /// Single element or collection of elements to highlight as not - /// being dragged. - /// At the end of the animation, the elements' properties have been - /// modified to reflect the drag state. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var promise1 = thisWinUI.executeTransition( - dragSource, - [{ - property: mstransform, - delay: 0, - duration: 240, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "scale(1.05)" - }, - { - property: "opacity", - delay: 0, - duration: 240, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: 0.65 - }]); - var promise2 = thisWinUI.executeTransition( - affected, - { - property: mstransform, - delay: 0, - duration: 240, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "scale(0.95)" - }); - return WinJS.Promise.join([promise1, promise2]); - }, - - dragSourceEnd: function (dragSource, offset, affected) { - /// - /// - /// Execute a drag-end animation. - /// This reverses the effect of the dragSourceStart animation. - /// - /// - /// Single element or collection of elements no longer being dragged. - /// At the end of the animation, the elements' properties have been - /// returned to normal. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the starting point of the animation. - /// If the number of offset objects is less than the length of the - /// dragSource parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// Single element or collection of elements which were highlighted as not - /// being dragged. - /// At the end of the animation, the elements' properties have been - /// returned to normal. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, "WinJS-dragSourceEnd"); - var promise1 = thisWinUI.executeTransition( - dragSource, - [{ - property: mstransform, - delay: 0, - duration: 500, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" // this removes the scale - }, - { - property: "opacity", - delay: 0, - duration: 500, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: 1 - }]); - - var promise2 = thisWinUI.executeAnimation( - dragSource, - { - keyframe: offsetArray.keyframe, - property: mstransform, - delay: 0, - duration: 500, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: offsetArray.keyframe || translateCallback(offsetArray, "scale(1.05) "), - to: "none" - }); - - var promise3 = thisWinUI.executeTransition( - affected, - { - property: mstransform, - delay: 0, - duration: 500, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - return WinJS.Promise.join([promise1, promise2, promise3]); - }, - - - enterContent: function (incoming, offset, options) { - /// - /// - /// Execute an enter-content animation. - /// - /// - /// Single element or collection of elements which represent - /// the incoming content. - /// At the end of the animation, the opacity of the elements is 1. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the starting point of the animation. - /// If the number of offset objects is less than the length of the - /// incoming parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// Optional object which can specify the mechanism to use to play the animation. By default css - /// animations are used but if { mechanism: "transition" } is provided css transitions will be used. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, "WinJS-enterContent", [{ top: "0px", left: "40px", rtlflip: true }]); - if (options && options.mechanism === "transition") { - return thisWinUI.executeTransition( - incoming, - [{ - property: mstransform, - delay: 0, - duration: 550, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: translateCallback(offsetArray), - to: "none" - }, - { - property: "opacity", - delay: 0, - duration: 170, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: 0, - to: 1 - }]); - } else { - var promise1 = thisWinUI.executeAnimation( - incoming, - { - keyframe: offsetArray.keyframe, - property: mstransform, - delay: 0, - duration: 550, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: offsetArray.keyframe || translateCallback(offsetArray), - to: "none" - }); - var promise2 = thisWinUI.executeTransition( - incoming, - { - property: "opacity", - delay: 0, - duration: 170, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: 0, - to: 1 - }); - return WinJS.Promise.join([promise1, promise2]); - } - }, - - exitContent: function (outgoing, offset) { - /// - /// - /// Execute an exit-content animation. - /// - /// - /// Single element or collection of elements which represent - /// the outgoing content. - /// At the end of the animation, the opacity of the elements is 0. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the ending point of the animation. - /// If the number of offset objects is less than the length of the - /// outgoing parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, "WinJS-exit", [{ top: "0px", left: "0px" }]); - var promise1 = thisWinUI.executeAnimation( - outgoing, - offset && { - keyframe: offsetArray.keyframe, - property: mstransform, - delay: 0, - duration: 117, - timing: "linear", - from: "none", - to: offsetArray.keyframe || translateCallback(offsetArray) - }); - - var promise2 = thisWinUI.executeTransition( - outgoing, - { - property: "opacity", - delay: 0, - duration: 117, - timing: "linear", - to: 0 - }); - return WinJS.Promise.join([promise1, promise2]); - }, - - dragBetweenEnter: function (target, offset) { - /// - /// - /// Execute an animation which indicates that a dragged object - /// can be dropped between other elements. - /// Use the dragBetweenLeave animation to reverse the effects of this animation. - /// - /// - /// Single element or collection of elements (usually two) - /// that the dragged object can be dropped between. - /// At the end of the animation, the elements' properties have been - /// modified to reflect the drag-between state. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the ending point of the animation. - /// If the number of offset objects is less than the length of the - /// element parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, null, [{ top: "-40px", left: "0px" }, { top: "40px", left: "0px" }]); - return thisWinUI.executeTransition( - target, - { - property: mstransform, - delay: 0, - duration: 200, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: translateCallback(offsetArray, "scale(0.95) ") - }); - }, - - dragBetweenLeave: function (target) { - /// - /// - /// Execute an animation which indicates that a dragged object - /// will no longer be dropped between other elements. - /// This reverses the effect of the dragBetweenEnter animation. - /// - /// - /// Single element or collection of elements (usually two) - /// that the dragged object no longer will be dropped between. - /// At the end of the animation, the elements' properties have been - /// set to the dragSourceStart state. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - return thisWinUI.executeTransition( - target, - { - property: mstransform, - delay: 0, - duration: 200, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "scale(0.95)" - }); - }, - - swipeSelect: function (selected, selection) { - /// - /// - /// Slide a swipe-selected object back into position when the - /// pointer is released, and show the selection mark. - /// - /// - /// Single element or collection of elements being selected. - /// At the end of the animation, the elements' properties have been - /// returned to normal. - /// - /// - /// Single element or collection of elements that is the selection mark. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var promise1 = thisWinUI.executeTransition( - selected, - { - property: mstransform, - delay: 0, - duration: 300, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - - var promise2 = thisWinUI.executeAnimation( - selection, - { - keyframe: "WinJS-opacity-in", - property: "opacity", - delay: 0, - duration: 300, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: 0, - to: 1 - }); - return WinJS.Promise.join([promise1, promise2]); - }, - - swipeDeselect: function (deselected, selection) { - /// - /// - /// Slide a swipe-deselected object back into position when the - /// pointer is released, and hide the selection mark. - /// - /// - /// Single element or collection of elements being deselected. - /// At the end of the animation, the elements' properties have been - /// returned to normal. - /// - /// - /// Single element or collection of elements that is the selection mark. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var promise1 = thisWinUI.executeTransition( - deselected, - { - property: mstransform, - delay: 0, - duration: 300, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - }); - - var promise2 = thisWinUI.executeAnimation( - selection, - { - keyframe: "WinJS-opacity-out", - property: "opacity", - delay: 0, - duration: 300, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: 1, - to: 0 - }); - return WinJS.Promise.join([promise1, promise2]); - }, - - swipeReveal: function (target, offset) { - /// - /// - /// Reveal an object as the result of a swipe, or slide the - /// swipe-selected object back into position after the reveal. - /// - /// - /// Single element or collection of elements being selected. - /// At the end of the animation, the elements' properties have been - /// modified to reflect the specified offset. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the ending point of the animation. - /// When moving the object back into position, the offset should be - /// { top: "0px", left: "0px" }. - /// If the number of offset objects is less than the length of the - /// element parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// The default value describes the motion for a reveal. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, null, [{ top: "25px", left: "0px" }]); - return thisWinUI.executeTransition( - target, - { - property: mstransform, - delay: 0, - duration: 300, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: translateCallback(offsetArray) - }); - }, - - enterPage: function (element, offset) { - /// - /// - /// Execute an enterPage animation. - /// - /// - /// Single element or collection of elements representing the - /// incoming page. - /// At the end of the animation, the opacity of the elements is 1. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the starting point of the animation. - /// If the number of offset objects is less than the length of the - /// element parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, "WinJS-enterPage", [{ top: "0px", left: "100px", rtlflip: true }]); - var promise1 = thisWinUI.executeAnimation( - element, - { - keyframe: offsetArray.keyframe, - property: mstransform, - delay: staggerDelay(0, 83, 1, 333), - duration: 1000, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: offsetArray.keyframe || translateCallback(offsetArray), - to: "none" - }); - var promise2 = thisWinUI.executeTransition( - element, - { - property: "opacity", - delay: staggerDelay(0, 83, 1, 333), - duration: 170, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: 0, - to: 1 - }); - return WinJS.Promise.join([promise1, promise2]); - }, - - exitPage: function (outgoing, offset) { - /// - /// - /// Execute an exitPage animation. - /// - /// - /// Single element or collection of elements representing - /// the outgoing page. - /// At the end of the animation, the opacity of the elements is 0. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the ending point of the animation. - /// If the number of offset objects is less than the length of the - /// outgoing parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, "WinJS-exit", [{ top: "0px", left: "0px" }]); - var promise1 = thisWinUI.executeAnimation( - outgoing, - offset && { - keyframe: offsetArray.keyframe, - property: mstransform, - delay: 0, - duration: 117, - timing: "linear", - from: "none", - to: offsetArray.keyframe || translateCallback(offsetArray) - }); - - var promise2 = thisWinUI.executeTransition( - outgoing, - { - property: "opacity", - delay: 0, - duration: 117, - timing: "linear", - to: 0 - }); - return WinJS.Promise.join([promise1, promise2]); - }, - - crossFade: function (incoming, outgoing) { - /// - /// - /// Execute a crossFade animation. - /// - /// - /// Single incoming element or collection of incoming elements. - /// At the end of the animation, the opacity of the elements is 1. - /// - /// - /// Single outgoing element or collection of outgoing elements. - /// At the end of the animation, the opacity of the elements is 0. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var promise1 = thisWinUI.executeTransition( - incoming, - { - property: "opacity", - delay: 0, - duration: 167, - timing: "linear", - to: 1 - }); - - var promise2 = thisWinUI.executeTransition( - outgoing, - { - property: "opacity", - delay: 0, - duration: 167, - timing: "linear", - to: 0 - }); - return WinJS.Promise.join([promise1, promise2]); - }, - - createPeekAnimation: function (element) { - /// - /// - /// Creates a peek animation. - /// After creating the PeekAnimation object, - /// modify the document to move the elements to their new positions, - /// then call the execute method on the PeekAnimation object. - /// - /// - /// Single element or collection of elements to be repositioned for peek. - /// - /// - /// PeekAnimation object whose execute method returns - /// a Promise that completes when the animation is complete. - /// - /// - return layoutTransition(PeekAnimation, null, element); - }, - - updateBadge: function (incoming, offset) { - /// - /// - /// Execute an updateBadge animation. - /// - /// - /// Single element or collection of elements representing the - /// incoming badge. - /// - /// - /// Optional offset object or collection of offset objects - /// array describing the starting point of the animation. - /// If the number of offset objects is less than the length of the - /// incoming parameter, then the last value is repeated for all - /// remaining elements. - /// If this parameter is omitted, then a default value is used. - /// - /// - /// Promise object that completes when the animation is complete. - /// - /// - var offsetArray = new OffsetArray(offset, "WinJS-updateBadge", [{ top: "24px", left: "0px" }]); - return thisWinUI.executeAnimation( - incoming, - [{ - keyframe: "WinJS-opacity-in", - property: "opacity", - delay: 0, - duration: 367, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: 0, - to: 1 - }, - { - keyframe: offsetArray.keyframe, - property: mstransform, - delay: 0, - duration: 1333, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - from: offsetArray.keyframe || translateCallback(offsetArray), - to: "none" - }]); - } - }); - -})(WinJS); - -/*#DBG -var _ASSERT = function (condition) { - if (!condition) { - throw "ASSERT FAILED"; - } -}; -var _TRACE = function (text) { - if (window.console && console.log) { - console.log(text); - } -}; -#DBG*/ - - -// WinJS.Binding.ListDataSource -// -(function bindingListDataSourceInit(global, undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.Binding", { - _BindingListDataSource: WinJS.Namespace._lazy(function () { - var errors = { - get noLongerMeaningful() { return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.EditError.noLongerMeaningful)); } - }; - - function findNextKey(list, index) { - var len = list.length; - while (index < len - 1) { - var item = list.getItem(++index); - if (item) { - return item.key; - } - } - return null; - } - - function findPreviousKey(list, index) { - while (index > 0) { - var item = list.getItem(--index); - if (item) { - return item.key; - } - } - return null; - } - - function subscribe(target, handlers) { - Object.keys(handlers).forEach(function (handler) { - target.addEventListener(handler, handlers[handler]); - }); - } - - function unsubscribe(target, handlers) { - Object.keys(handlers).forEach(function (handler) { - target.removeEventListener(handler, handlers[handler]); - }); - } - - var CompletePromise = WinJS.Promise.wrap().constructor; - - var NullWrappedItem = WinJS.Class.derive(CompletePromise, - function () { - this._value = null; - }, { - release: function () { }, - retain: function () { return this; } - }, { - supportedForProcessing: false, - } - ); - - var WrappedItem = WinJS.Class.derive(CompletePromise, - function (listBinding, item) { - this._value = item; - this._listBinding = listBinding; - }, { - handle: { - get: function () { return this._value.key; } - }, - index: { - get: function () { return this._value.index; } - }, - release: function () { - this._listBinding._release(this._value, this._listBinding._list.indexOfKey(this._value.key)); - }, - retain: function () { - this._listBinding._addRef(this._value, this._listBinding._list.indexOfKey(this._value.key)); - return this; - } - }, { - supportedForProcessing: false, - } - ); - - var AsyncWrappedItem = WinJS.Class.derive(WinJS.Promise, - function (listBinding, item, name) { - var that = this; - this._item = item; - this._listBinding = listBinding; - WinJS.Promise.call(this, function (c) { - WinJS.Utilities.Scheduler.schedule(function () { - if (listBinding._released) { - that.cancel(); - return; - } - c(item); - }, WinJS.Utilities.Scheduler.Priority.normal, null, "WinJS.Binding.List." + name); - }); - }, { - handle: { - get: function () { return this._item.key; } - }, - index: { - get: function () { return this._item.index; } - }, - release: function () { - this._listBinding._release(this._item, this._listBinding._list.indexOfKey(this._item.key)); - }, - retain: function () { - this._listBinding._addRef(this._item, this._listBinding._list.indexOfKey(this._item.key)); - return this; - } - }, { - supportedForProcessing: false, - } - ); - - function wrap(listBinding, item) { - return item ? new WrappedItem(listBinding, item) : new NullWrappedItem(); - } - - function wrapAsync(listBinding, item, name) { - return item ? new AsyncWrappedItem(listBinding, item, name) : new NullWrappedItem(); - } - - function cloneWithIndex(list, item, index) { - return item && list._annotateWithIndex(item, index); - } - - var ListBinding = WinJS.Class.define(function ListBinding_ctor(dataSource, list, notificationHandler, id) { - this._dataSource = dataSource; - this._list = list; - this._editsCount = 0; - this._notificationHandler = notificationHandler; - this._pos = -1; - this._retained = []; - this._retained.length = list.length; - this._retainedKeys = {}; - this._affectedRange = null; - // When in WebContext, weakref utility functions don't work as desired so we capture this - // ListBinding object in the handler's closure. This causes the same leak as in 1.0. - var fallbackReference = null; - if (!WinJS.Utilities.hasWinRT || !global.msSetWeakWinRTProperty || !global.msGetWeakWinRTProperty) { - fallbackReference = this; - } - if (notificationHandler) { - var handleEvent = function (eventName, eventArg) { - var lb = WinJS.Utilities._getWeakRefElement(id) || fallbackReference; - if (lb) { - lb["_" + eventName](eventArg); - return true; - } - return false; - }; - - this._handlers = { - itemchanged: function handler(event) { - if (!handleEvent("itemchanged", event)) { - list.removeEventListener("itemchanged", handler); - } - }, - iteminserted: function handler(event) { - if (!handleEvent("iteminserted", event)) { - list.removeEventListener("iteminserted", handler); - } - }, - itemmoved: function handler(event) { - if (!handleEvent("itemmoved", event)) { - list.removeEventListener("itemmoved", handler); - } - }, - itemremoved: function handler(event) { - if (!handleEvent("itemremoved", event)) { - list.removeEventListener("itemremoved", handler); - } - }, - reload: function handler() { - if (!handleEvent("reload")) { - list.removeEventListener("reload", handler); - } - } - }; - subscribe(this._list, this._handlers); - } - }, { - _itemchanged: function (event) { - var key = event.detail.key; - var index = event.detail.index; - this._updateAffectedRange(index, "changed"); - var newItem = event.detail.newItem; - var oldItem = this._retained[index]; - if (oldItem) { - var handler = this._notificationHandler; - if (oldItem.index !== index) { - var oldIndex = oldItem.index; - oldItem.index = index; - if (handler && handler.indexChanged) { - handler.indexChanged(newItem.key, index, oldIndex); - } - } - newItem = cloneWithIndex(this._list, newItem, index); - newItem._retainedCount = oldItem._retainedCount; - this._retained[index] = newItem; - this._retainedKeys[key] = newItem; - - this._beginEdits(this._list.length); - if (handler && handler.changed) { - handler.changed( - newItem, - oldItem - ); - } - this._endEdits(); - } else { - // Item was not retained, but we still want to batch this change with the other edits to send the affectedRange notification. - this._beginEdits(this._list.length); - this._endEdits(); - } - }, - - _iteminserted: function (event) { - var key = event.detail.key; - var index = event.detail.index; - this._updateAffectedRange(index, "inserted"); - this._beginEdits(this._list.length - 1); - if (index <= this._pos) { - this._pos = Math.min(this._pos + 1, this._list.length); - } - var retained = this._retained; - // create a hole for this thing and then immediately make it undefined - retained.splice(index, 0, 0); - delete retained[index]; - if (this._shouldNotify(index) || this._list.length === 1) { - var handler = this._notificationHandler; - if (handler && handler.inserted) { - handler.inserted( - wrap(this, cloneWithIndex(this._list, this._list.getItem(index), index)), - findPreviousKey(this._list, index), - findNextKey(this._list, index) - ); - } - } - this._endEdits(); - }, - - _itemmoved: function (event) { - var key = event.detail.key; - var oldIndex = event.detail.oldIndex; - var newIndex = event.detail.newIndex; - this._updateAffectedRange(oldIndex, "moved"); - this._updateAffectedRange(newIndex, "moved"); - this._beginEdits(this._list.length); - if (oldIndex < this._pos || newIndex <= this._pos) { - if (newIndex > this._pos) { - this._pos = Math.max(-1, this._pos - 1); - } else if (oldIndex > this._pos) { - this._pos = Math.min(this._pos + 1, this._list.length); - } - } - var retained = this._retained; - var item = retained.splice(oldIndex, 1)[0]; - retained.splice(newIndex, 0, item); - if (!item) { - delete retained[newIndex]; - item = cloneWithIndex(this._list, this._list.getItem(newIndex), newIndex); - } - item._moved = true; - this._addRef(item, newIndex); - this._endEdits(); - }, - - _itemremoved: function (event) { - var key = event.detail.key; - var index = event.detail.index; - this._updateAffectedRange(index, "removed"); - this._beginEdits(this._list.length + 1); - if (index < this._pos) { - this._pos = Math.max(-1, this._pos - 1); - } - var retained = this._retained; - var retainedKeys = this._retainedKeys; - var wasRetained = index in retained; - retained.splice(index, 1); - delete retainedKeys[key]; - var handler = this._notificationHandler; - if (wasRetained && handler && handler.removed) { - handler.removed(key, false); - } - this._endEdits(); - }, - - _reload: function () { - this._retained = []; - this._retainedKeys = {}; - var handler = this._notificationHandler; - if (handler && handler.reload) { - handler.reload(); - } - }, - - _addRef: function (item, index) { - if (index in this._retained) { - this._retained[index]._retainedCount++; - } else { - this._retained[index] = item; - this._retainedKeys[item.key] = item; - item._retainedCount = 1; - } - }, - _release: function (item, index) { - var retained = this._retained[index]; - if (retained) { - //#DBG _ASSERT(retained.key === item.key); - if (retained._retainedCount === 1) { - delete this._retained[index]; - delete this._retainedKeys[retained.key]; - } else { - retained._retainedCount--; - } - } - /*#DBG - // If an item isn't found in the retained map, it was either removed from retainedCount reaching zero, or removed from the map by a removed notification. - // We'll decrement the count here for debugging purposes. If retainedCount is less than zero, there's a refcounting error somewhere. - if (!retained) { - item._retainedCount--; - _ASSERT(item._retainedCount >= 0); - } - #DBG*/ - }, - _shouldNotify: function (index) { - var retained = this._retained; - return index in retained || index + 1 in retained || index - 1 in retained; - }, - - _updateAffectedRange: function ListBinding_updateAffectedRange(index, operation) { - // Creates a range of affected indices [start, end). - // Definition of _affectedRange.start: All items in the set of data with indices < _affectedRange.start have not been directly modified. - // Definition of _affectedRange.end: All items in the set of data with indices >= _affectedRange.end have not been directly modified. - - if (!this._notificationHandler.affectedRange) { - return; - } - - //[newStart, newEnd) - var newStart = index; - var newEnd = (operation !== "removed") ? - index + 1 : index; - - if (this._affectedRange) { - switch (operation) { - case "inserted": - if (index <= this._affectedRange.end) { - ++this._affectedRange.end; - } - break; - case "removed": - if (index < this._affectedRange.end) { - --this._affectedRange.end; - } - break; - case "moved": - case "changed": - break; - } - this._affectedRange.start = Math.min(this._affectedRange.start, newStart); - this._affectedRange.end = Math.max(this._affectedRange.end, newEnd); - } else { - // Handle the initial state - this._affectedRange = { start: newStart, end: newEnd }; - } - }, - - _notifyAffectedRange: function ListBinding_notifyAffectedRange() { - if (this._affectedRange) { - if (this._notificationHandler && this._notificationHandler.affectedRange) { - this._notificationHandler.affectedRange(this._affectedRange); - } - // reset range - this._affectedRange = null; - } - }, - _notifyCountChanged: function () { - var oldCount = this._countAtBeginEdits; - var newCount = this._list.length; - if (oldCount !== newCount) { - var handler = this._notificationHandler; - if (handler && handler.countChanged) { - handler.countChanged(newCount, oldCount); - } - } - }, - _notifyIndicesChanged: function () { - var retained = this._retained; - for (var i = 0, len = retained.length; i < len; i++) { - var item = retained[i]; - if (item && item.index !== i) { - var newIndex = i; - var oldIndex = item.index; - item.index = newIndex; - var handler = this._notificationHandler; - if (handler && handler.indexChanged) { - handler.indexChanged(item.key, newIndex, oldIndex); - } - } - } - }, - _notifyMoved: function () { - var retained = this._retained; - for (var i = 0, len = retained.length; i < len; i++) { - var item = retained[i]; - if (item && item._moved) { - item._moved = false; - this._release(item, i); - if (this._shouldNotify(i)) { - var handler = this._notificationHandler; - if (handler && handler.moved) { - handler.moved( - wrap(this, item), - findPreviousKey(this._list, i), - findNextKey(this._list, i) - ); - } - } - } - } - }, - - _beginEdits: function (length, explicit) { - this._editsCount++; - var handler = this._notificationHandler; - if (this._editsCount === 1 && handler) { - if (!explicit) { - // Batch all edits between now and the job running. This has the effect - // of batching synchronous edits. - // - this._editsCount++; - var that = this; - WinJS.Utilities.Scheduler.schedule(function () { - that._endEdits(); - }, WinJS.Utilities.Scheduler.Priority.high, null, "WinJS.Binding.List._endEdits"); - } - if (handler.beginNotifications) { - handler.beginNotifications(); - } - this._countAtBeginEdits = length; - } - }, - _endEdits: function () { - this._editsCount--; - var handler = this._notificationHandler; - if (this._editsCount === 0 && handler) { - this._notifyIndicesChanged(); - this._notifyMoved(); - this._notifyCountChanged(); - // It's important to notify the affectedRange after _notifyCountChanged since we expect developers - // may take a dependancy on the count being up to date when they recieve the affected range. - this._notifyAffectedRange(); - if (handler.endNotifications) { - handler.endNotifications(); - } - } - }, - - jumpToItem: function (item) { - var index = this._list.indexOfKey(item.handle); - if (index === -1) { - return WinJS.Promise.wrap(null); - } - this._pos = index; - return this.current(); - }, - current: function () { - return this.fromIndex(this._pos); - }, - previous: function () { - this._pos = Math.max(-1, this._pos - 1); - return this._fromIndex(this._pos, true, "previous"); - }, - next: function () { - this._pos = Math.min(this._pos + 1, this._list.length); - return this._fromIndex(this._pos, true, "next"); - }, - releaseItem: function (item) { - if (item.release) { - item.release(); - } else { - this._release(item, this._list.indexOfKey(item.key)); - } - }, - release: function () { - if (this._notificationHandler) { - unsubscribe(this._list, this._handlers); - } - this._notificationHandler = null; - this._dataSource._releaseBinding(this); - this._released = true; - }, - first: function () { - return this.fromIndex(0); - }, - last: function () { - return this.fromIndex(this._list.length - 1); - }, - fromKey: function (key) { - var retainedKeys = this._retainedKeys; - var item; - if (key in retainedKeys) { - item = retainedKeys[key]; - } else { - item = cloneWithIndex(this._list, this._list.getItemFromKey(key), this._list.indexOfKey(key)); - } - return wrap(this, item); - }, - fromIndex: function (index) { - return this._fromIndex(index, false, "fromIndex"); - }, - _fromIndex: function (index, async, name) { - var retained = this._retained; - var item; - if (index in retained) { - item = retained[index]; - } else { - item = cloneWithIndex(this._list, this._list.getItem(index), index); - } - return async ? wrapAsync(this, item, name) : wrap(this, item); - }, - }, { - supportedForProcessing: false, - }); - - function insertAtStart(unused, data) { - // List ignores the key because its key management is internal - this._list.unshift(data); - return this.itemFromIndex(0); - } - function insertBefore(unused, data, nextKey) { - // List ignores the key because its key management is internal - var index = this._list.indexOfKey(nextKey); - if (index === -1) { - return errors.noLongerMeaningful; - } - this._list.splice(index, 0, data); - return this.itemFromIndex(index); - } - function insertAfter(unused, data, previousKey) { - // List ignores the key because its key management is internal - var index = this._list.indexOfKey(previousKey); - if (index === -1) { - return errors.noLongerMeaningful; - } - index += 1; - this._list.splice(index, 0, data); - return this.itemFromIndex(index); - } - function insertAtEnd(unused, data) { - // List ignores the key because its key management is internal - this._list.push(data); - return this.itemFromIndex(this._list.length - 1); - } - function change(key, newData) { - var index = this._list.indexOfKey(key); - if (index === -1) { - return errors.noLongerMeaningful; - } - this._list.setAt(index, newData); - return this.itemFromIndex(index); - } - function moveToStart(key) { - var sourceIndex = this._list.indexOfKey(key); - if (sourceIndex === -1) { - return errors.noLongerMeaningful; - } - var targetIndex = 0; - this._list.move(sourceIndex, targetIndex); - return this.itemFromIndex(targetIndex); - } - function moveBefore(key, nextKey) { - var sourceIndex = this._list.indexOfKey(key); - var targetIndex = this._list.indexOfKey(nextKey); - if (sourceIndex === -1 || targetIndex === -1) { - return errors.noLongerMeaningful; - } - targetIndex = sourceIndex < targetIndex ? targetIndex - 1 : targetIndex; - this._list.move(sourceIndex, targetIndex); - return this.itemFromIndex(targetIndex); - } - function moveAfter(key, previousKey) { - var sourceIndex = this._list.indexOfKey(key); - var targetIndex = this._list.indexOfKey(previousKey); - if (sourceIndex === -1 || targetIndex === -1) { - return errors.noLongerMeaningful; - } - targetIndex = sourceIndex <= targetIndex ? targetIndex : targetIndex + 1; - this._list.move(sourceIndex, targetIndex); - return this.itemFromIndex(targetIndex); - } - function moveToEnd(key) { - var sourceIndex = this._list.indexOfKey(key); - if (sourceIndex === -1) { - return errors.noLongerMeaningful; - } - var targetIndex = this._list.length - 1; - this._list.move(sourceIndex, targetIndex); - return this.itemFromIndex(targetIndex); - } - function remove(key) { - var index = this._list.indexOfKey(key); - if (index === -1) { - return errors.noLongerMeaningful; - } - this._list.splice(index, 1); - return WinJS.Promise.wrap(); - } - - var bindingId = 0; - var DataSource = WinJS.Class.define(function DataSource_ctor(list) { - this._usingWeakRef = WinJS.Utilities.hasWinRT && global.msSetWeakWinRTProperty && global.msGetWeakWinRTProperty; - this._bindings = {}; - this._list = list; - - if (list.unshift) { - this.insertAtStart = insertAtStart; - } - if (list.push) { - this.insertAtEnd = insertAtEnd; - } - if (list.setAt) { - this.change = change; - } - if (list.splice) { - this.insertAfter = insertAfter; - this.insertBefore = insertBefore; - this.remove = remove; - } - if (list.move) { - this.moveAfter = moveAfter; - this.moveBefore = moveBefore; - this.moveToEnd = moveToEnd; - this.moveToStart = moveToStart; - } - }, { - _releaseBinding: function (binding) { - delete this._bindings[binding._id]; - }, - - addEventListener: function () { - // nop, we don't send statusChanged - }, - removeEventListener: function () { - // nop, we don't send statusChanged - }, - - createListBinding: function (notificationHandler) { - var id = "ds_" + (++bindingId); - var binding = new ListBinding(this, this._list, notificationHandler, id); - binding._id = id; - - if (this._usingWeakRef) { - WinJS.Utilities._createWeakRef(binding, id); - this._bindings[id] = id; - } else { - this._bindings[id] = binding; - } - - return binding; - }, - - getCount: function () { - return WinJS.Promise.wrap(this._list.length); - }, - - itemFromKey: function (key) { - // Clone with a dummy index - var list = this._list, - item = cloneWithIndex(list, list.getItemFromKey(key), -1); - - // Override the index property with a getter - Object.defineProperty(item, "index", { - get: function () { - return list.indexOfKey(key); - }, - enumerable: false, - configurable: true - }); - - return WinJS.Promise.wrap(item); - }, - itemFromIndex: function (index) { - return WinJS.Promise.wrap(cloneWithIndex(this._list, this._list.getItem(index), index)); - }, - - list: { - get: function () { return this._list; } - }, - - beginEdits: function () { - var length = this._list.length; - this._forEachBinding(function (binding) { - binding._beginEdits(length, true); - }); - }, - endEdits: function () { - this._forEachBinding(function (binding) { - binding._endEdits(); - }); - }, - _forEachBinding: function (callback) { - if (this._usingWeakRef) { - var toBeDeleted = []; - Object.keys(this._bindings).forEach(function (id) { - var lb = WinJS.Utilities._getWeakRefElement(id); - if (lb) { - callback(lb); - } else { - toBeDeleted.push(id); - } - }); - for (var i = 0, len = toBeDeleted.length; i < len; i++) { - delete this._bindings[toBeDeleted[i]]; - } - } else { - var that = this; - Object.keys(this._bindings).forEach(function (id) { - callback(that._bindings[id]); - }); - } - }, - - invalidateAll: function () { - return WinJS.Promise.wrap(); - }, - - // - // insert* and change are not implemented as I don't understand how they are - // used by the controls since it is hard to fathom how they would be able - // to make up unique keys. Manual editing of the List is meant to go through - // the list itself. - // - // move* are implemented only if the underlying list supports move(). The - // GroupsListProjection for instance does not. - // - moveAfter: undefined, - moveBefore: undefined, - moveToEnd: undefined, - moveToStart: undefined - - }, { - supportedForProcessing: false, - }); - return DataSource; - }) - }); - -}(this)); - -// Virtualized Data Source - -(function listDataSourceInit(undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - - DataSourceStatus: { - ready: "ready", - waiting: "waiting", - failure: "failure" - }, - - CountResult: { - unknown: "unknown" - }, - - CountError: { - noResponse: "noResponse" - }, - - FetchError: { - noResponse: "noResponse", - doesNotExist: "doesNotExist" - }, - - EditError: { - noResponse: "noResponse", - canceled: "canceled", - notPermitted: "notPermitted", - noLongerMeaningful: "noLongerMeaningful" - }, - - VirtualizedDataSource: WinJS.Namespace._lazy(function () { - var MAX_BEGINREFRESH_COUNT = 100; - var uniqueID = 1; - - var Promise = WinJS.Promise, - Signal = WinJS._Signal, - Scheduler = WinJS.Utilities.Scheduler, - UI = WinJS.UI; - - // Private statics - - var strings = { - get listDataAdapterIsInvalid() { return WinJS.Resources._getWinJSString("ui/listDataAdapterIsInvalid").value; }, - get indexIsInvalid() { return WinJS.Resources._getWinJSString("ui/indexIsInvalid").value; }, - get keyIsInvalid() { return WinJS.Resources._getWinJSString("ui/keyIsInvalid").value; }, - get invalidItemReturned() { return WinJS.Resources._getWinJSString("ui/undefinedItemReturned").value; }, - get invalidKeyReturned() { return WinJS.Resources._getWinJSString("ui/invalidKeyReturned").value; }, - get invalidIndexReturned() { return WinJS.Resources._getWinJSString("ui/invalidIndexReturned").value; }, - get invalidCountReturned() { return WinJS.Resources._getWinJSString("ui/invalidCountReturned").value; }, - get invalidRequestedCountReturned() { return WinJS.Resources._getWinJSString("ui/invalidRequestedCountReturned").value; }, - get refreshCycleIdentified() { return WinJS.Resources._getWinJSString("ui/refreshCycleIdentified").value; }, - }; - - var statusChangedEvent = "statuschanged"; - - function _baseDataSourceConstructor(listDataAdapter, options) { - /// - /// - /// Initializes the VirtualizedDataSource base class of a custom data source. - /// - /// - /// An object that implements IListDataAdapter and supplies data to the VirtualizedDataSource. - /// - /// - /// An object that contains properties that specify additonal options for the VirtualizedDataSource: - /// - /// cacheSize - /// A Number that specifies minimum number of unrequested items to cache in case they are requested. - /// - /// The options parameter is optional. - /// - /// - - // Private members - - var listDataNotificationHandler, - cacheSize, - status, - statusPending, - statusChangePosted, - bindingMap, - nextListBindingID, - nextHandle, - nextListenerID, - getCountPromise, - resultsProcessed, - beginEditsCalled, - editsInProgress, - firstEditInProgress, - editQueue, - editsQueued, - synchronousEdit, - waitForRefresh, - dataNotificationsInProgress, - countDelta, - indexUpdateDeferred, - nextTempKey, - currentRefreshID, - fetchesPosted, - nextFetchID, - fetchesInProgress, - fetchCompleteCallbacks, - startMarker, - endMarker, - knownCount, - slotsStart, - slotListEnd, - slotsEnd, - handleMap, - keyMap, - indexMap, - releasedSlots, - lastSlotReleased, - reduceReleasedSlotCountPosted, - refreshRequested, - refreshInProgress, - refreshSignal, - refreshFetchesInProgress, - refreshItemsFetched, - refreshCount, - refreshStart, - refreshEnd, - keyFetchIDs, - refreshKeyMap, - refreshIndexMap, - deletedKeys, - synchronousProgress, - reentrantContinue, - synchronousRefresh, - reentrantRefresh; - - var beginRefreshCount = 0, - refreshHistory = new Array(100), - refreshHistoryPos = -1; - - var itemsFromKey, - itemsFromIndex, - itemsFromStart, - itemsFromEnd, - itemsFromDescription; - - if (listDataAdapter.itemsFromKey) { - itemsFromKey = function (fetchID, key, countBefore, countAfter, hints) { - var perfID = "fetchItemsFromKey id=" + fetchID + " key=" + key + " countBefore=" + countBefore + " countAfter=" + countAfter; - profilerMarkStart(perfID); - refreshHistory[++refreshHistoryPos % refreshHistory.length] = { kind: "itemsFromKey", key: key, countBefore: countBefore, countAfter: countAfter }; - var result = listDataAdapter.itemsFromKey(key, countBefore, countAfter, hints); - profilerMarkEnd(perfID); - return result; - }; - } - if (listDataAdapter.itemsFromIndex) { - itemsFromIndex = function (fetchID, index, countBefore, countAfter) { - var perfID = "fetchItemsFromIndex id=" + fetchID + " index=" + index + " countBefore=" + countBefore + " countAfter=" + countAfter; - profilerMarkStart(perfID); - refreshHistory[++refreshHistoryPos % refreshHistory.length] = { kind: "itemsFromIndex", index: index, countBefore: countBefore, countAfter: countAfter }; - var result = listDataAdapter.itemsFromIndex(index, countBefore, countAfter); - profilerMarkEnd(perfID); - return result; - }; - } - if (listDataAdapter.itemsFromStart) { - itemsFromStart = function (fetchID, count) { - var perfID = "fetchItemsFromStart id=" + fetchID + " count=" + count; - profilerMarkStart(perfID); - refreshHistory[++refreshHistoryPos % refreshHistory.length] = { kind: "itemsFromStart", count: count }; - var result = listDataAdapter.itemsFromStart(count); - profilerMarkEnd(perfID); - return result; - }; - } - if (listDataAdapter.itemsFromEnd) { - itemsFromEnd = function (fetchID, count) { - var perfID = "fetchItemsFromEnd id=" + fetchID + " count=" + count; - profilerMarkStart(perfID); - refreshHistory[++refreshHistoryPos % refreshHistory.length] = { kind: "itemsFromEnd", count: count }; - var result = listDataAdapter.itemsFromEnd(count); - profilerMarkEnd(perfID); - return result; - }; - } - if (listDataAdapter.itemsFromDescription) { - itemsFromDescription = function (fetchID, description, countBefore, countAfter) { - var perfID = "fetchItemsFromDescription id=" + fetchID + " desc=" + description + " countBefore=" + countBefore + " countAfter=" + countAfter; - profilerMarkStart(perfID); - refreshHistory[++refreshHistoryPos % refreshHistory.length] = { kind: "itemsFromDescription", description: description, countBefore: countBefore, countAfter: countAfter }; - var result = listDataAdapter.itemsFromDescription(description, countBefore, countAfter); - profilerMarkEnd(perfID); - return result; - }; - } - - var dataSourceID = ++uniqueID; - - function profilerMarkStart(text) { - var message = "WinJS.UI.VirtualizedDataSource:" + dataSourceID + ":" + text + ",StartTM"; - msWriteProfilerMark(message); - WinJS.log && WinJS.log(message, "winjs vds", "perf"); - } - function profilerMarkEnd(text) { - var message = "WinJS.UI.VirtualizedDataSource:" + dataSourceID + ":" + text + ",StopTM"; - msWriteProfilerMark(message); - WinJS.log && WinJS.log(message, "winjs vds", "perf"); - } - - /*#DBG - - var totalSlots = 0; - - function VERIFYLIST() { - _ASSERT(slotListEnd.lastInSequence); - _ASSERT(slotsEnd.firstInSequence); - checkListIntegrity(slotsStart, slotsEnd, keyMap, indexMap); - } - - function VERIFYREFRESHLIST() { - checkListIntegrity(refreshStart, refreshEnd, refreshKeyMap, refreshIndexMap); - } - - function checkListIntegrity(listStart, listEnd, keyMapForSlot, indexMapForSlot) { - if (UI.VirtualizedDataSource._internalValidation) { - var listEndReached, - slotWithoutIndexReached; - for (var slotCheck = listStart; slotCheck !== listEnd; slotCheck = slotCheck.next) { - _ASSERT(slotCheck.next); - _ASSERT(slotCheck.next.prev === slotCheck); - if (slotCheck.lastInSequence) { - _ASSERT(slotCheck.next.firstInSequence); - } - - if (slotCheck !== listStart) { - _ASSERT(slotCheck.prev); - _ASSERT(slotCheck.prev.next === slotCheck); - if (slotCheck.firstInSequence) { - _ASSERT(slotCheck.prev.lastInSequence); - } - } - - if (slotCheck.item || slotCheck.itemNew) { - _ASSERT(editsQueued || slotCheck.key); - } - - if (slotCheck.key) { - _ASSERT(keyMapForSlot[slotCheck.key] === slotCheck); - - if (slotCheck.item) { - _ASSERT(slotCheck.item.key === slotCheck.key); - } - } - - if (typeof slotCheck.index === "number") { - _ASSERT(!listEndReached); - - if (!indexUpdateDeferred) { - _ASSERT(indexMapForSlot[slotCheck.index] === slotCheck); - _ASSERT(slotCheck === listStart || slotCheck.prev.index < slotCheck.index); - _ASSERT(!slotCheck.firstInSequence || !slotCheck.prev || slotCheck.prev.index !== slotCheck.index - 1); - _ASSERT(!slotCheck.lastInSequence || !slotCheck.next || slotCheck.next.index !== slotCheck.index + 1); - - if (slotCheck.item) { - _ASSERT(listStart === refreshStart || slotCheck.item.index === slotCheck.index); - } - } - } else { - slotWithoutIndexReached = true; - } - - if (slotCheck === slotListEnd) { - listEndReached = true; - } - - if (slotCheck.lastInSequence && !listEndReached && !indexUpdateDeferred) { - _ASSERT(!slotWithoutIndexReached); - } - } - } - } - - function OUTPUTLIST() { - outputList("Main List", slotsStart); - } - - function OUTPUTREFRESHLIST() { - outputList("Refresh List", refreshStart); - } - - function outputList(header, slotFirst) { - _TRACE("-- " + header + " --"); - - for (var slot = slotFirst; slot; slot = slot.next) { - var line = (slot.firstInSequence ? "[" : " "); - - if (slot.index !== undefined && slot !== slotsStart && slot !== refreshStart) { - line += slot.index + ": "; - } - - if (slot === slotsStart || slot === refreshStart) { - line += "{"; - } else if (slot === slotListEnd || slot === refreshEnd) { - line += "}"; - } else if (slot === slotsEnd) { - line += "-"; - } else { - line += (slot.key ? '"' + slot.key + '"' : "?"); - } - - if (slot.bindingMap) { - line += " ("; - var first = true; - for (var listBindingID in slot.bindingMap) { - if (first) { - first = false; - } else { - line += ", "; - } - - line += listBindingID; - } - line += ")"; - } - - if (slot.itemNew) { - line += " itemNew"; - } - - if (slot.item) { - line += " item"; - } - - if (slot.fetchListeners) { - line += " fetching"; - } - - if (slot.directFetchListeners) { - line += " directFetching"; - } - - if (slot.indexRequested) { - line += " index"; - } - - if (slot.keyRequested) { - line += " key"; - } - - if (slot.description) { - line += " description=" + JSON.stringify(slot.description); - } - - if (slotFetchInProgress(slot)) { - line += " now"; - } - - if (typeof slot.handle === "string") { - line += " <" + slot.handle + ">"; - } - - if (slot.lastInSequence) { - line += "]"; - } - - _TRACE(line); - } - } - - #DBG*/ - - function isNonNegativeNumber(n) { - return (typeof n === "number") && n >= 0; - } - - function isNonNegativeInteger(n) { - return isNonNegativeNumber(n) && n === Math.floor(n); - } - - function validateIndexReturned(index) { - // Ensure that index is always undefined or a non-negative integer - if (index === null) { - index = undefined; - } else if (index !== undefined && !isNonNegativeInteger(index)) { - throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.InvalidIndexReturned", strings.invalidIndexReturned); - } - - return index; - } - - function validateCountReturned(count) { - // Ensure that count is always undefined or a non-negative integer - if (count === null) { - count = undefined; - } else if (count !== undefined && !isNonNegativeInteger(count) && count !== CountResult.unknown) { - throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.InvalidCountReturned", strings.invalidCountReturned); - } - - return count; - } - - // Slot List - - function createSlot() { - var handle = (nextHandle++).toString(), - slotNew = { - handle: handle, - item: null, - itemNew: null, - fetchListeners: null, - cursorCount: 0, - bindingMap: null - }; - - // Deliberately not initialized: - // - directFetchListeners - - handleMap[handle] = slotNew; - - return slotNew; - } - - function createPrimarySlot() { - /*#DBG - totalSlots++; - #DBG*/ - - return createSlot(); - } - - function insertSlot(slot, slotNext) { - //#DBG _ASSERT(slotNext); - //#DBG _ASSERT(slotNext.prev); - - slot.prev = slotNext.prev; - slot.next = slotNext; - - slot.prev.next = slot; - slotNext.prev = slot; - } - - function removeSlot(slot) { - //#DBG _ASSERT(slot.prev.next === slot); - //#DBG _ASSERT(slot.next.prev === slot); - //#DBG _ASSERT(slot !== slotsStart && slot !== slotListEnd && slot !== slotsEnd); - - if (slot.lastInSequence) { - delete slot.lastInSequence; - slot.prev.lastInSequence = true; - } - if (slot.firstInSequence) { - delete slot.firstInSequence; - slot.next.firstInSequence = true; - } - slot.prev.next = slot.next; - slot.next.prev = slot.prev; - } - - function sequenceStart(slot) { - while (!slot.firstInSequence) { - slot = slot.prev; - } - - return slot; - } - - function sequenceEnd(slot) { - while (!slot.lastInSequence) { - slot = slot.next; - } - - return slot; - } - - // Does a little careful surgery to the slot sequence from slotFirst to slotLast before slotNext - function moveSequenceBefore(slotNext, slotFirst, slotLast) { - //#DBG _ASSERT(slotFirst !== slotsStart && slotLast !== slotListEnd && slotLast !== slotsEnd); - //#DBG _ASSERT(slotFirst.firstInSequence && slotLast.lastInSequence); - //#DBG _ASSERT(slotNext.firstInSequence && slotNext.prev.lastInSequence); - - slotFirst.prev.next = slotLast.next; - slotLast.next.prev = slotFirst.prev; - - slotFirst.prev = slotNext.prev; - slotLast.next = slotNext; - - slotFirst.prev.next = slotFirst; - slotNext.prev = slotLast; - - return true; - } - - // Does a little careful surgery to the slot sequence from slotFirst to slotLast after slotPrev - function moveSequenceAfter(slotPrev, slotFirst, slotLast) { - //#DBG _ASSERT(slotFirst !== slotsStart && slotLast !== slotsEnd); - //#DBG _ASSERT(slotFirst.firstInSequence && slotLast.lastInSequence); - //#DBG _ASSERT(slotPrev.lastInSequence && slotPrev.next.firstInSequence); - - slotFirst.prev.next = slotLast.next; - slotLast.next.prev = slotFirst.prev; - - slotFirst.prev = slotPrev; - slotLast.next = slotPrev.next; - - slotPrev.next = slotFirst; - slotLast.next.prev = slotLast; - - return true; - } - - function mergeSequences(slotPrev) { - delete slotPrev.lastInSequence; - delete slotPrev.next.firstInSequence; - } - - function splitSequence(slotPrev) { - var slotNext = slotPrev.next; - - slotPrev.lastInSequence = true; - slotNext.firstInSequence = true; - - if (slotNext === slotListEnd) { - // Clear slotListEnd's index, as that's now unknown - changeSlotIndex(slotListEnd, undefined); - } - } - - // Inserts a slot in the middle of a sequence or between sequences. If the latter, mergeWithPrev and mergeWithNext - // parameters specify whether to merge the slot with the previous sequence, or next, or neither. - function insertAndMergeSlot(slot, slotNext, mergeWithPrev, mergeWithNext) { - insertSlot(slot, slotNext); - - var slotPrev = slot.prev; - - if (slotPrev.lastInSequence) { - //#DBG _ASSERT(slotNext.firstInSequence); - - if (mergeWithPrev) { - delete slotPrev.lastInSequence; - } else { - slot.firstInSequence = true; - } - - if (mergeWithNext) { - delete slotNext.firstInSequence; - } else { - slot.lastInSequence = true; - } - } - } - - // Keys and Indices - - function setSlotKey(slot, key) { - //#DBG _ASSERT(!slot.key); - //#DBG _ASSERT(!keyMap[key]); - - slot.key = key; - - // Add the slot to the keyMap, so it is possible to quickly find the slot given its key - keyMap[slot.key] = slot; - } - - function setSlotIndex(slot, index, indexMapForSlot) { - // Tolerate NaN, so clients can pass (undefined - 1) or (undefined + 1) - if (+index === index) { - //#DBG _ASSERT(indexUpdateDeferred || !indexMapForSlot[index]); - - slot.index = index; - - // Add the slot to the indexMap, so it is possible to quickly find the slot given its index - indexMapForSlot[index] = slot; - - if (!indexUpdateDeferred) { - // See if any sequences should be merged - if (slot.firstInSequence && slot.prev && slot.prev.index === index - 1) { - mergeSequences(slot.prev); - } - if (slot.lastInSequence && slot.next && slot.next.index === index + 1) { - mergeSequences(slot); - } - } - } - } - - // Creates a new slot and adds it to the slot list before slotNext - function createAndAddSlot(slotNext, indexMapForSlot) { - var slotNew = (indexMapForSlot === indexMap ? createPrimarySlot() : createSlot()); - - insertSlot(slotNew, slotNext); - - return slotNew; - } - - function createSlotSequence(slotNext, index, indexMapForSlot) { - //#DBG _ASSERT(slotNext.prev.lastInSequence); - //#DBG _ASSERT(slotNext.firstInSequence); - - var slotNew = createAndAddSlot(slotNext, indexMapForSlot); - - slotNew.firstInSequence = true; - slotNew.lastInSequence = true; - - setSlotIndex(slotNew, index, indexMapForSlot); - - return slotNew; - } - - function createPrimarySlotSequence(slotNext, index) { - return createSlotSequence(slotNext, index, indexMap); - } - - function addSlotBefore(slotNext, indexMapForSlot) { - //#DBG _ASSERT(slotNext.firstInSequence); - //#DBG _ASSERT(slotNext.prev.lastInSequence); - var slotNew = createAndAddSlot(slotNext, indexMapForSlot); - delete slotNext.firstInSequence; - - // See if we've bumped into the previous sequence - if (slotNew.prev.index === slotNew.index - 1) { - delete slotNew.prev.lastInSequence; - } else { - slotNew.firstInSequence = true; - } - - setSlotIndex(slotNew, slotNext.index - 1, indexMapForSlot); - - return slotNew; - } - - function addSlotAfter(slotPrev, indexMapForSlot) { - //#DBG _ASSERT(slotPrev !== slotListEnd); - //#DBG _ASSERT(slotPrev.lastInSequence); - //#DBG _ASSERT(slotPrev.next.firstInSequence); - var slotNew = createAndAddSlot(slotPrev.next, indexMapForSlot); - delete slotPrev.lastInSequence; - - // See if we've bumped into the next sequence - if (slotNew.next.index === slotNew.index + 1) { - delete slotNew.next.firstInSequence; - } else { - slotNew.lastInSequence = true; - } - - setSlotIndex(slotNew, slotPrev.index + 1, indexMapForSlot); - - return slotNew; - } - - function reinsertSlot(slot, slotNext, mergeWithPrev, mergeWithNext) { - insertAndMergeSlot(slot, slotNext, mergeWithPrev, mergeWithNext); - //#DBG _ASSERT(!keyMap[slot.key]); - keyMap[slot.key] = slot; - var index = slot.index; - if (slot.index !== undefined) { - indexMap[slot.index] = slot; - } - } - - function removeSlotPermanently(slot) { - /*#DBG - _ASSERT(totalSlots > 0); - totalSlots--; - #DBG*/ - - removeSlot(slot); - - if (slot.key) { - delete keyMap[slot.key]; - } - if (slot.index !== undefined && indexMap[slot.index] === slot) { - delete indexMap[slot.index]; - } - - var bindingMap = slot.bindingMap; - for (var listBindingID in bindingMap) { - var handle = bindingMap[listBindingID].handle; - if (handle && handleMap[handle] === slot) { - delete handleMap[handle]; - } - } - - // Invalidating the slot's handle marks it as deleted - if (handleMap[slot.handle] === slot) { - delete handleMap[slot.handle]; - } - } - - function slotPermanentlyRemoved(slot) { - return !handleMap[slot.handle]; - } - - function successorFromIndex(index, indexMapForSlot, listStart, listEnd, skipPreviousIndex) { - //#DBG _ASSERT(index !== undefined); - - // Try the previous index - var slotNext = (skipPreviousIndex ? null : indexMapForSlot[index - 1]); - if (slotNext && (slotNext.next !== listEnd || listEnd.firstInSequence)) { - // We want the successor - slotNext = slotNext.next; - } else { - // Try the next index - slotNext = indexMapForSlot[index + 1]; - if (!slotNext) { - // Resort to a linear search - slotNext = listStart.next; - var lastSequenceStart; - while (true) { - //#DBG _ASSERT(slotNext); - //#DBG _ASSERT(slotNext.index !== index); - - if (slotNext.firstInSequence) { - lastSequenceStart = slotNext; - } - - if (!(index >= slotNext.index) || slotNext === listEnd) { - break; - } - - slotNext = slotNext.next; - } - - if (slotNext === listEnd && !listEnd.firstInSequence) { - // Return the last insertion point between sequences, or undefined if none - slotNext = (lastSequenceStart && lastSequenceStart.index === undefined ? lastSequenceStart : undefined); - } - } - } - - return slotNext; - } - - // Slot Items - - function isPlaceholder(slot) { - //#DBG _ASSERT(slot !== slotsStart && slot !== slotsEnd); - return !slot.item && !slot.itemNew && slot !== slotListEnd; - } - - function defineHandleProperty(item, handle) { - Object.defineProperty(item, "handle", { - value: handle, - writable: false, - enumerable: false, - configurable: true - }); - } - - function defineCommonItemProperties(item, slot, handle) { - defineHandleProperty(item, handle); - - Object.defineProperty(item, "index", { - get: function () { - while (slot.slotMergedWith) { - slot = slot.slotMergedWith; - } - - return slot.index; - }, - enumerable: false, - configurable: true - }); - } - - function validateData(data) { - if (data === undefined) { - return data; - } else { - // Convert the data object to JSON to enforce the constraints we want. For example, we don't want - // functions, arrays with extra properties, DOM objects, cyclic or acyclic graphs, or undefined values. - var dataValidated = JSON.stringify(data); - - if (dataValidated === undefined) { - throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.ObjectIsNotValidJson", strings.objectIsNotValidJson); - } - - return dataValidated; - } - } - - function itemSignature(item) { - return ( - listDataAdapter.itemSignature ? - listDataAdapter.itemSignature(item.data) : - validateData(item.data) - ); - } - - function prepareSlotItem(slot) { - var item = slot.itemNew; - slot.itemNew = null; - - if (item) { - item = Object.create(item); - defineCommonItemProperties(item, slot, slot.handle); - - if (!listDataAdapter.compareByIdentity) { - // Store the item signature or a stringified copy of the data for comparison later - slot.signature = itemSignature(item); - } - } - - slot.item = item; - - delete slot.indexRequested; - delete slot.keyRequested; - } - - // Slot Caching - - function slotRetained(slot) { - return slot.bindingMap || slot.cursorCount > 0; - } - - function slotRequested(slot) { - return slotRetained(slot) || slot.fetchListeners || slot.directFetchListeners; - } - - function slotLive(slot) { - return slotRequested(slot) || (!slot.firstInSequence && slotRetained(slot.prev)) || (!slot.lastInSequence && slotRetained(slot.next)) || - (!itemsFromIndex && ( - (!slot.firstInSequence && slot.prev !== slotsStart && !(slot.prev.item || slot.prev.itemNew)) | - (!slot.lastInSequence && slot.next !== slotListEnd && !(slot.next.item || slot.next.itemNew)) - )); - } - - function deleteUnnecessarySlot(slot) { - splitSequence(slot); - removeSlotPermanently(slot); - } - - function reduceReleasedSlotCount() { - // Must not release slots while edits are queued, as undo queue might refer to them - if (!editsQueued) { - // If lastSlotReleased is no longer valid, use the end of the list instead - if (!lastSlotReleased || slotPermanentlyRemoved(lastSlotReleased)) { - lastSlotReleased = slotListEnd.prev; - } - - // Now use the simple heuristic of walking outwards in both directions from lastSlotReleased until the - // desired cache size is reached, then removing everything else. - var slotPrev = lastSlotReleased.prev, - slotNext = lastSlotReleased.next, - releasedSlotsFound = 0; - - var considerDeletingSlot = function (slotToDelete) { - if (slotToDelete !== slotListEnd && !slotLive(slotToDelete)) { - if (releasedSlotsFound <= cacheSize) { - releasedSlotsFound++; - } else { - deleteUnnecessarySlot(slotToDelete); - } - } - } - - while (slotPrev || slotNext) { - if (slotPrev) { - var slotPrevToDelete = slotPrev; - slotPrev = slotPrevToDelete.prev; - if (slotPrevToDelete !== slotsStart) { - considerDeletingSlot(slotPrevToDelete); - } - } - if (slotNext) { - var slotNextToDelete = slotNext; - slotNext = slotNextToDelete.next; - if (slotNextToDelete !== slotsEnd) { - considerDeletingSlot(slotNextToDelete); - } - } - } - - // Reset the count to zero, so this method is only called periodically - releasedSlots = 0; - } - } - - function releaseSlotIfUnrequested(slot) { - if (!slotRequested(slot)) { - if (UI._PerfMeasurement_leakSlots) { - return; - } - - releasedSlots++; - - // Must not release slots while edits are queued, as undo queue might refer to them. If a refresh is in - // progress, retain all slots, just in case the user re-requests some of them before the refresh completes. - if (!editsQueued && !refreshInProgress) { - // Track which slot was released most recently - lastSlotReleased = slot; - - // See if the number of released slots has exceeded the cache size. In practice there will be more - // live slots than retained slots, so this is just a heuristic to periodically shrink the cache. - if (releasedSlots > cacheSize && !reduceReleasedSlotCountPosted) { - reduceReleasedSlotCountPosted = true; - Scheduler.schedule(function () { - reduceReleasedSlotCountPosted = false; - reduceReleasedSlotCount(); - }, Scheduler.Priority.idle, null, "WinJS.UI.VirtualizedDataSource.releaseSlotIfUnrequested"); - } - } - } - } - - // Notifications - - function forEachBindingRecord(callback) { - for (var listBindingID in bindingMap) { - callback(bindingMap[listBindingID]); - } - } - - function forEachBindingRecordOfSlot(slot, callback) { - for (var listBindingID in slot.bindingMap) { - callback(slot.bindingMap[listBindingID].bindingRecord, listBindingID); - } - } - - function handlerToNotify(bindingRecord) { - //#DBG _ASSERT(bindingRecord.notificationHandler); - - if (!bindingRecord.notificationsSent) { - bindingRecord.notificationsSent = true; - - if (bindingRecord.notificationHandler.beginNotifications) { - bindingRecord.notificationHandler.beginNotifications(); - } - } - return bindingRecord.notificationHandler; - } - - function finishNotifications() { - if (!editsInProgress && !dataNotificationsInProgress) { - forEachBindingRecord(function (bindingRecord) { - if (bindingRecord.notificationsSent) { - //#DBG _ASSERT(bindingRecord.notificationHandler); - - bindingRecord.notificationsSent = false; - - if (bindingRecord.notificationHandler.endNotifications) { - bindingRecord.notificationHandler.endNotifications(); - } - } - }); - } - } - - function handleForBinding(slot, listBindingID) { - var bindingMap = slot.bindingMap; - if (bindingMap) { - var slotBinding = bindingMap[listBindingID]; - if (slotBinding) { - var handle = slotBinding.handle; - if (handle) { - return handle; - } - } - } - return slot.handle; - } - - function itemForBinding(item, handle) { - if (item && item.handle !== handle) { - item = Object.create(item); - defineHandleProperty(item, handle); - } - return item; - } - - function changeCount(count) { - var oldCount = knownCount; - knownCount = count; - - forEachBindingRecord(function (bindingRecord) { - if (bindingRecord.notificationHandler && bindingRecord.notificationHandler.countChanged) { - handlerToNotify(bindingRecord).countChanged(knownCount, oldCount); - } - }); - } - - function sendIndexChangedNotifications(slot, indexOld) { - forEachBindingRecordOfSlot(slot, function (bindingRecord, listBindingID) { - //#DBG _ASSERT(bindingRecord.notificationHandler); - if (bindingRecord.notificationHandler.indexChanged) { - handlerToNotify(bindingRecord).indexChanged(handleForBinding(slot, listBindingID), slot.index, indexOld); - } - }); - } - - function changeSlotIndex(slot, index) { - //#DBG _ASSERT(indexUpdateDeferred || ((typeof slot.index !== "number" || indexMap[slot.index] === slot) && !indexMap[index])); - - var indexOld = slot.index; - - if (indexOld !== undefined && indexMap[indexOld] === slot) { - // Remove the slot's old index from the indexMap - delete indexMap[indexOld]; - } - - // Tolerate NaN, so clients can pass (undefined - 1) or (undefined + 1) - if (+index === index) { - setSlotIndex(slot, index, indexMap); - } else if (+indexOld === indexOld) { - //#DBG _ASSERT(!slot.indexRequested); - delete slot.index; - } else { - // If neither the new index or the old index is defined then there was no index changed. - return; - } - - sendIndexChangedNotifications(slot, indexOld); - } - - function insertionNotificationRecipients(slot, slotPrev, slotNext, mergeWithPrev, mergeWithNext) { - var bindingMapRecipients = {}; - - // Start with the intersection of the bindings for the two adjacent slots - if ((mergeWithPrev || !slotPrev.lastInSequence) && (mergeWithNext || !slotNext.firstInSequence)) { - if (slotPrev === slotsStart) { - if (slotNext === slotListEnd) { - // Special case: if the list was empty, broadcast the insertion to all ListBindings with - // notification handlers. - for (var listBindingID in bindingMap) { - bindingMapRecipients[listBindingID] = bindingMap[listBindingID]; - } - } else { - // Include every binding on the next slot - for (var listBindingID in slotNext.bindingMap) { - bindingMapRecipients[listBindingID] = bindingMap[listBindingID]; - } - } - } else if (slotNext === slotListEnd || slotNext.bindingMap) { - for (var listBindingID in slotPrev.bindingMap) { - if (slotNext === slotListEnd || slotNext.bindingMap[listBindingID]) { - bindingMapRecipients[listBindingID] = bindingMap[listBindingID]; - } - } - } - } - - // Use the union of that result with the bindings for the slot being inserted - for (var listBindingID in slot.bindingMap) { - bindingMapRecipients[listBindingID] = bindingMap[listBindingID]; - } - - return bindingMapRecipients; - } - - function sendInsertedNotification(slot) { - var slotPrev = slot.prev, - slotNext = slot.next, - bindingMapRecipients = insertionNotificationRecipients(slot, slotPrev, slotNext), - listBindingID; - - for (listBindingID in bindingMapRecipients) { - var bindingRecord = bindingMapRecipients[listBindingID]; - if (bindingRecord.notificationHandler) { - handlerToNotify(bindingRecord).inserted(bindingRecord.itemPromiseFromKnownSlot(slot), - slotPrev.lastInSequence || slotPrev === slotsStart ? null : handleForBinding(slotPrev, listBindingID), - slotNext.firstInSequence || slotNext === slotListEnd ? null : handleForBinding(slotNext, listBindingID) - ); - } - } - } - - function changeSlot(slot) { - var itemOld = slot.item; - prepareSlotItem(slot); - - forEachBindingRecordOfSlot(slot, function (bindingRecord, listBindingID) { - //#DBG _ASSERT(bindingRecord.notificationHandler); - var handle = handleForBinding(slot, listBindingID); - handlerToNotify(bindingRecord).changed(itemForBinding(slot.item, handle), itemForBinding(itemOld, handle)); - }); - } - - function moveSlot(slot, slotMoveBefore, mergeWithPrev, mergeWithNext, skipNotifications) { - var slotMoveAfter = slotMoveBefore.prev, - listBindingID; - - // If the slot is being moved before or after itself, adjust slotMoveAfter or slotMoveBefore accordingly. If - // nothing is going to change in the slot list, don't send a notification. - if (slotMoveBefore === slot) { - if (!slot.firstInSequence || !mergeWithPrev) { - return; - } - slotMoveBefore = slot.next; - } else if (slotMoveAfter === slot) { - if (!slot.lastInSequence || !mergeWithNext) { - return; - } - slotMoveAfter = slot.prev; - } - - if (!skipNotifications) { - // Determine which bindings to notify - - var bindingMapRecipients = insertionNotificationRecipients(slot, slotMoveAfter, slotMoveBefore, mergeWithPrev, mergeWithNext); - - // Send the notification before the move - for (listBindingID in bindingMapRecipients) { - var bindingRecord = bindingMapRecipients[listBindingID]; - //#DBG _ASSERT(bindingRecord.notificationHandler); - handlerToNotify(bindingRecord).moved(bindingRecord.itemPromiseFromKnownSlot(slot), - ((slotMoveAfter.lastInSequence || slotMoveAfter === slot.prev) && !mergeWithPrev) || slotMoveAfter === slotsStart ? null : handleForBinding(slotMoveAfter, listBindingID), - ((slotMoveBefore.firstInSequence || slotMoveBefore === slot.next) && !mergeWithNext) || slotMoveBefore === slotListEnd ? null : handleForBinding(slotMoveBefore, listBindingID) - ); - } - - // If a ListBinding cursor is at the slot that's moving, adjust the cursor - forEachBindingRecord(function (bindingRecord) { - bindingRecord.adjustCurrentSlot(slot); - }); - } - - removeSlot(slot); - insertAndMergeSlot(slot, slotMoveBefore, mergeWithPrev, mergeWithNext); - } - - function deleteSlot(slot, mirage) { - //#DBG _ASSERT((!slot.fetchListeners && !slot.directFetchListeners) || !slot.item); - completeFetchPromises(slot, true); - - forEachBindingRecordOfSlot(slot, function (bindingRecord, listBindingID) { - //#DBG _ASSERT(bindingRecord.notificationHandler); - handlerToNotify(bindingRecord).removed(handleForBinding(slot, listBindingID), mirage); - }); - - // If a ListBinding cursor is at the slot that's being removed, adjust the cursor - forEachBindingRecord(function (bindingRecord) { - bindingRecord.adjustCurrentSlot(slot); - }); - - removeSlotPermanently(slot); - } - - function deleteMirageSequence(slot) { - // Remove the slots in order - - while (!slot.firstInSequence) { - slot = slot.prev; - } - - //#DBG _ASSERT(slot !== slotsStart); - - var last; - do { - last = slot.lastInSequence; - - var slotNext = slot.next; - deleteSlot(slot, true); - slot = slotNext; - } while (!last); - } - - // Deferred Index Updates - - // Returns the index of the slot taking into account any outstanding index updates - function adjustedIndex(slot) { - var undefinedIndex; - - if (!slot) { - return undefinedIndex; - } - - var delta = 0; - while (!slot.firstInSequence) { - //#DBG _ASSERT(typeof slot.indexNew !== "number"); - - delta++; - slot = slot.prev; - } - - return ( - typeof slot.indexNew === "number" ? - slot.indexNew + delta : - typeof slot.index === "number" ? - slot.index + delta : - undefinedIndex - ); - } - - // Updates the new index of the first slot in each sequence after the given slot - function updateNewIndicesAfterSlot(slot, indexDelta) { - // Adjust all the indexNews after this slot - for (slot = slot.next; slot; slot = slot.next) { - if (slot.firstInSequence) { - var indexNew = (slot.indexNew !== undefined ? slot.indexNew : slot.index); - if (indexNew !== undefined) { - slot.indexNew = indexNew + indexDelta; - } - } - } - - // Adjust the overall count - countDelta += indexDelta; - - indexUpdateDeferred = true; - - // Increment currentRefreshID so any outstanding fetches don't cause trouble. If a refresh is in progress, - // restart it (which will also increment currentRefreshID). - if (refreshInProgress) { - beginRefresh(); - } else { - currentRefreshID++; - } - } - - // Updates the new index of the given slot if necessary, and all subsequent new indices - function updateNewIndices(slot, indexDelta) { - //#DBG _ASSERT(indexDelta !== 0); - - // If this slot is at the start of a sequence, transfer the indexNew - if (slot.firstInSequence) { - var indexNew; - - if (indexDelta < 0) { - // The given slot is about to be removed - indexNew = slot.indexNew; - if (indexNew !== undefined) { - delete slot.indexNew; - } else { - indexNew = slot.index; - } - - if (!slot.lastInSequence) { - // Update the next slot now - slot = slot.next; - if (indexNew !== undefined) { - slot.indexNew = indexNew; - } - } - } else { - // The given slot was just inserted - if (!slot.lastInSequence) { - var slotNext = slot.next; - - indexNew = slotNext.indexNew; - if (indexNew !== undefined) { - delete slotNext.indexNew; - } else { - indexNew = slotNext.index; - } - - if (indexNew !== undefined) { - slot.indexNew = indexNew; - } - } - } - } - - updateNewIndicesAfterSlot(slot, indexDelta); - } - - // Updates the new index of the first slot in each sequence after the given new index - function updateNewIndicesFromIndex(index, indexDelta) { - //#DBG _ASSERT(indexDelta !== 0); - - for (var slot = slotsStart; slot !== slotListEnd; slot = slot.next) { - var indexNew = slot.indexNew; - - if (indexNew !== undefined && index <= indexNew) { - updateNewIndicesAfterSlot(slot, indexDelta); - break; - } - } - } - - // Adjust the indices of all slots to be consistent with any indexNew properties, and strip off the indexNews - function updateIndices() { - var slot, - slotFirstInSequence, - indexNew; - - for (slot = slotsStart; ; slot = slot.next) { - if (slot.firstInSequence) { - slotFirstInSequence = slot; - if (slot.indexNew !== undefined) { - indexNew = slot.indexNew; - delete slot.indexNew; - if (isNaN(indexNew)) { - break; - } - } else { - indexNew = slot.index; - } - - // See if this sequence should be merged with the previous one - if (slot !== slotsStart && slot.prev.index === indexNew - 1) { - mergeSequences(slot.prev); - } - } - - if (slot.lastInSequence) { - var index = indexNew; - for (var slotUpdate = slotFirstInSequence; slotUpdate !== slot.next; slotUpdate = slotUpdate.next) { - //#DBG _ASSERT(index !== slotUpdate.index || +index !== index || indexMap[index] === slotUpdate); - if (index !== slotUpdate.index) { - changeSlotIndex(slotUpdate, index); - } - if (+index === index) { - index++; - } - } - } - - if (slot === slotListEnd) { - break; - } - } - - // Clear any indices on slots that were moved adjacent to slots without indices - for (; slot !== slotsEnd; slot = slot.next) { - if (slot.index !== undefined && slot !== slotListEnd) { - changeSlotIndex(slot, undefined); - } - } - - indexUpdateDeferred = false; - - if (countDelta && +knownCount === knownCount) { - if (getCountPromise) { - getCountPromise.reset(); - } else { - changeCount(knownCount + countDelta); - } - - countDelta = 0; - } - } - - // Fetch Promises - - function createFetchPromise(slot, listenersProperty, listenerID, listBindingID, onComplete) { - if (slot.item) { - return new Promise(function (complete) { - if (onComplete) { - onComplete(complete, slot.item); - } else { - complete(slot.item); - } - }); - } else { - var listener = { - listBindingID: listBindingID, - retained: false - }; - - if (!slot[listenersProperty]) { - slot[listenersProperty] = {}; - } - slot[listenersProperty][listenerID] = listener; - - listener.promise = new Promise(function (complete, error) { - listener.complete = (onComplete ? function (item) { - onComplete(complete, item); - } : complete); - listener.error = error; - }, function () { - // By now the slot might have been merged with another - - while (slot.slotMergedWith) { - slot = slot.slotMergedWith; - } - - var fetchListeners = slot[listenersProperty]; - if (fetchListeners) { - delete fetchListeners[listenerID]; - - // See if there are any other listeners - for (var listenerID2 in fetchListeners) { - return; - } - delete slot[listenersProperty]; - } - releaseSlotIfUnrequested(slot); - }); - - return listener.promise; - } - } - - function completePromises(item, listeners) { - for (var listenerID in listeners) { - listeners[listenerID].complete(item); - } - } - - function completeFetchPromises(slot, completeSynchronously) { - var fetchListeners = slot.fetchListeners, - directFetchListeners = slot.directFetchListeners; - - if (fetchListeners || directFetchListeners) { - prepareSlotItem(slot); - - // By default, complete asynchronously to minimize reentrancy - - var item = slot.item; - - var completeOrQueuePromises = function (listeners) { - if (completeSynchronously) { - completePromises(item, listeners); - } else { - fetchCompleteCallbacks.push(function () { - completePromises(item, listeners); - }); - } - } - - if (directFetchListeners) { - slot.directFetchListeners = null; - completeOrQueuePromises(directFetchListeners); - } - - if (fetchListeners) { - slot.fetchListeners = null; - completeOrQueuePromises(fetchListeners); - } - - releaseSlotIfUnrequested(slot); - } - } - - function callFetchCompleteCallbacks() { - var callbacks = fetchCompleteCallbacks; - - // Clear fetchCompleteCallbacks first to avoid reentrancy problems - fetchCompleteCallbacks = []; - - for (var i = 0, len = callbacks.length; i < len; i++) { - callbacks[i](); - } - } - - function returnDirectFetchError(slot, error) { - var directFetchListeners = slot.directFetchListeners; - if (directFetchListeners) { - slot.directFetchListeners = null; - - for (var listenerID in directFetchListeners) { - directFetchListeners[listenerID].error(error); - } - - releaseSlotIfUnrequested(slot); - } - } - - // Item Requests - - function requestSlot(slot) { - // Ensure that there's a slot on either side of each requested item - if (slot.firstInSequence) { - //#DBG _ASSERT(slot.index - 1 !== slot.prev.index); - addSlotBefore(slot, indexMap); - } - if (slot.lastInSequence) { - //#DBG _ASSERT(slot.index + 1 !== slot.next.index); - addSlotAfter(slot, indexMap); - } - - // If the item has already been fetched, prepare it now to be returned to the client - if (slot.itemNew) { - prepareSlotItem(slot); - } - - // Start a new fetch if necessary - postFetch(); - - return slot; - } - - function requestSlotBefore(slotNext) { - // First, see if the previous slot already exists - if (!slotNext.firstInSequence) { - var slotPrev = slotNext.prev; - - // Next, see if the item is known to not exist - return (slotPrev === slotsStart ? null : requestSlot(slotPrev)); - } - - return requestSlot(addSlotBefore(slotNext, indexMap)); - } - - function requestSlotAfter(slotPrev) { - // First, see if the next slot already exists - if (!slotPrev.lastInSequence) { - var slotNext = slotPrev.next; - - // Next, see if the item is known to not exist - return (slotNext === slotListEnd ? null : requestSlot(slotNext)); - } - - return requestSlot(addSlotAfter(slotPrev, indexMap)); - } - - function itemDirectlyFromSlot(slot) { - // Return a complete promise for a non-existent slot - return ( - slot ? - createFetchPromise(slot, "directFetchListeners", (nextListenerID++).toString()) : - Promise.wrap(null) - ); - } - - function validateKey(key) { - if (typeof key !== "string" || !key) { - throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.KeyIsInvalid", strings.keyIsInvalid); - } - } - - function createSlotForKey(key) { - var slot = createPrimarySlotSequence(slotsEnd); - - setSlotKey(slot, key); - slot.keyRequested = true; - - return slot; - } - - function slotFromKey(key, hints) { - validateKey(key); - - var slot = keyMap[key]; - - if (!slot) { - slot = createSlotForKey(key); - slot.hints = hints; - } - - //#DBG _ASSERT(slot.key === key); - - return requestSlot(slot); - } - - function slotFromIndex(index) { - if (typeof index !== "number" || index < 0) { - throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.IndexIsInvalid", strings.indexIsInvalid); - } - - if (slotListEnd.index <= index) { - return null; - } - - var slot = indexMap[index]; - //#DBG _ASSERT(slot !== slotListEnd); - - if (!slot) { - var slotNext = successorFromIndex(index, indexMap, slotsStart, slotListEnd); - - if (!slotNext) { - // The complete list has been observed, and this index isn't a part of it; a refresh may be necessary - return null; - } - - if (slotNext === slotListEnd && index >= slotListEnd) { - // Clear slotListEnd's index, as that's now unknown - changeSlotIndex(slotListEnd, undefined); - } - - // Create a new slot and start a request for it - if (slotNext.prev.index === index - 1) { - slot = addSlotAfter(slotNext.prev, indexMap); - } else if (slotNext.index === index + 1) { - slot = addSlotBefore(slotNext, indexMap); - } else { - slot = createPrimarySlotSequence(slotNext, index); - } - } - - //#DBG _ASSERT(slot.index === index); - - if (!slot.item) { - slot.indexRequested = true; - } - - return requestSlot(slot); - } - - function slotFromDescription(description) { - // Create a new slot and start a request for it - var slot = createPrimarySlotSequence(slotsEnd); - - slot.description = description; - - return requestSlot(slot); - } - - // Status - - var that = this; - function setStatus(statusNew) { - statusPending = statusNew; - if (status !== statusPending) { - var dispatch = function () { - statusChangePosted = false; - - if (status !== statusPending) { - status = statusPending; - that.dispatchEvent(statusChangedEvent, status); - } - }; - if (statusPending === WinJS.UI.DataSourceStatus.failure) { - dispatch(); - } else if (!statusChangePosted) { - statusChangePosted = true; - - // Delay the event to filter out rapid changes - setTimeout(dispatch, 40); - } - } - } - - // Slot Fetching - - function slotFetchInProgress(slot) { - var fetchID = slot.fetchID; - return fetchID && fetchesInProgress[fetchID]; - } - - function setFetchID(slot, fetchID) { - slot.fetchID = fetchID; - } - - function newFetchID() { - var fetchID = nextFetchID; - nextFetchID++; - - fetchesInProgress[fetchID] = true; - - return fetchID; - } - - function setFetchIDs(slot, countBefore, countAfter) { - var fetchID = newFetchID(); - setFetchID(slot, fetchID); - - var slotBefore = slot; - while (!slotBefore.firstInSequence && countBefore > 0) { - slotBefore = slotBefore.prev; - countBefore--; - setFetchID(slotBefore, fetchID); - } - - var slotAfter = slot; - while (!slotAfter.lastInSequence && countAfter > 0) { - slotAfter = slotAfter.next; - countAfter--; - setFetchID(slotAfter, fetchID); - } - - return fetchID; - } - - // Adds markers on behalf of the data adapter if their presence can be deduced - function addMarkers(fetchResult) { - var items = fetchResult.items, - offset = fetchResult.offset, - totalCount = fetchResult.totalCount, - absoluteIndex = fetchResult.absoluteIndex, - atStart = fetchResult.atStart, - atEnd = fetchResult.atEnd; - - if (isNonNegativeNumber(absoluteIndex)) { - if (isNonNegativeNumber(totalCount)) { - var itemsLength = items.length; - if (absoluteIndex - offset + itemsLength === totalCount) { - atEnd = true; - } - } - - if (offset === absoluteIndex) { - atStart = true; - } - } - - if (atStart) { - items.unshift(startMarker); - fetchResult.offset++; - } - - if (atEnd) { - items.push(endMarker); - } - } - - function resultsValid(slot, refreshID, fetchID) { - // This fetch has completed, whatever it has returned - //#DBG _ASSERT(!fetchID || fetchesInProgress[fetchID]); - delete fetchesInProgress[fetchID]; - - if (refreshID !== currentRefreshID || slotPermanentlyRemoved(slot)) { - // This information is out of date, or the slot has since been discarded - - postFetch(); - return false; - } - - return true; - } - - function fetchItems(slot, fetchID, promiseItems, index) { - var refreshID = currentRefreshID; - promiseItems.then(function (fetchResult) { - if (fetchResult.items && fetchResult.items.length) { - var perfID = "itemsFetched id=" + fetchID + " count=" + fetchResult.items.length; - profilerMarkStart(perfID); - if (resultsValid(slot, refreshID, fetchID)) { - if (+index === index) { - fetchResult.absoluteIndex = index; - } - addMarkers(fetchResult); - processResults(slot, fetchResult.items, fetchResult.offset, fetchResult.totalCount, fetchResult.absoluteIndex); - } - profilerMarkEnd(perfID); - } else { - return Promise.wrapError(new WinJS.ErrorFromName(FetchError.doesNotExist)); - } - }).then(null, function (error) { - if (resultsValid(slot, refreshID, fetchID)) { - processErrorResult(slot, error); - } - }); - } - - function fetchItemsForIndex(indexRequested, slot, fetchID, promiseItems) { - var refreshID = currentRefreshID; - promiseItems.then(function (fetchResult) { - if (fetchResult.items && fetchResult.items.length) { - var perfID = "itemsFetched id=" + fetchID + " count=" + fetchResult.items.length; - profilerMarkStart(perfID); - if (resultsValid(slot, refreshID, fetchID)) { - //#DBG _ASSERT(+indexRequested === indexRequested); - fetchResult.absoluteIndex = indexRequested; - addMarkers(fetchResult); - processResultsForIndex(indexRequested, slot, fetchResult.items, fetchResult.offset, fetchResult.totalCount, fetchResult.absoluteIndex); - } - profilerMarkEnd(perfID); - } else { - return Promise.wrapError(new WinJS.ErrorFromName(FetchError.doesNotExist)); - } - }).then(null, function (error) { - if (resultsValid(slot, refreshID, fetchID)) { - processErrorResultForIndex(indexRequested, slot, refreshID, name); - } - }); - } - - function fetchItemsFromStart(slot, count) { - //#DBG _ASSERT(!refreshInProgress); - - var fetchID = setFetchIDs(slot, 0, count - 1); - if (itemsFromStart) { - fetchItems(slot, fetchID, itemsFromStart(fetchID, count), 0); - } else { - fetchItems(slot, fetchID, itemsFromIndex(fetchID, 0, 0, count - 1), 0); - } - } - - function fetchItemsFromEnd(slot, count) { - //#DBG _ASSERT(!refreshInProgress); - - var fetchID = setFetchIDs(slot, count - 1, 0); - fetchItems(slot, fetchID, itemsFromEnd(fetchID, count)); - } - - function fetchItemsFromKey(slot, countBefore, countAfter) { - //#DBG _ASSERT(!refreshInProgress); - //#DBG _ASSERT(itemsFromKey); - //#DBG _ASSERT(slot.key); - - var fetchID = setFetchIDs(slot, countBefore, countAfter); - fetchItems(slot, fetchID, itemsFromKey(fetchID, slot.key, countBefore, countAfter, slot.hints)); - } - - function fetchItemsFromIndex(slot, countBefore, countAfter) { - //#DBG _ASSERT(!refreshInProgress); - //#DBG _ASSERT(slot !== slotsStart); - - var index = slot.index; - - // Don't ask for items with negative indices - if (countBefore > index) { - countBefore = index; - } - - if (itemsFromIndex) { - var fetchID = setFetchIDs(slot, countBefore, countAfter); - fetchItems(slot, fetchID, itemsFromIndex(fetchID, index, countBefore, countAfter), index); - } else { - // If the slot key is known, we just need to request the surrounding items - if (slot.key) { - fetchItemsFromKey(slot, countBefore, countAfter); - } else { - // Search for the slot with the closest index that has a known key (using the start of the list as a - // last resort). - var slotClosest = slotsStart, - closestDelta = index + 1, - slotSearch, - delta; - - // First search backwards - for (slotSearch = slot.prev; slotSearch !== slotsStart; slotSearch = slotSearch.prev) { - if (slotSearch.index !== undefined && slotSearch.key) { - //#DBG _ASSERT(index > slotSearch.index); - delta = index - slotSearch.index; - if (closestDelta > delta) { - closestDelta = delta; - slotClosest = slotSearch; - } - break; - } - } - - // Then search forwards - for (slotSearch = slot.next; slotSearch !== slotListEnd; slotSearch = slotSearch.next) { - if (slotSearch.index !== undefined && slotSearch.key) { - //#DBG _ASSERT(slotSearch.index > index); - delta = slotSearch.index - index; - if (closestDelta > delta) { - closestDelta = delta; - slotClosest = slotSearch; - } - break; - } - } - - if (slotClosest === slotsStart) { - var fetchID = setFetchIDs(slot, 0, index + 1); - fetchItemsForIndex(0, slot, fetchID, itemsFromStart(fetchID, index + 1)); - } else { - var fetchBefore = Math.max(slotClosest.index - index, 0); - var fetchAfter = Math.max(index - slotClosest.index, 0); - var fetchID = setFetchIDs(slotClosest, fetchBefore, fetchAfter); - fetchItemsForIndex(slotClosest.index, slot, fetchID, itemsFromKey(fetchID, - slotClosest.key, - fetchBefore, - fetchAfter, - slot.hints - )); - } - } - } - } - - function fetchItemsFromDescription(slot, countBefore, countAfter) { - //#DBG _ASSERT(!refreshInProgress); - - var fetchID = setFetchIDs(slot, countBefore, countAfter); - fetchItems(slot, fetchID, itemsFromDescription(fetchID, slot.description, countBefore, countAfter)); - } - - function fetchItemsForAllSlots() { - if (!refreshInProgress) { - var slotFirstPlaceholder, - placeholderCount, - fetchInProgress = false, - fetchesInProgress = false, - slotRequestedByKey, - requestedKeyOffset, - slotRequestedByDescription, - requestedDescriptionOffset, - slotRequestedByIndex, - requestedIndexOffset; - - for (var slot = slotsStart.next; slot !== slotsEnd;) { - var slotNext = slot.next; - - if (slot !== slotListEnd && isPlaceholder(slot)) { - fetchesInProgress = true; - - if (!slotFirstPlaceholder) { - slotFirstPlaceholder = slot; - placeholderCount = 1; - } else { - placeholderCount++; - } - - if (slotFetchInProgress(slot)) { - fetchInProgress = true; - } - - if (slot.keyRequested && !slotRequestedByKey) { - //#DBG _ASSERT(slot.key); - slotRequestedByKey = slot; - requestedKeyOffset = placeholderCount - 1; - } - - if (slot.description !== undefined && !slotRequestedByDescription) { - slotRequestedByDescription = slot; - requestedDescriptionOffset = placeholderCount - 1; - } - - if (slot.indexRequested && !slotRequestedByIndex) { - //#DBG _ASSERT(typeof slot.index === "number"); - slotRequestedByIndex = slot; - requestedIndexOffset = placeholderCount - 1; - } - - if (slot.lastInSequence || slotNext === slotsEnd || !isPlaceholder(slotNext)) { - if (fetchInProgress) { - fetchInProgress = false; - } else { - resultsProcessed = false; - - // Start a new fetch for this placeholder sequence - - // Prefer fetches in terms of a known item - if (!slotFirstPlaceholder.firstInSequence && slotFirstPlaceholder.prev.key && itemsFromKey) { - fetchItemsFromKey(slotFirstPlaceholder.prev, 0, placeholderCount); - } else if (!slot.lastInSequence && slotNext.key && itemsFromKey) { - fetchItemsFromKey(slotNext, placeholderCount, 0); - } else if (slotFirstPlaceholder.prev === slotsStart && !slotFirstPlaceholder.firstInSequence && (itemsFromStart || itemsFromIndex)) { - fetchItemsFromStart(slotFirstPlaceholder, placeholderCount); - } else if (slotNext === slotListEnd && !slot.lastInSequence && itemsFromEnd) { - fetchItemsFromEnd(slot, placeholderCount); - } else if (slotRequestedByKey) { - fetchItemsFromKey(slotRequestedByKey, requestedKeyOffset, placeholderCount - 1 - requestedKeyOffset); - } else if (slotRequestedByDescription) { - fetchItemsFromDescription(slotRequestedByDescription, requestedDescriptionOffset, placeholderCount - 1 - requestedDescriptionOffset); - } else if (slotRequestedByIndex) { - fetchItemsFromIndex(slotRequestedByIndex, requestedIndexOffset, placeholderCount - 1 - requestedIndexOffset); - } else if (typeof slotFirstPlaceholder.index === "number") { - fetchItemsFromIndex(slotFirstPlaceholder, placeholderCount - 1, 0); - } else { - // There is no way to fetch anything in this sequence - //#DBG _ASSERT(slot.lastInSequence); - deleteMirageSequence(slotFirstPlaceholder); - } - - if (resultsProcessed) { - // A re-entrant fetch might have altered the slots list - start again - postFetch(); - return; - } - - if (refreshInProgress) { - // A re-entrant fetch might also have caused a refresh - return; - } - } - - slotFirstPlaceholder = slotRequestedByIndex = slotRequestedByKey = null; - } - } - - slot = slotNext; - } - - setStatus(fetchesInProgress ? DataSourceStatus.waiting : DataSourceStatus.ready); - } - } - - function postFetch() { - if (!fetchesPosted) { - fetchesPosted = true; - Scheduler.schedule(function () { - fetchesPosted = false; - fetchItemsForAllSlots(); - - // A mirage sequence might have been removed - finishNotifications(); - }, Scheduler.Priority.max, null, "WinJS.UI.ListDataSource._fetch"); - } - } - - // Fetch Result Processing - - function itemChanged(slot) { - var itemNew = slot.itemNew; - - if (!itemNew) { - return false; - } - - var item = slot.item; - - for (var property in item) { - switch (property) { - case "data": - // This is handled below - break; - - default: - //#DBG _ASSERT(property !== "handle"); - //#DBG _ASSERT(property !== "index"); - if (item[property] !== itemNew[property]) { - return true; - } - break; - } - } - - return ( - listDataAdapter.compareByIdentity ? - item.data !== itemNew.data : - slot.signature !== itemSignature(itemNew) - ); - } - - function changeSlotIfNecessary(slot) { - if (!slotRequested(slot)) { - // There's no need for any notifications, just delete the old item - slot.item = null; - } else if (itemChanged(slot)) { - changeSlot(slot); - } else { - slot.itemNew = null; - } - } - - function updateSlotItem(slot) { - //#DBG _ASSERT(slot.itemNew); - - if (slot.item) { - changeSlotIfNecessary(slot); - } else { - //#DBG _ASSERT(slot.key); - completeFetchPromises(slot); - } - } - - function updateSlot(slot, item) { - //#DBG _ASSERT(item !== startMarker && item !== endMarker); - - if (!slot.key) { - setSlotKey(slot, item.key); - } - slot.itemNew = item; - - //#DBG _ASSERT(slot.key === item.key); - - updateSlotItem(slot); - } - - function sendMirageNotifications(slot, slotToDiscard, listBindingIDsToDelete) { - var bindingMap = slotToDiscard.bindingMap; - if (bindingMap) { - for (var listBindingID in listBindingIDsToDelete) { - if (bindingMap[listBindingID]) { - var fetchListeners = slotToDiscard.fetchListeners; - for (var listenerID in fetchListeners) { - var listener = fetchListeners[listenerID]; - - if (listener.listBindingID === listBindingID && listener.retained) { - delete fetchListeners[listenerID]; - listener.complete(null); - } - } - - var bindingRecord = bindingMap[listBindingID].bindingRecord; - //#DBG _ASSERT(bindingRecord.notificationHandler); - - handlerToNotify(bindingRecord).removed(handleForBinding(slotToDiscard, listBindingID), true, handleForBinding(slot, listBindingID)); - - // A re-entrant call to release from the removed handler might have cleared slotToDiscard.bindingMap - if (slotToDiscard.bindingMap) { - delete slotToDiscard.bindingMap[listBindingID]; - } - } - } - } - } - - function mergeSlots(slot, slotToDiscard) { - // This shouldn't be called on a slot that has a pending change notification - //#DBG _ASSERT(!slot.item || !slot.itemNew); - - // Only one of the two slots should have a key - //#DBG _ASSERT(!slot.key || !slotToDiscard.key); - - // If slotToDiscard is about to acquire an index, send the notifications now; in rare cases, multiple - // indexChanged notifications will be sent for a given item during a refresh, but that's fine. - if (slot.index !== slotToDiscard.index) { - // If slotToDiscard has a defined index, that should have been transferred already - //#DBG _ASSERT(refreshInProgress || slot.index !== undefined); - - var indexOld = slotToDiscard.index; - slotToDiscard.index = slot.index; - sendIndexChangedNotifications(slotToDiscard, indexOld); - } - - slotToDiscard.slotMergedWith = slot; - - // Transfer the slotBindings from slotToDiscard to slot - var bindingMap = slotToDiscard.bindingMap; - for (var listBindingID in bindingMap) { - if (!slot.bindingMap) { - slot.bindingMap = {}; - } - - //#DBG _ASSERT(!slot.bindingMap[listBindingID]); - - var slotBinding = bindingMap[listBindingID]; - - if (!slotBinding.handle) { - slotBinding.handle = slotToDiscard.handle; - } - //#DBG _ASSERT(handleMap[slotBinding.handle] === slotToDiscard); - handleMap[slotBinding.handle] = slot; - - slot.bindingMap[listBindingID] = slotBinding; - } - - // Update any ListBinding cursors pointing to slotToDiscard - forEachBindingRecord(function (bindingRecord) { - bindingRecord.adjustCurrentSlot(slotToDiscard, slot); - }); - - // See if the item needs to be transferred from slotToDiscard to slot - var item = slotToDiscard.itemNew || slotToDiscard.item; - //#DBG _ASSERT(!item || !slot.key); - - if (item) { - item = Object.create(item); - defineCommonItemProperties(item, slot, slot.handle); - updateSlot(slot, item); - } - - // Transfer the fetch listeners from slotToDiscard to slot, or complete them if item is known - if (slot.item) { - if (slotToDiscard.directFetchListeners) { - fetchCompleteCallbacks.push(function () { - completePromises(slot.item, slotToDiscard.directFetchListeners); - }); - } - if (slotToDiscard.fetchListeners) { - fetchCompleteCallbacks.push(function () { - completePromises(slot.item, slotToDiscard.fetchListeners); - }); - } - } else { - var listenerID; - - for (listenerID in slotToDiscard.directFetchListeners) { - if (!slot.directFetchListeners) { - slot.directFetchListeners = {}; - } - slot.directFetchListeners[listenerID] = slotToDiscard.directFetchListeners[listenerID]; - } - - for (listenerID in slotToDiscard.fetchListeners) { - if (!slot.fetchListeners) { - slot.fetchListeners = {}; - } - slot.fetchListeners[listenerID] = slotToDiscard.fetchListeners[listenerID]; - } - } - - // This might be the first time this slot's item can be prepared - if (slot.itemNew) { - completeFetchPromises(slot); - } - - // Give slotToDiscard an unused handle so it appears to be permanently removed - slotToDiscard.handle = (nextHandle++).toString(); - - splitSequence(slotToDiscard); - removeSlotPermanently(slotToDiscard); - } - - function mergeSlotsAndItem(slot, slotToDiscard, item) { - if (slotToDiscard && slotToDiscard.key) { - //#DBG _ASSERT(!item || slotToDiscard.key === item.key); - //#DBG _ASSERT(!slotToDiscard.bindingMap); - - if (!item) { - item = slotToDiscard.itemNew || slotToDiscard.item; - } - - // Free up the key for the promoted slot - delete slotToDiscard.key; - delete keyMap[item.key]; - - slotToDiscard.itemNew = null; - slotToDiscard.item = null; - } - - if (item) { - updateSlot(slot, item); - } - - if (slotToDiscard) { - mergeSlots(slot, slotToDiscard); - } - } - - function slotFromResult(result) { - if (typeof result !== "object") { - throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.InvalidItemReturned", strings.invalidItemReturned); - } else if (result === startMarker) { - return slotsStart; - } else if (result === endMarker) { - return slotListEnd; - } else if (!result.key) { - throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.InvalidKeyReturned", strings.invalidKeyReturned); - } else { - if (WinJS.validation) { - validateKey(result.key); - } - return keyMap[result.key]; - } - } - - function matchSlot(slot, result) { - //#DBG _ASSERT(result !== startMarker && result !== endMarker); - - // First see if there is an existing slot that needs to be merged - var slotExisting = slotFromResult(result); - if (slotExisting === slot) { - slotExisting = null; - } - - if (slotExisting) { - sendMirageNotifications(slot, slotExisting, slot.bindingMap); - } - - mergeSlotsAndItem(slot, slotExisting, result); - } - - function promoteSlot(slot, item, index, insertionPoint) { - //#DBG _ASSERT(typeof slot.index !== "number"); - //#DBG _ASSERT(+index === index || !indexMap[index]); - - if (item && slot.key && slot.key !== item.key) { - // A contradiction has been found - beginRefresh(); - return false; - } - - // The slot with the key "wins"; slots without bindings can be merged without any change in observable behavior - - var slotWithIndex = indexMap[index]; - if (slotWithIndex) { - if (slotWithIndex === slot) { - slotWithIndex = null; - } else if (slotWithIndex.key && (slot.key || (item && slotWithIndex.key !== item.key))) { - // A contradiction has been found - beginRefresh(); - return false; - } else if (!slot.key && slotWithIndex.bindingMap) { - return false; - } - } - - var slotWithKey; - if (item) { - slotWithKey = keyMap[item.key]; - - if (slotWithKey === slot) { - slotWithKey = null; - } else if (slotWithKey && slotWithKey.bindingMap) { - return false; - } - } - - if (slotWithIndex) { - sendMirageNotifications(slot, slotWithIndex, slot.bindingMap); - - // Transfer the index to the promoted slot - delete indexMap[index]; - changeSlotIndex(slot, index); - - // See if this sequence should be merged with its neighbors - if (slot.prev.index === index - 1) { - mergeSequences(slot.prev); - } - if (slot.next.index === index + 1) { - mergeSequences(slot); - } - - insertionPoint.slotNext = slotWithIndex.slotNext; - - if (!item) { - item = slotWithIndex.itemNew || slotWithIndex.item; - if (item) { - slotWithKey = keyMap[item.key]; - } - } - } else { - changeSlotIndex(slot, index); - } - - if (slotWithKey && slotWithIndex !== slotWithKey) { - sendMirageNotifications(slot, slotWithKey, slot.bindingMap); - } - - mergeSlotsAndItem(slot, slotWithKey, item); - - // Do this after mergeSlotsAndItem, since its call to updateSlot might send changed notifications, and those - // wouldn't make sense to clients that never saw the old item. - if (slotWithIndex && slotWithIndex !== slotWithKey) { - mergeSlots(slot, slotWithIndex); - } - - //#DBG _ASSERT(!slotWithIndex || slotWithIndex.prev.next !== slotWithIndex); - - return true; - } - - function mergeAdjacentSlot(slotExisting, slot, listBindingIDsToDelete) { - if (slot.key && slotExisting.key && slot.key !== slotExisting.key) { - // A contradiction has been found - beginRefresh(); - return false; - } - - for (var listBindingID in slotExisting.bindingMap) { - listBindingIDsToDelete[listBindingID] = true; - } - - sendMirageNotifications(slotExisting, slot, listBindingIDsToDelete); - mergeSlotsAndItem(slotExisting, slot); - - return true; - } - - function mergeSlotsBefore(slot, slotExisting) { - var listBindingIDsToDelete = {}; - - while (slot) { - var slotPrev = (slot.firstInSequence ? null : slot.prev); - - if (!slotExisting.firstInSequence && slotExisting.prev === slotsStart) { - deleteSlot(slot, true); - } else { - if (slotExisting.firstInSequence) { - slotExisting = addSlotBefore(slotExisting, indexMap); - } else { - slotExisting = slotExisting.prev; - } - - if (!mergeAdjacentSlot(slotExisting, slot, listBindingIDsToDelete)) { - return; - } - } - - slot = slotPrev; - } - } - - function mergeSlotsAfter(slot, slotExisting) { - var listBindingIDsToDelete = {}; - - while (slot) { - var slotNext = (slot.lastInSequence ? null : slot.next); - - if (!slotExisting.lastInSequence && slotExisting.next === slotListEnd) { - deleteSlot(slot, true); - } else { - if (slotExisting.lastInSequence) { - slotExisting = addSlotAfter(slotExisting, indexMap); - } else { - slotExisting = slotExisting.next; - } - - if (!mergeAdjacentSlot(slotExisting, slot, listBindingIDsToDelete)) { - return; - } - } - - slot = slotNext; - } - } - - function mergeSequencePairs(sequencePairsToMerge) { - for (var i = 0; i < sequencePairsToMerge.length; i++) { - var sequencePairToMerge = sequencePairsToMerge[i]; - mergeSlotsBefore(sequencePairToMerge.slotBeforeSequence, sequencePairToMerge.slotFirstInSequence); - mergeSlotsAfter(sequencePairToMerge.slotAfterSequence, sequencePairToMerge.slotLastInSequence); - } - } - - // Removes any placeholders with indices that exceed the given upper bound on the count - function removeMirageIndices(countMax, indexFirstKnown) { - //#DBG _ASSERT(isNonNegativeInteger(countMax)); - - var placeholdersAtEnd = 0; - - function removePlaceholdersAfterSlot(slotRemoveAfter) { - for (var slot2 = slotListEnd.prev; !(slot2.index < countMax) && slot2 !== slotRemoveAfter;) { - var slotPrev2 = slot2.prev; - if (slot2.index !== undefined) { - deleteSlot(slot2, true); - } - slot2 = slotPrev2; - } - - placeholdersAtEnd = 0; - } - - for (var slot = slotListEnd.prev; !(slot.index < countMax) || placeholdersAtEnd > 0;) { - //#DBG _ASSERT(!refreshInProgress); - - var slotPrev = slot.prev; - - if (slot === slotsStart) { - removePlaceholdersAfterSlot(slotsStart); - break; - } else if (slot.key) { - if (slot.index >= countMax) { - beginRefresh(); - return false; - } else if (slot.index >= indexFirstKnown) { - removePlaceholdersAfterSlot(slot); - //#DBG _ASSERT(slot.index < countMax); - } else { - if (itemsFromKey) { - fetchItemsFromKey(slot, 0, placeholdersAtEnd); - } else { - fetchItemsFromIndex(slot, 0, placeholdersAtEnd); - } - - // Wait until the fetch has completed before doing anything - return false; - } - } else if (slot.indexRequested || slot.firstInSequence) { - removePlaceholdersAfterSlot(slotPrev); - } else { - placeholdersAtEnd++; - } - - slot = slotPrev; - } - - return true; - } - - // Merges the results of a fetch into the slot list data structure, and determines if any notifications need to be - // synthesized. - function processResults(slot, results, offset, count, index) { - var perfId = "WinJS.UI.ListDataSource.processResults"; - profilerMarkStart(perfId); - - index = validateIndexReturned(index); - count = validateCountReturned(count); - - // If there are edits queued, we need to wait until the slots get back in sync with the data - if (editsQueued) { - profilerMarkEnd(perfId); - return; - } - - if (indexUpdateDeferred) { - updateIndices(); - } - - // If the count has changed, and the end of the list has been reached, that's a contradiction - if ((isNonNegativeNumber(count) || count === CountResult.unknown) && count !== knownCount && !slotListEnd.firstInSequence) { - beginRefresh(); - profilerMarkEnd(perfId); - return; - } - - resultsProcessed = true; - - /*#DBG - VERIFYLIST(); - #DBG*/ - - (function () { - var i, - j, - resultsCount = results.length, - slotExisting, - slotBefore; - - // If an index wasn't passed in, see if the indices of these items can be determined - if (typeof index !== "number") { - for (i = 0; i < resultsCount; i++) { - slotExisting = slotFromResult(results[i]); - if (slotExisting && slotExisting.index !== undefined) { - index = slotExisting.index + offset - i; - break; - } - } - } - - // See if these results include the end of the list - if (typeof index === "number" && results[resultsCount - 1] === endMarker) { - // If the count wasn't known, it is now - count = index - offset + resultsCount - 1; - } else if (isNonNegativeNumber(count) && index == undefined) { - // If the index wasn't known, it is now - index = count - (resultsCount - 1) + offset; - } - - // If the count is known, remove any mirage placeholders at the end - if (isNonNegativeNumber(count) && !removeMirageIndices(count, index - offset)) { - // "Forget" the count - a subsequent fetch or refresh will update the count and list end - count = undefined; - } - - // Find any existing slots that correspond to the results, and check for contradictions - var offsetMap = new Array(resultsCount); - for (i = 0; i < resultsCount; i++) { - var slotBestMatch = null; - - slotExisting = slotFromResult(results[i]); - - if (slotExisting) { - // See if this item is currently adjacent to a different item, or has a different index - if ((i > 0 && !slotExisting.firstInSequence && slotExisting.prev.key && slotExisting.prev.key !== results[i - 1].key) || - (typeof index === "number" && slotExisting.index !== undefined && slotExisting.index !== index - offset + i)) { - // A contradiction has been found, so we can't proceed further - beginRefresh(); - return; - } - - if (slotExisting === slotsStart || slotExisting === slotListEnd || slotExisting.bindingMap) { - // First choice is a slot with the given key and at least one binding (or an end of the list) - slotBestMatch = slotExisting; - } - } - - if (typeof index === "number") { - slotExisting = indexMap[index - offset + i]; - - if (slotExisting) { - if (slotExisting.key && slotExisting.key !== results[i].key) { - // A contradiction has been found, so we can't proceed further - beginRefresh(); - return; - } - - if (!slotBestMatch && slotExisting.bindingMap) { - // Second choice is a slot with the given index and at least one binding - slotBestMatch = slotExisting; - } - } - } - - if (i === offset) { - if ((slot.key && slot.key !== results[i].key) || (typeof slot.index === "number" && typeof index === "number" && slot.index !== index)) { - // A contradiction has been found, so we can't proceed further - beginRefresh(); - return; - } - - if (!slotBestMatch) { - // Third choice is the slot that was passed in - slotBestMatch = slot; - } - } - - offsetMap[i] = slotBestMatch; - } - - // Update items with known indices (and at least one binding) first, as they will not be merged with - // anything. - for (i = 0; i < resultsCount; i++) { - slotExisting = offsetMap[i]; - if (slotExisting && slotExisting.index !== undefined && slotExisting !== slotsStart && slotExisting !== slotListEnd) { - matchSlot(slotExisting, results[i]); - } - } - - var sequencePairsToMerge = []; - - // Now process the sequences without indices - var firstSequence = true; - for (i = 0; i < resultsCount; i++) { - slotExisting = offsetMap[i]; - if (slotExisting && slotExisting !== slotListEnd) { - var iLast = i; - - if (slotExisting.index === undefined) { - var insertionPoint = {}; - - promoteSlot(slotExisting, results[i], index - offset + i, insertionPoint); - - // Find the extents of the sequence of slots that we can use - var slotFirstInSequence = slotExisting, - slotLastInSequence = slotExisting, - result; - - for (j = i - 1; !slotFirstInSequence.firstInSequence; j--) { - // Keep going until we hit the start marker or a slot that we can't use or promote (it's ok - // if j leaves the results range). - - result = results[j]; - if (result === startMarker) { - break; - } - - // Avoid assigning negative indices to slots - var index2 = index - offset + j; - if (index2 < 0) { - break; - } - - if (promoteSlot(slotFirstInSequence.prev, result, index2, insertionPoint)) { - slotFirstInSequence = slotFirstInSequence.prev; - if (j >= 0) { - offsetMap[j] = slotFirstInSequence; - } - } else { - break; - } - } - - for (j = i + 1; !slotLastInSequence.lastInSequence; j++) { - // Keep going until we hit the end marker or a slot that we can't use or promote (it's ok - // if j leaves the results range). - - // If slotListEnd is in this sequence, it should not be separated from any predecessor - // slots, but they may need to be promoted. - result = results[j]; - if ((result === endMarker || j === count) && slotLastInSequence.next !== slotListEnd) { - break; - } - - if (slotLastInSequence.next === slotListEnd || promoteSlot(slotLastInSequence.next, result, index - offset + j, insertionPoint)) { - slotLastInSequence = slotLastInSequence.next; - if (j < resultsCount) { - offsetMap[j] = slotLastInSequence; - } - - iLast = j; - - if (slotLastInSequence === slotListEnd) { - break; - } - } else { - break; - } - } - - var slotBeforeSequence = (slotFirstInSequence.firstInSequence ? null : slotFirstInSequence.prev), - slotAfterSequence = (slotLastInSequence.lastInSequence ? null : slotLastInSequence.next); - - if (slotBeforeSequence) { - splitSequence(slotBeforeSequence); - } - if (slotAfterSequence) { - splitSequence(slotLastInSequence); - } - - // Move the sequence if necessary - if (typeof index === "number") { - if (slotLastInSequence === slotListEnd) { - // Instead of moving the list end, move the sequence before out of the way - if (slotBeforeSequence) { - moveSequenceAfter(slotListEnd, sequenceStart(slotBeforeSequence), slotBeforeSequence); - } - //#DBG _ASSERT(!slotAfterSequence); - } else { - var slotInsertBefore = insertionPoint.slotNext; - if (!slotInsertBefore) { - slotInsertBefore = successorFromIndex(slotLastInSequence.index, indexMap, slotsStart, slotListEnd, true); - } - moveSequenceBefore(slotInsertBefore, slotFirstInSequence, slotLastInSequence); - } - if (slotFirstInSequence.prev.index === slotFirstInSequence.index - 1) { - mergeSequences(slotFirstInSequence.prev); - } - if (slotLastInSequence.next.index === slotLastInSequence.index + 1) { - mergeSequences(slotLastInSequence); - } - } else if (!firstSequence) { - //#DBG _ASSERT(slotFirstInSequence === slotExisting); - slotBefore = offsetMap[i - 1]; - - if (slotBefore) { - if (slotFirstInSequence.prev !== slotBefore) { - if (slotLastInSequence === slotListEnd) { - // Instead of moving the list end, move the sequence before out of the way and - // the predecessor sequence into place. - if (slotBeforeSequence) { - moveSequenceAfter(slotListEnd, sequenceStart(slotBeforeSequence), slotBeforeSequence); - } - moveSequenceBefore(slotFirstInSequence, sequenceStart(slotBefore), slotBefore); - } else { - moveSequenceAfter(slotBefore, slotFirstInSequence, slotLastInSequence); - } - } - mergeSequences(slotBefore); - } - } - firstSequence = false; - - if (refreshRequested) { - return; - } - - sequencePairsToMerge.push({ - slotBeforeSequence: slotBeforeSequence, - slotFirstInSequence: slotFirstInSequence, - slotLastInSequence: slotLastInSequence, - slotAfterSequence: slotAfterSequence - }); - } - - // See if the fetched slot needs to be merged - if (i === offset && slotExisting !== slot && !slotPermanentlyRemoved(slot)) { - //#DBG _ASSERT(!slot.key); - - slotBeforeSequence = (slot.firstInSequence ? null : slot.prev); - slotAfterSequence = (slot.lastInSequence ? null : slot.next); - - //#DBG _ASSERT(!slotBeforeSequence || !slotBeforeSequence.key); - //#DBG _ASSERT(!slotAfterSequence || !slotAfterSequence.key); - - sendMirageNotifications(slotExisting, slot, slotExisting.bindingMap); - mergeSlots(slotExisting, slot); - - sequencePairsToMerge.push({ - slotBeforeSequence: slotBeforeSequence, - slotFirstInSequence: slotExisting, - slotLastInSequence: slotExisting, - slotAfterSequence: slotAfterSequence - }); - } - - // Skip past all the other items in the sequence we just processed - i = iLast; - } - } - - // If the count is known, set the index of the list end (wait until now because promoteSlot can sometimes - // delete it; do this before mergeSequencePairs so the list end can have slots inserted immediately before - // it). - if (isNonNegativeNumber(count) && slotListEnd.index !== count) { - changeSlotIndex(slotListEnd, count); - } - - // Now that all the sequences have been moved, merge any colliding slots - mergeSequencePairs(sequencePairsToMerge); - - // Match or cache any leftover items - for (i = 0; i < resultsCount; i++) { - // Find the first matched item - slotExisting = offsetMap[i]; - if (slotExisting) { - for (j = i - 1; j >= 0; j--) { - var slotAfter = offsetMap[j + 1]; - matchSlot(offsetMap[j] = (slotAfter.firstInSequence ? addSlotBefore(offsetMap[j + 1], indexMap) : slotAfter.prev), results[j]); - } - for (j = i + 1; j < resultsCount; j++) { - slotBefore = offsetMap[j - 1]; - slotExisting = offsetMap[j]; - if (!slotExisting) { - matchSlot(offsetMap[j] = (slotBefore.lastInSequence ? addSlotAfter(slotBefore, indexMap) : slotBefore.next), results[j]); - } else if (slotExisting.firstInSequence) { - // Adding the cached items may result in some sequences merging - if (slotExisting.prev !== slotBefore) { - //#DBG _ASSERT(slotExisting.index === undefined); - moveSequenceAfter(slotBefore, slotExisting, sequenceEnd(slotExisting)); - } - mergeSequences(slotBefore); - } - } - break; - } - } - - // The description is no longer required - delete slot.description; - })(); - - if (!refreshRequested) { - // If the count changed, but that's the only thing, just send the notification - if (count !== undefined && count !== knownCount) { - changeCount(count); - } - - // See if there are more requests we can now fulfill - postFetch(); - } - - finishNotifications(); - - /*#DBG - VERIFYLIST(); - #DBG*/ - - // Finally complete any promises for newly obtained items - callFetchCompleteCallbacks(); - profilerMarkEnd(perfId); - } - - function processErrorResult(slot, error) { - switch (error.name) { - case FetchError.noResponse: - setStatus(DataSourceStatus.failure); - returnDirectFetchError(slot, error); - break; - - case FetchError.doesNotExist: - // Don't return an error, just complete with null (when the slot is deleted) - - if (slot.indexRequested) { - //#DBG _ASSERT(isPlaceholder(slot)); - //#DBG _ASSERT(slot.index !== undefined); - - // We now have an upper bound on the count - removeMirageIndices(slot.index); - } else if (slot.keyRequested || slot.description) { - // This item, and any items in the same sequence, count as mirages, since they might never have - // existed. - deleteMirageSequence(slot); - } - - finishNotifications(); - - // It's likely that the client requested this item because something has changed since the client's - // latest observations of the data. Begin a refresh just in case. - beginRefresh(); - break; - } - } - - function processResultsForIndex(indexRequested, slot, results, offset, count, index) { - index = validateIndexReturned(index); - count = validateCountReturned(count); - - var indexFirst = indexRequested - offset; - - var resultsCount = results.length; - if (slot.index >= indexFirst && slot.index < indexFirst + resultsCount) { - // The item is in this batch of results - process them all - processResults(slot, results, slot.index - indexFirst, count, slot.index); - } else if ((offset === resultsCount - 1 && indexRequested < slot.index) || (isNonNegativeNumber(count) && count <= slot.index)) { - // The requested index does not exist - processErrorResult(slot, new WinJS.ErrorFromName(UI.FetchError.doesNotExist)); - } else { - // We didn't get all the results we requested - pick up where they left off - if (slot.index < indexFirst) { - var fetchID = setFetchIDs(slot, 0, indexFirst - slot.index); - fetchItemsForIndex(indexFirst, slot, fetchID, itemsFromKey( - fetchID, - results[0].key, - indexFirst - slot.index, - 0 - )); - } else { - var indexLast = indexFirst + resultsCount - 1; - //#DBG _ASSERT(slot.index > indexLast); - - var fetchID = setFetchIDs(slot, slot.index - indexLast, 0); - fetchItemsForIndex(indexLast, slot, fetchID, itemsFromKey( - fetchID, - results[resultsCount - 1].key, - 0, - slot.index - indexLast - )); - } - } - } - - function processErrorResultForIndex(indexRequested, slot, error) { - // If the request was for an index other than the initial one, and the result was doesNotExist, this doesn't - switch (error.name) { - case FetchError.doesNotExist: - if (indexRequested === slotsStart.index) { - // The request was for the start of the list, so the item must not exist, and we now have an upper - // bound of zero for the count. - removeMirageIndices(0); - - processErrorResult(slot, error); - - // No need to check return value of removeMirageIndices, since processErrorResult is going to start - // a refresh anyway. - //#DBG _ASSERT(refreshRequested); - } else { - // Something has changed, but this index might still exist, so request a refresh - beginRefresh(); - } - break; - - default: - processErrorResult(slot, error); - break; - } - } - - // Refresh - - function identifyRefreshCycle() { - // find refresh cycles, find the first beginRefresh in the refreshHistory and see whether it - // matches the next beginRefresh, if so then move the data source into an error state and stop - // refreshing. - var start = 0; - for (; start < refreshHistory.length; start++) { - if (refreshHistory[start].kind === "beginRefresh") { - break; - } - } - var end = start; - for (; end < refreshHistory.length; end++) { - if (refreshHistory[end].kind === "beginRefresh") { - break; - } - } - if (end > start && (end + (end - start) < refreshHistory.length)) { - var match = true; - var length = end - start; - for (var i = 0; i < length; i++) { - if (refreshHistory[start + i].kind !== refreshHistory[end + i].kind) { - match = false; - break; - } - } - if (match) { - if (WinJS.log) { - WinJS.log(strings.refreshCycleIdentified, "winjs vds", "error"); - for (var i = start; i < end; i++) { - WinJS.log("" + (i - start) + ": " + JSON.stringify(refreshHistory[i]), "winjs vds", "error"); - } - } - } - return match; - } - } - - function resetRefreshState() { - if (++beginRefreshCount > MAX_BEGINREFRESH_COUNT) { - if (identifyRefreshCycle()) { - setState(DataSourceStatus.failure); - return; - } - } - refreshHistory[++refreshHistoryPos % refreshHistory.length] = { kind: "beginRefresh" }; - - // Give the start sentinel an index so we can always use predecessor + 1 - refreshStart = { - firstInSequence: true, - lastInSequence: true, - index: -1 - }; - refreshEnd = { - firstInSequence: true, - lastInSequence: true - }; - refreshStart.next = refreshEnd; - refreshEnd.prev = refreshStart; - - /*#DBG - refreshStart.debugInfo = "*** refreshStart ***"; - refreshEnd.debugInfo = "*** refreshEnd ***"; - #DBG*/ - - refreshItemsFetched = false; - refreshCount = undefined; - keyFetchIDs = {}; - refreshKeyMap = {}; - refreshIndexMap = {}; - refreshIndexMap[-1] = refreshStart; - deletedKeys = {}; - } - - function beginRefresh() { - if (refreshRequested) { - // There's already a refresh that has yet to start - return; - } - - refreshRequested = true; - - setStatus(DataSourceStatus.waiting); - - if (waitForRefresh) { - waitForRefresh = false; - - // The edit queue has been paused until the next refresh - resume it now - //#DBG _ASSERT(editsQueued); - applyNextEdit(); - return; - } - - if (editsQueued) { - // The refresh will be started once the edit queue empties out - return; - } - - var refreshID = ++currentRefreshID; - refreshInProgress = true; - refreshFetchesInProgress = 0; - - // Batch calls to beginRefresh - Scheduler.schedule(function () { - if (currentRefreshID !== refreshID) { - return; - } - - //#DBG _ASSERT(refreshRequested); - refreshRequested = false; - - resetRefreshState(); - - // Remove all slots that aren't live, so we don't waste time fetching them - for (var slot = slotsStart.next; slot !== slotsEnd;) { - var slotNext = slot.next; - - if (!slotLive(slot) && slot !== slotListEnd) { - deleteUnnecessarySlot(slot); - } - - slot = slotNext; - } - - startRefreshFetches(); - }, Scheduler.Priority.high, null, "WinJS.VirtualizedDataSource.beginRefresh"); - } - - function requestRefresh() { - refreshSignal = refreshSignal || new Signal(); - - beginRefresh(); - - return refreshSignal.promise; - } - - function resultsValidForRefresh(refreshID, fetchID) { - // This fetch has completed, whatever it has returned - //#DBG _ASSERT(fetchesInProgress[fetchID]); - delete fetchesInProgress[fetchID]; - - if (refreshID !== currentRefreshID) { - // This information is out of date. Ignore it. - return false; - } - - //#DBG _ASSERT(refreshFetchesInProgress > 0); - refreshFetchesInProgress--; - - return true; - } - - function fetchItemsForRefresh(key, fromStart, fetchID, promiseItems, index) { - var refreshID = currentRefreshID; - - refreshFetchesInProgress++; - - promiseItems.then(function (fetchResult) { - if (fetchResult.items && fetchResult.items.length) { - var perfID = "itemsFetched id=" + fetchID + " count=" + fetchResult.items.length; - profilerMarkStart(perfID); - if (resultsValidForRefresh(refreshID, fetchID)) { - addMarkers(fetchResult); - processRefreshResults(key, fetchResult.items, fetchResult.offset, fetchResult.totalCount, (typeof index === "number" ? index : fetchResult.absoluteIndex)); - } - profilerMarkEnd(perfID); - } else { - return Promise.wrapError(new WinJS.ErrorFromName(FetchError.doesNotExist)); - } - }).then(null, function (error) { - if (resultsValidForRefresh(refreshID, fetchID)) { - processRefreshErrorResult(key, fromStart, error); - } - }); - } - - function refreshRange(slot, fetchID, countBefore, countAfter) { - if (itemsFromKey) { - // Keys are the preferred identifiers when the item might have moved - fetchItemsForRefresh(slot.key, false, fetchID, itemsFromKey(fetchID, slot.key, countBefore, countAfter, slot.hints)); - } else { - // Request additional items to try to locate items that have moved - var searchDelta = 10, - index = slot.index; - - //#DBG _ASSERT(+index === index); - - if (refreshIndexMap[index] && refreshIndexMap[index].firstInSequence) { - // Ensure at least one element is observed before this one - fetchItemsForRefresh(slot.key, false, fetchID, itemsFromIndex(fetchID, index - 1, Math.min(countBefore + searchDelta, index) - 1, countAfter + 1 + searchDelta), index - 1); - } else if (refreshIndexMap[index] && refreshIndexMap[index].lastInSequence) { - // Ask for the next index we need directly - fetchItemsForRefresh(slot.key, false, fetchID, itemsFromIndex(fetchID, index + 1, Math.min(countBefore + searchDelta, index) + 1, countAfter - 1 + searchDelta), index + 1); - } else { - fetchItemsForRefresh(slot.key, false, fetchID, itemsFromIndex(fetchID, index, Math.min(countBefore + searchDelta, index), countAfter + searchDelta), index); - } - } - } - - function refreshFirstItem(fetchID) { - if (itemsFromStart) { - fetchItemsForRefresh(null, true, fetchID, itemsFromStart(fetchID, 1), 0); - } else if (itemsFromIndex) { - fetchItemsForRefresh(null, true, fetchID, itemsFromIndex(fetchID, 0, 0, 0), 0); - } - } - - function keyFetchInProgress(key) { - return fetchesInProgress[keyFetchIDs[key]]; - } - - function refreshRanges(slotFirst, allRanges) { - // Fetch a few extra items each time, to catch insertions without requiring an extra fetch - var refreshFetchExtra = 3; - - var refreshID = currentRefreshID; - - var slotFetchFirst, - slotRefreshFirst, - fetchCount = 0, - fetchID; - - // Walk through the slot list looking for keys we haven't fetched or attempted to fetch yet. Rely on the - // heuristic that items that were close together before the refresh are likely to remain so after, so batched - // fetches will locate most of the previously fetched items. - for (var slot = slotFirst; slot !== slotsEnd; slot = slot.next) { - if (!slotFetchFirst && slot.key && !deletedKeys[slot.key] && !keyFetchInProgress(slot.key)) { - var slotRefresh = refreshKeyMap[slot.key]; - - // Keep attempting to fetch an item until at least one item on either side of it has been observed, so - // we can determine its position relative to others. - if (!slotRefresh || slotRefresh.firstInSequence || slotRefresh.lastInSequence) { - slotFetchFirst = slot; - slotRefreshFirst = slotRefresh; - fetchID = newFetchID(); - } - } - - if (!slotFetchFirst) { - // Also attempt to fetch placeholders for requests for specific keys, just in case those items no - // longer exist. - if (slot.key && isPlaceholder(slot) && !deletedKeys[slot.key]) { - // Fulfill each "itemFromKey" request - //#DBG _ASSERT(itemsFromKey); - if (!refreshKeyMap[slot.key]) { - // Fetch at least one item before and after, just to verify item's position in list - fetchID = newFetchID(); - fetchItemsForRefresh(slot.key, false, fetchID, itemsFromKey(fetchID, slot.key, 1, 1, slot.hints)); - } - } - } else { - var keyAlreadyFetched = keyFetchInProgress(slot.key); - - if (!deletedKeys[slot.key] && !refreshKeyMap[slot.key] && !keyAlreadyFetched) { - if (slot.key) { - keyFetchIDs[slot.key] = fetchID; - } - fetchCount++; - } - - if (slot.lastInSequence || slot.next === slotListEnd || keyAlreadyFetched) { - refreshRange(slotFetchFirst, fetchID, (!slotRefreshFirst || slotRefreshFirst.firstInSequence ? refreshFetchExtra : 0), fetchCount - 1 + refreshFetchExtra); - - /*#DBG - fetchID = undefined; - #DBG*/ - - if (!allRanges) { - break; - } - - slotFetchFirst = null; - fetchCount = 0; - } - } - } - - if (refreshFetchesInProgress === 0 && !refreshItemsFetched && currentRefreshID === refreshID) { - // If nothing was successfully fetched, try fetching the first item, to detect an empty list - refreshFirstItem(newFetchID()); - } - - //#DBG _ASSERT(fetchID === undefined); - } - - function startRefreshFetches() { - var refreshID = currentRefreshID; - - do { - synchronousProgress = false; - reentrantContinue = true; - refreshRanges(slotsStart.next, true); - reentrantContinue = false; - } while (refreshFetchesInProgress === 0 && synchronousProgress && currentRefreshID === refreshID && refreshInProgress); - - if (refreshFetchesInProgress === 0 && currentRefreshID === refreshID) { - concludeRefresh(); - } - } - - function continueRefresh(key) { - var refreshID = currentRefreshID; - - // If the key is absent, then the attempt to fetch the first item just completed, and there is nothing else to - // fetch. - if (key) { - var slotContinue = keyMap[key]; - if (!slotContinue) { - // In a rare case, the slot might have been deleted; just start scanning from the beginning again - slotContinue = slotsStart.next; - } - - do { - synchronousRefresh = false; - reentrantRefresh = true; - refreshRanges(slotContinue, false); - reentrantRefresh = false; - } while (synchronousRefresh && currentRefreshID === refreshID && refreshInProgress); - } - - if (reentrantContinue) { - synchronousProgress = true; - } else { - if (refreshFetchesInProgress === 0 && currentRefreshID === refreshID) { - // Walk through the entire list one more time, in case any edits were made during the refresh - startRefreshFetches(); - } - } - } - - function slotRefreshFromResult(result) { - if (typeof result !== "object" || !result) { - throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.InvalidItemReturned", strings.invalidItemReturned); - } else if (result === startMarker) { - return refreshStart; - } else if (result === endMarker) { - return refreshEnd; - } else if (!result.key) { - throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.InvalidKeyReturned", strings.invalidKeyReturned); - } else { - return refreshKeyMap[result.key]; - } - } - - function processRefreshSlotIndex(slot, expectedIndex) { - while (slot.index === undefined) { - setSlotIndex(slot, expectedIndex, refreshIndexMap); - - if (slot.firstInSequence) { - return true; - } - - slot = slot.prev; - expectedIndex--; - } - - if (slot.index !== expectedIndex) { - // Something has changed since the refresh began; start again - beginRefresh(); - return false; - } - - return true; - } - - function setRefreshSlotResult(slotRefresh, result) { - //#DBG _ASSERT(result.key); - slotRefresh.key = result.key; - //#DBG _ASSERT(!refreshKeyMap[slotRefresh.key]); - refreshKeyMap[slotRefresh.key] = slotRefresh; - - slotRefresh.item = result; - } - - // Returns the slot after the last insertion point between sequences - function lastRefreshInsertionPoint() { - var slotNext = refreshEnd; - while (!slotNext.firstInSequence) { - slotNext = slotNext.prev; - - if (slotNext === refreshStart) { - return null; - } - } - - return slotNext; - } - - function processRefreshResults(key, results, offset, count, index) { - index = validateIndexReturned(index); - count = validateCountReturned(count); - - /*#DBG - VERIFYREFRESHLIST(); - #DBG*/ - - var keyPresent = false; - - refreshItemsFetched = true; - - var indexFirst = index - offset, - result = results[0]; - - if (result.key === key) { - keyPresent = true; - } - - var slot = slotRefreshFromResult(result); - if (!slot) { - if (refreshIndexMap[indexFirst]) { - // Something has changed since the refresh began; start again - beginRefresh(); - return; - } - - // See if these results should be appended to an existing sequence - var slotPrev; - if (index !== undefined && (slotPrev = refreshIndexMap[indexFirst - 1])) { - if (!slotPrev.lastInSequence) { - // Something has changed since the refresh began; start again - beginRefresh(); - return; - } - slot = addSlotAfter(slotPrev, refreshIndexMap); - } else { - // Create a new sequence - var slotSuccessor = ( - +indexFirst === indexFirst ? - successorFromIndex(indexFirst, refreshIndexMap, refreshStart, refreshEnd) : - lastRefreshInsertionPoint(refreshStart, refreshEnd) - ); - - if (!slotSuccessor) { - // Something has changed since the refresh began; start again - beginRefresh(); - return; - } - - slot = createSlotSequence(slotSuccessor, indexFirst, refreshIndexMap); - } - - setRefreshSlotResult(slot, results[0]); - } else { - if (+indexFirst === indexFirst) { - if (!processRefreshSlotIndex(slot, indexFirst)) { - return; - } - } - } - - var resultsCount = results.length; - for (var i = 1; i < resultsCount; i++) { - result = results[i]; - - if (result.key === key) { - keyPresent = true; - } - - var slotNext = slotRefreshFromResult(result); - - if (!slotNext) { - if (!slot.lastInSequence) { - // Something has changed since the refresh began; start again - beginRefresh(); - return; - } - slotNext = addSlotAfter(slot, refreshIndexMap); - setRefreshSlotResult(slotNext, result); - } else { - if (slot.index !== undefined && !processRefreshSlotIndex(slotNext, slot.index + 1)) { - return; - } - - // If the slots aren't adjacent, see if it's possible to reorder sequences to make them so - if (slotNext !== slot.next) { - if (!slot.lastInSequence || !slotNext.firstInSequence) { - // Something has changed since the refresh began; start again - beginRefresh(); - return; - } - - var slotLast = sequenceEnd(slotNext); - if (slotLast !== refreshEnd) { - moveSequenceAfter(slot, slotNext, slotLast); - } else { - var slotFirst = sequenceStart(slot); - if (slotFirst !== refreshStart) { - moveSequenceBefore(slotNext, slotFirst, slot); - } else { - // Something has changed since the refresh began; start again - beginRefresh(); - return; - } - } - - mergeSequences(slot); - } else if (slot.lastInSequence) { - //#DBG _ASSERT(slotNext.firstInSequence); - - mergeSequences(slot); - } - } - - slot = slotNext; - } - - if (!keyPresent) { - deletedKeys[key] = true; - } - - // If the count wasn't provided, see if it can be determined from the end of the list. - if (!isNonNegativeNumber(count) && !refreshEnd.firstInSequence) { - var indexLast = refreshEnd.prev.index; - if (indexLast !== undefined) { - count = indexLast + 1; - } - } - - if (isNonNegativeNumber(count) || count === CountResult.unknown) { - if (isNonNegativeNumber(refreshCount)) { - if (count !== refreshCount) { - // Something has changed since the refresh began; start again - beginRefresh(); - return; - } - } else { - refreshCount = count; - } - - if (isNonNegativeNumber(refreshCount) && !refreshIndexMap[refreshCount]) { - setSlotIndex(refreshEnd, refreshCount, refreshIndexMap); - } - } - - /*#DBG - VERIFYREFRESHLIST(); - #DBG*/ - - if (reentrantRefresh) { - synchronousRefresh = true; - } else { - continueRefresh(key); - } - } - - function processRefreshErrorResult(key, fromStart, error) { - switch (error.name) { - case FetchError.noResponse: - setStatus(DataSourceStatus.failure); - break; - - case FetchError.doesNotExist: - if (fromStart) { - // The attempt to fetch the first item failed, so the list must be empty - //#DBG _ASSERT(refreshStart.next === refreshEnd); - //#DBG _ASSERT(refreshStart.lastInSequence && refreshEnd.firstInSequence); - - setSlotIndex(refreshEnd, 0, refreshIndexMap); - refreshCount = 0; - - concludeRefresh(); - } else { - deletedKeys[key] = true; - - if (reentrantRefresh) { - synchronousRefresh = true; - } else { - continueRefresh(key); - } - } - break; - } - } - - function slotFromSlotRefresh(slotRefresh) { - if (slotRefresh === refreshStart) { - return slotsStart; - } else if (slotRefresh === refreshEnd) { - return slotListEnd; - } else { - return keyMap[slotRefresh.key]; - } - } - - function slotRefreshFromSlot(slot) { - if (slot === slotsStart) { - return refreshStart; - } else if (slot === slotListEnd) { - return refreshEnd; - } else { - return refreshKeyMap[slot.key]; - } - } - - function mergeSequencesForRefresh(slotPrev) { - mergeSequences(slotPrev); - - // Mark the merge point, so we can distinguish insertions from unrequested items - slotPrev.next.mergedForRefresh = true; - } - - function copyRefreshSlotData(slotRefresh, slot) { - setSlotKey(slot, slotRefresh.key); - slot.itemNew = slotRefresh.item; - } - - function addNewSlotFromRefresh(slotRefresh, slotNext, insertAfter) { - var slotNew = createPrimarySlot(); - - copyRefreshSlotData(slotRefresh, slotNew); - insertAndMergeSlot(slotNew, slotNext, insertAfter, !insertAfter); - - var index = slotRefresh.index; - if (+index !== index) { - index = (insertAfter ? slotNew.prev.index + 1 : slotNext.next.index - 1); - } - - setSlotIndex(slotNew, index, indexMap); - - return slotNew; - } - - function matchSlotForRefresh(slotExisting, slot, slotRefresh) { - if (slotExisting) { - sendMirageNotifications(slotExisting, slot, slotExisting.bindingMap); - mergeSlotsAndItem(slotExisting, slot, slotRefresh.item); - } else { - copyRefreshSlotData(slotRefresh, slot); - - // If the index was requested, complete the promises now, as the index might be about to change - if (slot.indexRequested) { - updateSlotItem(slot); - } - } - } - - function updateSlotForRefresh(slotExisting, slot, slotRefresh) { - if (!slot.key) { - if (slotExisting) { - // Record the relationship between the slot to discard and its neighbors - slotRefresh.mergeWithPrev = !slot.firstInSequence; - slotRefresh.mergeWithNext = !slot.lastInSequence; - } else { - slotRefresh.stationary = true; - } - matchSlotForRefresh(slotExisting, slot, slotRefresh); - return true; - } else { - //#DBG _ASSERT(!slotExisting); - return false; - } - } - - function indexForRefresh(slot) { - var indexNew; - - if (slot.indexRequested) { - //#DBG _ASSERT(!slot.key); - indexNew = slot.index; - } else { - var slotRefresh = slotRefreshFromSlot(slot); - if (slotRefresh) { - indexNew = slotRefresh.index; - } - } - - return indexNew; - } - - function concludeRefresh() { - //#DBG _ASSERT(refreshInProgress); - //#DBG _ASSERT(!indexUpdateDeferred); - - beginRefreshCount = 0; - refreshHistory = new Array(100); - refreshHistoryPos = -1; - - indexUpdateDeferred = true; - - keyFetchIDs = {}; - - var i, - j, - slot, - slotPrev, - slotNext, - slotBefore, - slotAfter, - slotRefresh, - slotExisting, - slotsAvailable = [], - slotFirstInSequence, - sequenceCountOld, - sequencesOld = [], - sequenceOld, - sequenceOldPrev, - sequenceOldBestMatch, - sequenceCountNew, - sequencesNew = [], - sequenceNew, - index, - offset; - - /*#DBG - VERIFYLIST(); - VERIFYREFRESHLIST(); - #DBG*/ - - // Assign a sequence number to each refresh slot - sequenceCountNew = 0; - for (slotRefresh = refreshStart; slotRefresh; slotRefresh = slotRefresh.next) { - slotRefresh.sequenceNumber = sequenceCountNew; - - if (slotRefresh.firstInSequence) { - slotFirstInSequence = slotRefresh; - } - - if (slotRefresh.lastInSequence) { - sequencesNew[sequenceCountNew] = { - first: slotFirstInSequence, - last: slotRefresh, - matchingItems: 0 - }; - sequenceCountNew++; - } - } - - // Remove unnecessary information from main slot list, and update the items - lastSlotReleased = null; - releasedSlots = 0; - for (slot = slotsStart.next; slot !== slotsEnd;) { - slotRefresh = refreshKeyMap[slot.key]; - slotNext = slot.next; - - if (slot !== slotListEnd) { - if (!slotLive(slot)) { - // Some more items might have been released since the refresh started. Strip them away from the - // main slot list, as they'll just get in the way from now on. Since we're discarding these, but - // don't know if they're actually going away, split the sequence as our starting assumption must be - // that the items on either side are in separate sequences. - deleteUnnecessarySlot(slot); - } else if (slot.key && !slotRefresh) { - // Remove items that have been deleted (or moved far away) and send removed notifications - deleteSlot(slot, false); - } else if (refreshCount === 0 || (slot.indexRequested && slot.index >= refreshCount)) { - // Remove items that can't exist in the list and send mirage removed notifications - deleteSlot(slot, true); - } else if (slot.item || slot.keyRequested) { - //#DBG _ASSERT(slotRefresh); - - // Store the new item; this value will be compared with that stored in slot.item later - slot.itemNew = slotRefresh.item; - } else { - //#DBG _ASSERT(!slot.item); - - // Clear keys and items that have never been observed by client - if (slot.key) { - if (!slot.keyRequested) { - delete keyMap[slot.key]; - delete slot.key; - } - slot.itemNew = null; - } - } - } - - slot = slotNext; - } - - /*#DBG - VERIFYLIST(); - #DBG*/ - - // Placeholders generated by itemsAtIndex should not move. Match these to items now if possible, or merge them - // with existing items if necessary. - for (slot = slotsStart.next; slot !== slotListEnd;) { - slotNext = slot.next; - - //#DBG _ASSERT(!slot.key || refreshKeyMap[slot.key]); - - if (slot.indexRequested) { - //#DBG _ASSERT(!slot.item); - //#DBG _ASSERT(slot.index !== undefined); - - slotRefresh = refreshIndexMap[slot.index]; - if (slotRefresh) { - matchSlotForRefresh(slotFromSlotRefresh(slotRefresh), slot, slotRefresh); - } - } - - slot = slotNext; - } - - /*#DBG - VERIFYLIST(); - #DBG*/ - - // Match old sequences to new sequences - var bestMatch, - bestMatchCount, - previousBestMatch = 0, - newSequenceCounts = [], - slotIndexRequested, - sequenceIndexEnd, - sequenceOldEnd; - - sequenceCountOld = 0; - for (slot = slotsStart; slot !== slotsEnd; slot = slot.next) { - if (slot.firstInSequence) { - slotFirstInSequence = slot; - slotIndexRequested = null; - for (i = 0; i < sequenceCountNew; i++) { - newSequenceCounts[i] = 0; - } - } - - if (slot.indexRequested) { - slotIndexRequested = slot; - } - - slotRefresh = slotRefreshFromSlot(slot); - if (slotRefresh) { - //#DBG _ASSERT(slotRefresh.sequenceNumber !== undefined); - newSequenceCounts[slotRefresh.sequenceNumber]++; - } - - if (slot.lastInSequence) { - // Determine which new sequence is the best match for this old one. Use a simple greedy algorithm to - // ensure the relative ordering of matched sequences is the same; out-of-order sequences will require - // move notifications. - bestMatchCount = 0; - for (i = previousBestMatch; i < sequenceCountNew; i++) { - if (bestMatchCount < newSequenceCounts[i]) { - bestMatchCount = newSequenceCounts[i]; - bestMatch = i; - } - } - - sequenceOld = { - first: slotFirstInSequence, - last: slot, - sequenceNew: (bestMatchCount > 0 ? sequencesNew[bestMatch] : undefined), - matchingItems: bestMatchCount - }; - - if (slotIndexRequested) { - sequenceOld.indexRequested = true; - sequenceOld.stationarySlot = slotIndexRequested; - } - - sequencesOld[sequenceCountOld] = sequenceOld; - - if (slot === slotListEnd) { - sequenceIndexEnd = sequenceCountOld; - sequenceOldEnd = sequenceOld; - } - - sequenceCountOld++; - - if (sequencesNew[bestMatch].first.index !== undefined) { - previousBestMatch = bestMatch; - } - } - } - - //#DBG _ASSERT(sequenceOldEnd); - - // Special case: split the old start into a separate sequence if the new start isn't its best match - if (sequencesOld[0].sequenceNew !== sequencesNew[0]) { - //#DBG _ASSERT(sequencesOld[0].first === slotsStart); - //#DBG _ASSERT(!slotsStart.lastInSequence); - splitSequence(slotsStart); - sequencesOld[0].first = slotsStart.next; - sequencesOld.unshift({ - first: slotsStart, - last: slotsStart, - sequenceNew: sequencesNew[0], - matchingItems: 1 - }); - sequenceIndexEnd++; - sequenceCountOld++; - } - - var listEndObserved = !slotListEnd.firstInSequence; - - // Special case: split the old end into a separate sequence if the new end isn't its best match - if (sequenceOldEnd.sequenceNew !== sequencesNew[sequenceCountNew - 1]) { - //#DBG _ASSERT(sequenceOldEnd.last === slotListEnd); - //#DBG _ASSERT(!slotListEnd.firstInSequence); - splitSequence(slotListEnd.prev); - sequenceOldEnd.last = slotListEnd.prev; - sequenceIndexEnd++; - sequencesOld.splice(sequenceIndexEnd, 0, { - first: slotListEnd, - last: slotListEnd, - sequenceNew: sequencesNew[sequenceCountNew - 1], - matchingItems: 1 - }); - sequenceCountOld++; - sequenceOldEnd = sequencesOld[sequenceIndexEnd]; - } - - // Map new sequences to old sequences - for (i = 0; i < sequenceCountOld; i++) { - sequenceNew = sequencesOld[i].sequenceNew; - if (sequenceNew && sequenceNew.matchingItems < sequencesOld[i].matchingItems) { - sequenceNew.matchingItems = sequencesOld[i].matchingItems; - sequenceNew.sequenceOld = sequencesOld[i]; - } - } - - // The old end must always be the best match for the new end (if the new end is also the new start, they will - // be merged below). - sequencesNew[sequenceCountNew - 1].sequenceOld = sequenceOldEnd; - sequenceOldEnd.stationarySlot = slotListEnd; - - // The old start must always be the best match for the new start - sequencesNew[0].sequenceOld = sequencesOld[0]; - sequencesOld[0].stationarySlot = slotsStart; - - /*#DBG - VERIFYLIST(); - #DBG*/ - - // Merge additional indexed old sequences when possible - - // First do a forward pass - for (i = 0; i <= sequenceIndexEnd; i++) { - sequenceOld = sequencesOld[i]; - - //#DBG _ASSERT(sequenceOld); - if (sequenceOld.sequenceNew && (sequenceOldBestMatch = sequenceOld.sequenceNew.sequenceOld) === sequenceOldPrev && sequenceOldPrev.last !== slotListEnd) { - //#DBG _ASSERT(sequenceOldBestMatch.last.next === sequenceOld.first); - mergeSequencesForRefresh(sequenceOldBestMatch.last); - sequenceOldBestMatch.last = sequenceOld.last; - delete sequencesOld[i]; - } else { - sequenceOldPrev = sequenceOld; - } - } - - // Now do a reverse pass - sequenceOldPrev = null; - for (i = sequenceIndexEnd; i >= 0; i--) { - sequenceOld = sequencesOld[i]; - // From this point onwards, some members of sequencesOld may be undefined - if (sequenceOld) { - if (sequenceOld.sequenceNew && (sequenceOldBestMatch = sequenceOld.sequenceNew.sequenceOld) === sequenceOldPrev && sequenceOld.last !== slotListEnd) { - //#DBG _ASSERT(sequenceOld.last.next === sequenceOldBestMatch.first); - mergeSequencesForRefresh(sequenceOld.last); - sequenceOldBestMatch.first = sequenceOld.first; - delete sequencesOld[i]; - } else { - sequenceOldPrev = sequenceOld; - } - } - } - - // Since we may have forced the list end into a separate sequence, the mergedForRefresh flag may be incorrect - if (listEndObserved) { - delete slotListEnd.mergedForRefresh; - } - - var sequencePairsToMerge = []; - - // Find unchanged sequences without indices that can be merged with existing sequences without move - // notifications. - for (i = sequenceIndexEnd + 1; i < sequenceCountOld; i++) { - sequenceOld = sequencesOld[i]; - if (sequenceOld && (!sequenceOld.sequenceNew || sequenceOld.sequenceNew.sequenceOld !== sequenceOld)) { - //#DBG _ASSERT(!sequenceOld.indexRequested); - - // If the order of the known items in the sequence is unchanged, then the sequence probably has not - // moved, but we now know where it belongs relative to at least one other sequence. - var orderPreserved = true, - slotRefreshFirst = null, - slotRefreshLast = null, - sequenceLength = 0; - slotRefresh = slotRefreshFromSlot(sequenceOld.first); - if (slotRefresh) { - slotRefreshFirst = slotRefreshLast = slotRefresh; - sequenceLength = 1; - } - for (slot = sequenceOld.first; slot != sequenceOld.last; slot = slot.next) { - var slotRefreshNext = slotRefreshFromSlot(slot.next); - - if (slotRefresh && slotRefreshNext && (slotRefresh.lastInSequence || slotRefresh.next !== slotRefreshNext)) { - orderPreserved = false; - break; - } - - if (slotRefresh && !slotRefreshFirst) { - slotRefreshFirst = slotRefreshLast = slotRefresh; - } - - if (slotRefreshNext && slotRefreshFirst) { - slotRefreshLast = slotRefreshNext; - sequenceLength++; - } - - slotRefresh = slotRefreshNext; - } - - // If the stationary sequence has indices, verify that there is enough space for this sequence - if - // not, then something somewhere has moved after all. - if (orderPreserved && slotRefreshFirst && slotRefreshFirst.index !== undefined) { - var indexBefore; - if (!slotRefreshFirst.firstInSequence) { - slotBefore = slotFromSlotRefresh(slotRefreshFirst.prev); - if (slotBefore) { - indexBefore = slotBefore.index; - } - } - - var indexAfter; - if (!slotRefreshLast.lastInSequence) { - slotAfter = slotFromSlotRefresh(slotRefreshLast.next); - if (slotAfter) { - indexAfter = slotAfter.index; - } - } - - if ((!slotAfter || slotAfter.lastInSequence || slotAfter.mergedForRefresh) && - (indexBefore === undefined || indexAfter === undefined || indexAfter - indexBefore - 1 >= sequenceLength)) { - sequenceOld.locationJustDetermined = true; - - // Mark the individual refresh slots as not requiring move notifications - for (slotRefresh = slotRefreshFirst; ; slotRefresh = slotRefresh.next) { - slotRefresh.locationJustDetermined = true; - - if (slotRefresh === slotRefreshLast) { - break; - } - } - - // Store any adjacent placeholders so they can be merged once the moves and insertions have - // been processed. - var slotFirstInSequence = slotFromSlotRefresh(slotRefreshFirst), - slotLastInSequence = slotFromSlotRefresh(slotRefreshLast); - sequencePairsToMerge.push({ - slotBeforeSequence: (slotFirstInSequence.firstInSequence ? null : slotFirstInSequence.prev), - slotFirstInSequence: slotFirstInSequence, - slotLastInSequence: slotLastInSequence, - slotAfterSequence: (slotLastInSequence.lastInSequence ? null : slotLastInSequence.next) - }); - } - } - } - } - - // Remove placeholders in old sequences that don't map to new sequences (and don't contain requests for a - // specific index or key), as they no longer have meaning. - for (i = 0; i < sequenceCountOld; i++) { - sequenceOld = sequencesOld[i]; - if (sequenceOld && !sequenceOld.indexRequested && !sequenceOld.locationJustDetermined && (!sequenceOld.sequenceNew || sequenceOld.sequenceNew.sequenceOld !== sequenceOld)) { - sequenceOld.sequenceNew = null; - - slot = sequenceOld.first; - - var sequenceEndReached; - do { - sequenceEndReached = (slot === sequenceOld.last); - - slotNext = slot.next; - - if (slot !== slotsStart && slot !== slotListEnd && slot !== slotsEnd && !slot.item && !slot.keyRequested) { - //#DBG _ASSERT(!slot.indexRequested); - deleteSlot(slot, true); - if (sequenceOld.first === slot) { - if (sequenceOld.last === slot) { - delete sequencesOld[i]; - break; - } else { - sequenceOld.first = slot.next; - } - } else if (sequenceOld.last === slot) { - sequenceOld.last = slot.prev; - } - } - - slot = slotNext; - } while (!sequenceEndReached); - } - } - - /*#DBG - VERIFYLIST(); - #DBG*/ - - // Locate boundaries of new items in new sequences - for (i = 0; i < sequenceCountNew; i++) { - sequenceNew = sequencesNew[i]; - for (slotRefresh = sequenceNew.first; !slotFromSlotRefresh(slotRefresh) && !slotRefresh.lastInSequence; slotRefresh = slotRefresh.next) { - /*@empty*/ - } - if (slotRefresh.lastInSequence && !slotFromSlotRefresh(slotRefresh)) { - sequenceNew.firstInner = sequenceNew.lastInner = null; - } else { - sequenceNew.firstInner = slotRefresh; - for (slotRefresh = sequenceNew.last; !slotFromSlotRefresh(slotRefresh) ; slotRefresh = slotRefresh.prev) { - /*@empty*/ - } - sequenceNew.lastInner = slotRefresh; - } - } - - // Determine which items to move - for (i = 0; i < sequenceCountNew; i++) { - sequenceNew = sequencesNew[i]; - if (sequenceNew && sequenceNew.firstInner) { - sequenceOld = sequenceNew.sequenceOld; - if (sequenceOld) { - // Number the slots in each new sequence with their offset in the corresponding old sequence (or - // undefined if in a different old sequence). - var ordinal = 0; - for (slot = sequenceOld.first; true; slot = slot.next, ordinal++) { - slotRefresh = slotRefreshFromSlot(slot); - if (slotRefresh && slotRefresh.sequenceNumber === sequenceNew.firstInner.sequenceNumber) { - slotRefresh.ordinal = ordinal; - } - - if (slot.lastInSequence) { - //#DBG _ASSERT(slot === sequenceOld.last); - break; - } - } - - // Determine longest subsequence of items that are in the same order before and after - var piles = []; - for (slotRefresh = sequenceNew.firstInner; true; slotRefresh = slotRefresh.next) { - ordinal = slotRefresh.ordinal; - if (ordinal !== undefined) { - var searchFirst = 0, - searchLast = piles.length - 1; - while (searchFirst <= searchLast) { - var searchMidpoint = Math.floor(0.5 * (searchFirst + searchLast)); - if (piles[searchMidpoint].ordinal < ordinal) { - searchFirst = searchMidpoint + 1; - } else { - searchLast = searchMidpoint - 1; - } - } - piles[searchFirst] = slotRefresh; - if (searchFirst > 0) { - slotRefresh.predecessor = piles[searchFirst - 1]; - } - } - - if (slotRefresh === sequenceNew.lastInner) { - break; - } - } - - // The items in the longest ordered subsequence don't move; everything else does - var stationaryItems = [], - stationaryItemCount = piles.length; - //#DBG _ASSERT(stationaryItemCount > 0); - slotRefresh = piles[stationaryItemCount - 1]; - for (j = stationaryItemCount; j--;) { - slotRefresh.stationary = true; - stationaryItems[j] = slotRefresh; - slotRefresh = slotRefresh.predecessor; - } - //#DBG _ASSERT(!slotRefresh); - sequenceOld.stationarySlot = slotFromSlotRefresh(stationaryItems[0]); - - // Try to match new items before the first stationary item to placeholders - slotRefresh = stationaryItems[0]; - slot = slotFromSlotRefresh(slotRefresh); - slotPrev = slot.prev; - var sequenceBoundaryReached = slot.firstInSequence; - while (!slotRefresh.firstInSequence) { - slotRefresh = slotRefresh.prev; - slotExisting = slotFromSlotRefresh(slotRefresh); - if (!slotExisting || slotRefresh.locationJustDetermined) { - // Find the next placeholder walking backwards - while (!sequenceBoundaryReached && slotPrev !== slotsStart) { - slot = slotPrev; - slotPrev = slot.prev; - sequenceBoundaryReached = slot.firstInSequence; - - if (updateSlotForRefresh(slotExisting, slot, slotRefresh)) { - break; - } - } - } - } - - // Try to match new items between stationary items to placeholders - for (j = 0; j < stationaryItemCount - 1; j++) { - slotRefresh = stationaryItems[j]; - slot = slotFromSlotRefresh(slotRefresh); - //#DBG _ASSERT(slot); - var slotRefreshStop = stationaryItems[j + 1], - slotRefreshMergePoint = null, - slotStop = slotFromSlotRefresh(slotRefreshStop), - slotExisting; - //#DBG _ASSERT(slotStop); - - // Find all the new items - slotNext = slot.next; - for (slotRefresh = slotRefresh.next; slotRefresh !== slotRefreshStop && !slotRefreshMergePoint && slot !== slotStop; slotRefresh = slotRefresh.next) { - slotExisting = slotFromSlotRefresh(slotRefresh); - if (!slotExisting || slotRefresh.locationJustDetermined) { - // Find the next placeholder - while (slotNext !== slotStop) { - // If a merge point is reached, match the remainder of the placeholders by walking backwards - if (slotNext.mergedForRefresh) { - slotRefreshMergePoint = slotRefresh.prev; - break; - } - - slot = slotNext; - slotNext = slot.next; - - if (updateSlotForRefresh(slotExisting, slot, slotRefresh)) { - break; - } - } - } - } - - // Walk backwards to the first merge point if necessary - if (slotRefreshMergePoint) { - slotPrev = slotStop.prev; - for (slotRefresh = slotRefreshStop.prev; slotRefresh !== slotRefreshMergePoint && slotStop !== slot; slotRefresh = slotRefresh.prev) { - slotExisting = slotFromSlotRefresh(slotRefresh); - if (!slotExisting || slotRefresh.locationJustDetermined) { - // Find the next placeholder walking backwards - while (slotPrev !== slot) { - slotStop = slotPrev; - slotPrev = slotStop.prev; - - if (updateSlotForRefresh(slotExisting, slotStop, slotRefresh)) { - break; - } - } - } - } - } - - // Delete remaining placeholders, sending notifications - while (slotNext !== slotStop) { - slot = slotNext; - slotNext = slot.next; - - if (slot !== slotsStart && isPlaceholder(slot) && !slot.keyRequested) { - // This might occur due to two sequences - requested by different clients - being - // merged. However, since only sequences with indices are merged, if this placehholder - // is no longer necessary, it means an item actually was removed, so this doesn't count - // as a mirage. - deleteSlot(slot); - } - } - } - - // Try to match new items after the last stationary item to placeholders - slotRefresh = stationaryItems[stationaryItemCount - 1]; - slot = slotFromSlotRefresh(slotRefresh); - slotNext = slot.next; - sequenceBoundaryReached = slot.lastInSequence; - while (!slotRefresh.lastInSequence) { - slotRefresh = slotRefresh.next; - slotExisting = slotFromSlotRefresh(slotRefresh); - if (!slotExisting || slotRefresh.locationJustDetermined) { - // Find the next placeholder - while (!sequenceBoundaryReached && slotNext !== slotListEnd) { - slot = slotNext; - slotNext = slot.next; - sequenceBoundaryReached = slot.lastInSequence; - - if (updateSlotForRefresh(slotExisting, slot, slotRefresh)) { - break; - } - } - } - } - } - } - } - - /*#DBG - VERIFYLIST(); - #DBG*/ - - // Move items and send notifications - for (i = 0; i < sequenceCountNew; i++) { - sequenceNew = sequencesNew[i]; - - if (sequenceNew.firstInner) { - slotPrev = null; - for (slotRefresh = sequenceNew.firstInner; true; slotRefresh = slotRefresh.next) { - slot = slotFromSlotRefresh(slotRefresh); - if (slot) { - if (!slotRefresh.stationary) { - //#DBG _ASSERT(slot !== slotsStart); - //#DBG _ASSERT(slot !== slotsEnd); - - var slotMoveBefore, - mergeWithPrev = false, - mergeWithNext = false; - if (slotPrev) { - slotMoveBefore = slotPrev.next; - mergeWithPrev = true; - } else { - // The first item will be inserted before the first stationary item, so find that now - var slotRefreshStationary; - for (slotRefreshStationary = sequenceNew.firstInner; !slotRefreshStationary.stationary && slotRefreshStationary !== sequenceNew.lastInner; slotRefreshStationary = slotRefreshStationary.next) { - /*@empty*/ - } - - if (!slotRefreshStationary.stationary) { - // There are no stationary items, as all the items are moving from another old - // sequence. - - index = slotRefresh.index; - - // Find the best place to insert the new sequence - if (index === 0) { - // Index 0 is a special case - slotMoveBefore = slotsStart.next; - mergeWithPrev = true; - } else if (index === undefined) { - slotMoveBefore = slotsEnd; - } else { - // Use a linear search; unlike successorFromIndex, prefer the last insertion - // point between sequences over the precise index - slotMoveBefore = slotsStart.next; - var lastSequenceStart = null; - while (true) { - if (slotMoveBefore.firstInSequence) { - lastSequenceStart = slotMoveBefore; - } - - if ((index < slotMoveBefore.index && lastSequenceStart) || slotMoveBefore === slotListEnd) { - break; - } - - slotMoveBefore = slotMoveBefore.next; - } - - if (!slotMoveBefore.firstInSequence && lastSequenceStart) { - slotMoveBefore = lastSequenceStart; - } - } - } else { - slotMoveBefore = slotFromSlotRefresh(slotRefreshStationary); - mergeWithNext = true; - } - } - - // Preserve merge boundaries - if (slot.mergedForRefresh) { - delete slot.mergedForRefresh; - if (!slot.lastInSequence) { - slot.next.mergedForRefresh = true; - } - } - - mergeWithPrev = mergeWithPrev || slotRefresh.mergeWithPrev; - mergeWithNext = mergeWithNext || slotRefresh.mergeWithNext; - - var skipNotifications = slotRefresh.locationJustDetermined; - - moveSlot(slot, slotMoveBefore, mergeWithPrev, mergeWithNext, skipNotifications); - - if (skipNotifications && mergeWithNext) { - // Since this item was moved without a notification, this is an implicit merge of - // sequences. Mark the item's successor as mergedForRefresh. - slotMoveBefore.mergedForRefresh = true; - } - } - - slotPrev = slot; - } - - if (slotRefresh === sequenceNew.lastInner) { - break; - } - } - } - } - - /*#DBG - VERIFYLIST(); - #DBG*/ - - // Insert new items (with new indices) and send notifications - for (i = 0; i < sequenceCountNew; i++) { - sequenceNew = sequencesNew[i]; - - if (sequenceNew.firstInner) { - slotPrev = null; - for (slotRefresh = sequenceNew.firstInner; true; slotRefresh = slotRefresh.next) { - slot = slotFromSlotRefresh(slotRefresh); - if (!slot) { - var slotInsertBefore; - if (slotPrev) { - slotInsertBefore = slotPrev.next; - } else { - // The first item will be inserted *before* the first old item, so find that now - var slotRefreshOld; - for (slotRefreshOld = sequenceNew.firstInner; !slotFromSlotRefresh(slotRefreshOld) ; slotRefreshOld = slotRefreshOld.next) { - /*@empty*/ - //#DBG _ASSERT(slotRefreshOld !== sequenceNew.lastInner); - } - slotInsertBefore = slotFromSlotRefresh(slotRefreshOld); - } - - // Create a new slot for the item - slot = addNewSlotFromRefresh(slotRefresh, slotInsertBefore, !!slotPrev); - - var slotRefreshNext = slotRefreshFromSlot(slotInsertBefore); - - if (!slotInsertBefore.mergedForRefresh && (!slotRefreshNext || !slotRefreshNext.locationJustDetermined)) { - prepareSlotItem(slot); - - // Send the notification after the insertion - sendInsertedNotification(slot); - } - } - slotPrev = slot; - - if (slotRefresh === sequenceNew.lastInner) { - break; - } - } - } - } - - /*#DBG - VERIFYLIST(); - #DBG*/ - - // Rebuild the indexMap from scratch, so it is possible to detect colliding indices - indexMap = []; - - // Send indexChanged and changed notifications - var indexFirst = -1; - for (slot = slotsStart, offset = 0; slot !== slotsEnd; offset++) { - var slotNext = slot.next; - - if (slot.firstInSequence) { - slotFirstInSequence = slot; - offset = 0; - } - - if (indexFirst === undefined) { - var indexNew = indexForRefresh(slot); - if (indexNew !== undefined) { - indexFirst = indexNew - offset; - } - } - - // See if the next slot would cause a contradiction, in which case split the sequences - if (indexFirst !== undefined && !slot.lastInSequence) { - var indexNewNext = indexForRefresh(slot.next); - if (indexNewNext !== undefined && indexNewNext !== indexFirst + offset + 1) { - splitSequence(slot); - - // 'Move' the items in-place individually, so move notifications are sent. In rare cases, this - // will result in multiple move notifications being sent for a given item, but that's fine. - var first = true; - for (var slotMove = slot.next, lastInSequence = false; !lastInSequence && slotMove !== slotListEnd;) { - var slotMoveNext = slotMove.next; - - lastInSequence = slotMove.lastInSequence; - - moveSlot(slotMove, slotMoveNext, !first, false); - - first = false; - slotMove = slotMoveNext; - } - } - } - - if (slot.lastInSequence) { - index = indexFirst; - for (var slotUpdate = slotFirstInSequence; slotUpdate !== slotNext;) { - var slotUpdateNext = slotUpdate.next; - - if (index >= refreshCount && slotUpdate !== slotListEnd) { - deleteSlot(slotUpdate, true); - } else { - var slotWithIndex = indexMap[index]; - - if (index !== slotUpdate.index) { - delete indexMap[index]; - changeSlotIndex(slotUpdate, index); - } else if (+index === index && indexMap[index] !== slotUpdate) { - indexMap[index] = slotUpdate; - } - - if (slotUpdate.itemNew) { - updateSlotItem(slotUpdate); - } - - if (slotWithIndex) { - // Two slots' indices have collided - merge them - if (slotUpdate.key) { - sendMirageNotifications(slotUpdate, slotWithIndex, slotUpdate.bindingMap); - mergeSlots(slotUpdate, slotWithIndex); - if (+index === index) { - indexMap[index] = slotUpdate; - } - } else { - sendMirageNotifications(slotWithIndex, slotUpdate, slotWithIndex.bindingMap); - mergeSlots(slotWithIndex, slotUpdate); - if (+index === index) { - indexMap[index] = slotWithIndex; - } - } - } - - if (+index === index) { - index++; - } - } - - slotUpdate = slotUpdateNext; - } - - indexFirst = undefined; - } - - slot = slotNext; - } - - // See if any sequences need to be moved and/or merged - var indexMax = -2, - listEndReached; - - for (slot = slotsStart, offset = 0; slot !== slotsEnd; offset++) { - var slotNext = slot.next; - - if (slot.firstInSequence) { - slotFirstInSequence = slot; - offset = 0; - } - - // Clean up during this pass - delete slot.mergedForRefresh; - - if (slot.lastInSequence) { - // Move sequence if necessary - if (slotFirstInSequence.index === undefined) { - slotBefore = slotFirstInSequence.prev; - var slotRefreshBefore; - if (slotBefore && (slotRefreshBefore = slotRefreshFromSlot(slotBefore)) && !slotRefreshBefore.lastInSequence && - (slotRefresh = slotRefreshFromSlot(slot)) && slotRefresh.prev === slotRefreshBefore) { - moveSequenceAfter(slotBefore, slotFirstInSequence, slot); - mergeSequences(slotBefore); - } else if (slot !== slotListEnd && !listEndReached) { - moveSequenceBefore(slotsEnd, slotFirstInSequence, slot); - } - } else { - //#DBG _ASSERT(slot.index !== undefined); - if (indexMax < slot.index && !listEndReached) { - indexMax = slot.index; - } else { - // Find the correct insertion point - for (slotAfter = slotsStart.next; slotAfter.index < slot.index; slotAfter = slotAfter.next) { - /*@empty*/ - } - - // Move the items individually, so move notifications are sent - for (var slotMove = slotFirstInSequence; slotMove !== slotNext;) { - var slotMoveNext = slotMove.next; - slotRefresh = slotRefreshFromSlot(slotMove); - moveSlot(slotMove, slotAfter, slotAfter.prev.index === slotMove.index - 1, slotAfter.index === slotMove.index + 1, slotRefresh && slotRefresh.locationJustDetermined); - slotMove = slotMoveNext; - } - } - - // Store slotBefore here since the sequence might have just been moved - slotBefore = slotFirstInSequence.prev; - - // See if this sequence should be merged with the previous one - if (slotBefore && slotBefore.index === slotFirstInSequence.index - 1) { - mergeSequences(slotBefore); - } - } - } - - if (slot === slotListEnd) { - listEndReached = true; - } - - slot = slotNext; - } - - indexUpdateDeferred = false; - - /*#DBG - VERIFYLIST(); - #DBG*/ - - // Now that all the sequences have been moved, merge any colliding slots - mergeSequencePairs(sequencePairsToMerge); - - /*#DBG - VERIFYLIST(); - #DBG*/ - - // Send countChanged notification - if (refreshCount !== undefined && refreshCount !== knownCount) { - changeCount(refreshCount); - } - - /*#DBG - VERIFYLIST(); - #DBG*/ - - finishNotifications(); - - // Before discarding the refresh slot list, see if any fetch requests can be completed by pretending each range - // of refresh slots is an incoming array of results. - var fetchResults = []; - for (i = 0; i < sequenceCountNew; i++) { - sequenceNew = sequencesNew[i]; - - var results = []; - - slot = null; - offset = 0; - - var slotOffset; - - for (slotRefresh = sequenceNew.first; true; slotRefresh = slotRefresh.next, offset++) { - if (slotRefresh === refreshStart) { - results.push(startMarker); - } else if (slotRefresh === refreshEnd) { - results.push(endMarker); - } else { - results.push(slotRefresh.item); - - if (!slot) { - slot = slotFromSlotRefresh(slotRefresh); - slotOffset = offset; - } - } - - if (slotRefresh.lastInSequence) { - //#DBG _ASSERT(slotRefresh === sequenceNew.last); - break; - } - } - - if (slot) { - fetchResults.push({ - slot: slot, - results: results, - offset: slotOffset - }); - } - } - - resetRefreshState(); - refreshInProgress = false; - - /*#DBG - VERIFYLIST(); - #DBG*/ - - // Complete any promises for newly obtained items - callFetchCompleteCallbacks(); - - // Now process the 'extra' results from the refresh list - for (i = 0; i < fetchResults.length; i++) { - var fetchResult = fetchResults[i]; - processResults(fetchResult.slot, fetchResult.results, fetchResult.offset, knownCount, fetchResult.slot.index); - } - - if (refreshSignal) { - var signal = refreshSignal; - - refreshSignal = null; - - signal.complete(); - } - - // Finally, kick-start fetches for any remaining placeholders - postFetch(); - } - - // Edit Queue - - // Queues an edit and immediately "optimistically" apply it to the slots list, sending re-entrant notifications - function queueEdit(applyEdit, editType, complete, error, keyUpdate, updateSlots, undo) { - var editQueueTail = editQueue.prev, - edit = { - prev: editQueueTail, - next: editQueue, - applyEdit: applyEdit, - editType: editType, - complete: complete, - error: error, - keyUpdate: keyUpdate - }; - editQueueTail.next = edit; - editQueue.prev = edit; - editsQueued = true; - - // If there's a refresh in progress, abandon it, but request that a new one be started once the edits complete - if (refreshRequested || refreshInProgress) { - currentRefreshID++; - refreshInProgress = false; - refreshRequested = true; - } - - if (editQueue.next === edit) { - // Attempt the edit immediately, in case it completes synchronously - applyNextEdit(); - } - - // If the edit succeeded or is still pending, apply it to the slots (in the latter case, "optimistically") - if (!edit.failed) { - updateSlots(); - - // Supply the undo function now - edit.undo = undo; - } - - if (!editsInProgress) { - completeEdits(); - } - } - - function dequeueEdit() { - firstEditInProgress = false; - - //#DBG _ASSERT(editQueue.next !== editQueue); - var editNext = editQueue.next.next; - - editQueue.next = editNext; - editNext.prev = editQueue; - } - - // Undo all queued edits, starting with the most recent - function discardEditQueue() { - while (editQueue.prev !== editQueue) { - var editLast = editQueue.prev; - - if (editLast.error) { - editLast.error(new WinJS.ErrorFromName(UI.EditError.canceled)); - } - - // Edits that haven't been applied to the slots yet don't need to be undone - if (editLast.undo && !refreshRequested) { - editLast.undo(); - } - - editQueue.prev = editLast.prev; - } - editQueue.next = editQueue; - - editsInProgress = false; - - completeEdits(); - } - - var EditType = { - insert: "insert", - change: "change", - move: "move", - remove: "remove" - }; - - function attemptEdit(edit) { - if (firstEditInProgress) { - return; - } - - var reentrant = true; - - function continueEdits() { - if (!waitForRefresh) { - if (reentrant) { - synchronousEdit = true; - } else { - applyNextEdit(); - } - } - } - - var keyUpdate = edit.keyUpdate; - - function onEditComplete(item) { - if (item) { - if (keyUpdate && keyUpdate.key !== item.key) { - //#DBG _ASSERT(edit.editType === EditType.insert); - - var keyNew = item.key; - if (!edit.undo) { - // If the edit is in the process of being queued, we can use the correct key when we update the - // slots, so there's no need for a later update. - keyUpdate.key = keyNew; - } else { - var slot = keyUpdate.slot; - if (slot) { - var keyOld = slot.key; - if (keyOld) { - //#DBG _ASSERT(slot.key === keyOld); - //#DBG _ASSERT(keyMap[keyOld] === slot); - delete keyMap[keyOld]; - } - /*#DBG - // setSlotKey asserts that the slot key is absent - delete slot.key; - #DBG*/ - - setSlotKey(slot, keyNew); - slot.itemNew = item; - if (slot.item) { - changeSlot(slot); - finishNotifications(); - } else { - completeFetchPromises(slot); - } - } - } - } else if (edit.editType === EditType.change) { - //#DBG _ASSERT(slot.item); - slot.itemNew = item; - - if (!reentrant) { - changeSlotIfNecessary(slot); - } - } - } - - dequeueEdit(); - - if (edit.complete) { - edit.complete(item); - } - - continueEdits(); - } - - function onEditError(error) { - switch (error.Name) { - case EditError.noResponse: - // Report the failure to the client, but do not dequeue the edit - setStatus(DataSourceStatus.failure); - waitForRefresh = true; - - firstEditInProgress = false; - - // Don't report the error, as the edit will be attempted again on the next refresh - return; - - case EditError.notPermitted: - break; - - case EditError.noLongerMeaningful: - // Something has changed, so request a refresh - beginRefresh(); - break; - - default: - break; - } - - // Discard all remaining edits, rather than try to determine which subsequent ones depend on this one - edit.failed = true; - dequeueEdit(); - - discardEditQueue(); - - if (edit.error) { - edit.error(error); - } - - continueEdits(); - } - - if (listDataAdapter.beginEdits && !beginEditsCalled) { - beginEditsCalled = true; - listDataAdapter.beginEdits(); - } - - // Call the applyEdit function for the given edit, passing in our own wrapper of the error handler that the - // client passed in. - firstEditInProgress = true; - edit.applyEdit().then(onEditComplete, onEditError); - reentrant = false; - } - - function applyNextEdit() { - // See if there are any outstanding edits, and try to process as many as possible synchronously - while (editQueue.next !== editQueue) { - synchronousEdit = false; - attemptEdit(editQueue.next); - if (!synchronousEdit) { - return; - } - } - - // The queue emptied out synchronously (or was empty to begin with) - concludeEdits(); - } - - function completeEdits() { - //#DBG _ASSERT(!editsInProgress); - - updateIndices(); - - finishNotifications(); - - callFetchCompleteCallbacks(); - - if (editQueue.next === editQueue) { - concludeEdits(); - } - } - - // Once the edit queue has emptied, update state appropriately and resume normal operation - function concludeEdits() { - editsQueued = false; - - if (listDataAdapter.endEdits && beginEditsCalled && !editsInProgress) { - beginEditsCalled = false; - listDataAdapter.endEdits(); - } - - // See if there's a refresh that needs to begin - if (refreshRequested) { - refreshRequested = false; - beginRefresh(); - } else { - // Otherwise, see if anything needs to be fetched - postFetch(); - } - } - - // Editing Operations - - function getSlotForEdit(key) { - validateKey(key); - - return keyMap[key] || createSlotForKey(key); - } - - function insertNewSlot(key, itemNew, slotInsertBefore, mergeWithPrev, mergeWithNext) { - // Create a new slot, but don't worry about its index, as indices will be updated during endEdits - var slot = createPrimarySlot(); - - insertAndMergeSlot(slot, slotInsertBefore, mergeWithPrev, mergeWithNext); - if (key) { - setSlotKey(slot, key); - } - slot.itemNew = itemNew; - - updateNewIndices(slot, 1); - - // If this isn't part of a batch of changes, set the slot index now so renderers can see it - if (!editsInProgress && !dataNotificationsInProgress) { - if (!slot.firstInSequence && typeof slot.prev.index === "number") { - setSlotIndex(slot, slot.prev.index + 1, indexMap); - } else if (!slot.lastInSequence && typeof slot.next.index === "number") { - setSlotIndex(slot, slot.next.index - 1, indexMap); - } - } - - prepareSlotItem(slot); - - // Send the notification after the insertion - sendInsertedNotification(slot); - - return slot; - } - - function insertItem(key, data, slotInsertBefore, append, applyEdit) { - var keyUpdate = { key: key }; - - return new Promise(function (complete, error) { - queueEdit( - applyEdit, EditType.insert, complete, error, keyUpdate, - - // updateSlots - function () { - if (slotInsertBefore) { - var itemNew = { - key: keyUpdate.key, - data: data - }; - - keyUpdate.slot = insertNewSlot(keyUpdate.key, itemNew, slotInsertBefore, append, !append); - } - }, - - // undo - function () { - var slot = keyUpdate.slot; - - if (slot) { - updateNewIndices(slot, -1); - deleteSlot(slot, false); - } - } - ); - }); - } - - function moveItem(slot, slotMoveBefore, append, applyEdit) { - return new Promise(function (complete, error) { - var mergeAdjacent, - slotNext, - firstInSequence, - lastInSequence; - - queueEdit( - applyEdit, EditType.move, complete, error, - - // keyUpdate - null, - - // updateSlots - function () { - slotNext = slot.next; - firstInSequence = slot.firstInSequence; - lastInSequence = slot.lastInSequence; - - var slotPrev = slot.prev; - - mergeAdjacent = (typeof slot.index !== "number" && (firstInSequence || !slotPrev.item) && (lastInSequence || !slotNext.item)); - - updateNewIndices(slot, -1); - moveSlot(slot, slotMoveBefore, append, !append); - updateNewIndices(slot, 1); - - if (mergeAdjacent) { - splitSequence(slotPrev); - - if (!firstInSequence) { - mergeSlotsBefore(slotPrev, slot); - } - if (!lastInSequence) { - mergeSlotsAfter(slotNext, slot); - } - } - }, - - // undo - function () { - if (!mergeAdjacent) { - updateNewIndices(slot, -1); - moveSlot(slot, slotNext, !firstInSequence, !lastInSequence); - updateNewIndices(slot, 1); - } else { - beginRefresh(); - } - } - ); - }); - } - - function ListDataNotificationHandler() { - /// - /// - /// An implementation of IListDataNotificationHandler that is passed to the - /// IListDataAdapter.setNotificationHandler method. - /// - /// - - this.invalidateAll = function () { - /// - /// - /// Notifies the VirtualizedDataSource that some data has changed, without specifying which data. It might - /// be impractical for some data sources to call this method for any or all changes, so this call is optional. - /// But if a given data adapter never calls it, the application should periodically call - /// invalidateAll on the VirtualizedDataSource to refresh the data. - /// - /// - /// A Promise that completes when the data has been completely refreshed and all change notifications have - /// been sent. - /// - /// - - if (knownCount === 0) { - this.reload(); - return Promise.wrap(); - } - - return requestRefresh(); - }; - - this.reload = function () { - /// - /// - /// Notifies the list data source that the list data has changed so much that it is better - /// to reload the data from scratch. - /// - /// - - // Cancel all promises - - if (getCountPromise) { - getCountPromise.cancel(); - } - - if (refreshSignal) { - refreshSignal.cancel(); - } - - for (var slot = slotsStart.next; slot !== slotsEnd; slot = slot.next) { - var fetchListeners = slot.fetchListeners; - for (var listenerID in fetchListeners) { - fetchListeners[listenerID].promise.cancel(); - } - var directFetchListeners = slot.directFetchListeners; - for (var listenerID in directFetchListeners) { - directFetchListeners[listenerID].promise.cancel(); - } - } - - resetState(); - - forEachBindingRecord(function (bindingRecord) { - if (bindingRecord.notificationHandler) { - bindingRecord.notificationHandler.reload(); - } - }); - }; - - this.beginNotifications = function () { - /// - /// - /// Indicates the start of a notification batch. - /// Call it before a sequence of other notification calls to minimize the number of countChanged and - /// indexChanged notifications sent to the client of the VirtualizedDataSource. You must pair it with a call - /// to endNotifications, and pairs can't be nested. - /// - /// - - dataNotificationsInProgress = true; - }; - - function completeNotification() { - if (!dataNotificationsInProgress) { - updateIndices(); - finishNotifications(); - - callFetchCompleteCallbacks(); - } - } - - this.inserted = function (newItem, previousKey, nextKey, index) { - /// - /// - /// Raises a notification that an item was inserted. - /// - /// - /// The inserted item. It must have a key and a data property (it must implement the IItem interface). - /// - /// - /// The key of the item before the insertion point, or null if the item was inserted at the start of the - /// list. It can be null if you specified nextKey. - /// - /// - /// The key of the item after the insertion point, or null if the item was inserted at the end of the list. - /// It can be null if you specified previousKey. - /// - /// - /// The index of the inserted item. - /// - /// - - if (editsQueued) { - // We can't change the slots out from under any queued edits - beginRefresh(); - } else { - var key = newItem.key, - slotPrev = keyMap[previousKey], - slotNext = keyMap[nextKey]; - - var havePreviousKey = typeof previousKey === "string", - haveNextKey = typeof nextKey === "string"; - - // Only one of previousKey, nextKey needs to be passed in - // - if (havePreviousKey) { - if (slotNext && !slotNext.firstInSequence) { - slotPrev = slotNext.prev; - } - } else if (haveNextKey) { - if (slotPrev && !slotPrev.lastInSequence) { - slotNext = slotPrev.next; - } - } - - // If the VDS believes the list is empty but the data adapter believes the item has - // a adjacent item start a refresh. - // - if ((havePreviousKey || haveNextKey) && !(slotPrev || slotNext) && (slotsStart.next === slotListEnd)) { - beginRefresh(); - return; - } - - // If this key is known, something has changed, start a refresh. - // - if (keyMap[key]) { - beginRefresh(); - return; - } - - // If the slots aren't adjacent or are thought to be distinct sequences by the - // VDS something has changed so start a refresh. - // - if (slotPrev && slotNext) { - if (slotPrev.next !== slotNext || slotPrev.lastInSequence || slotNext.firstInSequence) { - beginRefresh(); - return; - } - } - - // If one of the adjacent keys or indicies has only just been requested - rare, - // and easier to deal with in a refresh. - // - if ((slotPrev && (slotPrev.keyRequested || slotPrev.indexRequested)) || - (slotNext && (slotNext.keyRequested || slotNext.indexRequested))) { - beginRefresh(); - return; - } - - if (slotPrev || slotNext) { - insertNewSlot(key, newItem, (slotNext ? slotNext : slotPrev.next), !!slotPrev, !!slotNext); - } else if (slotsStart.next === slotListEnd) { - insertNewSlot(key, newItem, slotsStart.next, true, true); - } else if (index !== undefined) { - updateNewIndicesFromIndex(index, 1); - } else { - // We could not find a previous or next slot and an index was not provided, start a refresh - // - beginRefresh(); - return; - } - - completeNotification(); - } - }; - - this.changed = function (item) { - /// - /// - /// Raises a notification that an item changed. - /// - /// - /// An IItem that represents the item that changed. - /// - /// - - if (editsQueued) { - // We can't change the slots out from under any queued edits - beginRefresh(); - } else { - var key = item.key, - slot = keyMap[key]; - - if (slot) { - if (slot.keyRequested) { - // The key has only just been requested - rare, and easier to deal with in a refresh - beginRefresh(); - } else { - slot.itemNew = item; - - if (slot.item) { - changeSlot(slot); - - completeNotification(); - } - } - } - } - }; - - this.moved = function (item, previousKey, nextKey, oldIndex, newIndex) { - /// - /// - /// Raises a notfication that an item was moved. - /// - /// - /// The item that was moved. - /// - /// - /// The key of the item before the insertion point, or null if the item was moved to the beginning of the list. - /// It can be null if you specified nextKey. - /// - /// - /// The key of the item after the insertion point, or null if the item was moved to the end of the list. - /// It can be null if you specified previousKey. - /// - /// - /// The index of the item before it was moved. - /// - /// - /// The index of the item after it was moved. - /// - /// - - if (editsQueued) { - // We can't change the slots out from under any queued edits - beginRefresh(); - } else { - var key = item.key, - slot = keyMap[key], - slotPrev = keyMap[previousKey], - slotNext = keyMap[nextKey]; - - if ((slot && slot.keyRequested) || (slotPrev && slotPrev.keyRequested) || (slotNext && slotNext.keyRequested)) { - // One of the keys has only just been requested - rare, and easier to deal with in a refresh - beginRefresh(); - } else if (slot) { - if (slotPrev && slotNext && (slotPrev.next !== slotNext || slotPrev.lastInSequence || slotNext.firstInSequence)) { - // Something has changed, start a refresh - beginRefresh(); - } else if (!slotPrev && !slotNext) { - // If we can't tell where the item moved to, treat this like a removal - updateNewIndices(slot, -1); - deleteSlot(slot, false); - - if (oldIndex !== undefined) { - if (oldIndex < newIndex) { - newIndex--; - } - - updateNewIndicesFromIndex(newIndex, 1); - } - - completeNotification(); - } else { - updateNewIndices(slot, -1); - moveSlot(slot, (slotNext ? slotNext : slotPrev.next), !!slotPrev, !!slotNext); - updateNewIndices(slot, 1); - - completeNotification(); - } - } else if (slotPrev || slotNext) { - // If previousKey or nextKey is known, but key isn't, treat this like an insertion. - - if (oldIndex !== undefined) { - updateNewIndicesFromIndex(oldIndex, -1); - - if (oldIndex < newIndex) { - newIndex--; - } - } - - this.inserted(item, previousKey, nextKey, newIndex); - } else if (oldIndex !== undefined) { - updateNewIndicesFromIndex(oldIndex, -1); - - if (oldIndex < newIndex) { - newIndex--; - } - - updateNewIndicesFromIndex(newIndex, 1); - - completeNotification(); - } - } - }; - - this.removed = function (key, index) { - /// - /// - /// Raises a notification that an item was removed. - /// - /// - /// The key of the item that was removed. - /// - /// - /// The index of the item that was removed. - /// - /// - - if (editsQueued) { - // We can't change the slots out from under any queued edits - beginRefresh(); - } else { - var slot; - - if (typeof key === "string") { - slot = keyMap[key]; - } else { - slot = indexMap[index]; - } - - if (slot) { - if (slot.keyRequested) { - // The key has only just been requested - rare, and easier to deal with in a refresh - beginRefresh(); - } else { - updateNewIndices(slot, -1); - deleteSlot(slot, false); - - completeNotification(); - } - } else if (index !== undefined) { - updateNewIndicesFromIndex(index, -1); - completeNotification(); - } - } - }; - - this.endNotifications = function () { - /// - /// - /// Concludes a sequence of notifications that began with a call to beginNotifications. - /// - /// - - dataNotificationsInProgress = false; - completeNotification(); - }; - - } // ListDataNotificationHandler - - function resetState() { - setStatus(DataSourceStatus.ready); - - // Track count promises - getCountPromise = null; - - // Track whether listDataAdapter.endEdits needs to be called - beginEditsCalled = false; - - // Track whether finishNotifications should be called after each edit - editsInProgress = false; - - // Track whether the first queued edit should be attempted - firstEditInProgress = false; - - // Queue of edis that have yet to be completed - editQueue = {}; - editQueue.next = editQueue; - editQueue.prev = editQueue; - /*#DBG - editQueue.debugInfo = "*** editQueueHead/Tail ***"; - #DBG*/ - - // Track whether there are currently edits queued - editsQueued = false; - - // If an edit has returned noResponse, the edit queue will be reapplied when the next refresh is requested - waitForRefresh = false; - - // Change to count while multiple edits are taking place - countDelta = 0; - - // True while the indices are temporarily in a bad state due to multiple edits - indexUpdateDeferred = false; - - // Next temporary key to use - nextTempKey = 0; - - // Set of fetches for which results have not yet arrived - fetchesInProgress = {}; - - // Queue of complete callbacks for fetches - fetchCompleteCallbacks = []; - - // Tracks the count returned explicitly or implicitly by the data adapter - knownCount = CountResult.unknown; - - // Sentinel objects for list of slots - // Give the start sentinel an index so we can always use predecessor + 1. - slotsStart = { - firstInSequence: true, - lastInSequence: true, - index: -1 - }; - slotListEnd = { - firstInSequence: true, - lastInSequence: true - }; - slotsEnd = { - firstInSequence: true, - lastInSequence: true - }; - slotsStart.next = slotListEnd; - slotListEnd.prev = slotsStart; - slotListEnd.next = slotsEnd; - slotsEnd.prev = slotListEnd; - - /*#DBG - slotsStart.debugInfo = "*** slotsStart ***"; - slotListEnd.debugInfo = "*** slotListEnd ***"; - slotsEnd.debugInfo = "*** slotsEnd ***"; - #DBG*/ - - // Map of request IDs to slots - handleMap = {}; - - // Map of keys to slots - keyMap = {}; - - // Map of indices to slots - indexMap = {}; - indexMap[-1] = slotsStart; - - // Count of slots that have been released but not deleted - releasedSlots = 0; - - lastSlotReleased = null; - - // At most one call to reduce the number of refresh slots should be posted at any given time - reduceReleasedSlotCountPosted = false; - - // Multiple refresh requests are coalesced - refreshRequested = false; - - // Requests do not cause fetches while a refresh is in progress - refreshInProgress = false; - - // Refresh requests yield the same promise until a refresh completes - refreshSignal = null; - } - - // Construction - - // Process creation parameters - if (!listDataAdapter) { - throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.ListDataAdapterIsInvalid", strings.listDataAdapterIsInvalid); - } - - // Minimum number of released slots to retain - cacheSize = (listDataAdapter.compareByIdentity ? 0 : 200); - - if (options) { - if (typeof options.cacheSize === "number") { - cacheSize = options.cacheSize; - } - } - - // Cached listDataNotificationHandler initially undefined - if (listDataAdapter.setNotificationHandler) { - listDataNotificationHandler = new ListDataNotificationHandler(); - - listDataAdapter.setNotificationHandler(listDataNotificationHandler); - } - - // Current status - status = DataSourceStatus.ready; - - // Track whether a change to the status has been posted already - statusChangePosted = false; - - // Map of bindingIDs to binding records - bindingMap = {}; - - // ID to assign to the next ListBinding, incremented each time one is created - nextListBindingID = 0; - - // ID assigned to a slot, incremented each time one is created - start with 1 so "if (handle)" tests are valid - nextHandle = 1; - - // ID assigned to a fetch listener, incremented each time one is created - nextListenerID = 0; - - // ID of the refresh in progress, incremented each time a new refresh is started - currentRefreshID = 0; - - // Track whether fetchItemsForAllSlots has been posted already - fetchesPosted = false; - - // ID of a fetch, incremented each time a new fetch is initiated - start with 1 so "if (fetchID)" tests are valid - nextFetchID = 1; - - // Sentinel objects for results arrays - startMarker = {}; - endMarker = {}; - - resetState(); - - /*#DBG - this._debugBuild = true; - - Object.defineProperty(this, "_totalSlots", { - get: function () { - return totalSlots; - } - }); - - Object.defineProperty(this, "_releasedSlots", { - get: function () { - return releasedSlots; - } - }); - #DBG*/ - - // Public methods - - this.createListBinding = function (notificationHandler) { - /// - /// - /// Creates an IListBinding object that allows a client to read from the list and receive notifications for - /// changes that affect those portions of the list that the client already read. - /// - /// - /// An object that implements the IListNotificationHandler interface. If you omit this parameter, - /// change notifications won't be available. - /// - /// - /// An object that implements the IListBinding interface. - /// - /// - - var listBindingID = (nextListBindingID++).toString(), - slotCurrent = null, - released = false; - - function retainSlotForCursor(slot) { - if (slot) { - slot.cursorCount++; - } - } - - function releaseSlotForCursor(slot) { - if (slot) { - //#DBG _ASSERT(slot.cursorCount > 0); - if (--slot.cursorCount === 0) { - releaseSlotIfUnrequested(slot); - } - } - } - - function moveCursor(slot) { - // Retain the new slot first just in case it's the same slot - retainSlotForCursor(slot); - releaseSlotForCursor(slotCurrent); - slotCurrent = slot; - } - - function adjustCurrentSlot(slot, slotNew) { - if (slot === slotCurrent) { - if (!slotNew) { - slotNew = ( - !slotCurrent || slotCurrent.lastInSequence || slotCurrent.next === slotListEnd ? - null : - slotCurrent.next - ); - } - moveCursor(slotNew); - } - } - - function releaseSlotFromListBinding(slot) { - var bindingMap = slot.bindingMap, - bindingHandle = bindingMap[listBindingID].handle; - - delete slot.bindingMap[listBindingID]; - - // See if there are any listBindings left in the map - var releaseBindingMap = true, - releaseHandle = true; - for (var listBindingID2 in bindingMap) { - releaseBindingMap = false; - if (bindingHandle && bindingMap[listBindingID2].handle === bindingHandle) { - releaseHandle = false; - break; - } - } - - if (bindingHandle && releaseHandle) { - delete handleMap[bindingHandle]; - } - if (releaseBindingMap) { - slot.bindingMap = null; - releaseSlotIfUnrequested(slot); - } - } - - function retainItem(slot, listenerID) { - if (!slot.bindingMap) { - slot.bindingMap = {}; - } - - var slotBinding = slot.bindingMap[listBindingID]; - if (slotBinding) { - slotBinding.count++; - } else { - slot.bindingMap[listBindingID] = { - bindingRecord: bindingMap[listBindingID], - count: 1 - }; - } - - if (slot.fetchListeners) { - var listener = slot.fetchListeners[listenerID]; - if (listener) { - listener.retained = true; - } - } - } - - function releaseItem(handle) { - var slot = handleMap[handle]; - - //#DBG _ASSERT(slot); - if (slot) { - var slotBinding = slot.bindingMap[listBindingID]; - if (--slotBinding.count === 0) { - var fetchListeners = slot.fetchListeners; - for (var listenerID in fetchListeners) { - var listener = fetchListeners[listenerID]; - if (listener.listBindingID === listBindingID) { - listener.retained = false; - } - } - - releaseSlotFromListBinding(slot); - } - } - } - - function itemPromiseFromKnownSlot(slot) { - var handle = handleForBinding(slot, listBindingID), - listenerID = (nextListenerID++).toString(); - - var itemPromise = createFetchPromise(slot, "fetchListeners", listenerID, listBindingID, - function (complete, item) { - complete(itemForBinding(item, handle)); - } - ); - - defineCommonItemProperties(itemPromise, slot, handle); - - // Only implement retain and release methods if a notification handler has been supplied - if (notificationHandler) { - itemPromise.retain = function () { - listBinding._retainItem(slot, listenerID); - return itemPromise; - }; - - itemPromise.release = function () { - listBinding._releaseItem(handle); - }; - } - - return itemPromise; - } - - bindingMap[listBindingID] = { - notificationHandler: notificationHandler, - notificationsSent: false, - adjustCurrentSlot: adjustCurrentSlot, - itemPromiseFromKnownSlot: itemPromiseFromKnownSlot, - }; - - function itemPromiseFromSlot(slot) { - var itemPromise; - - if (!released && slot) { - itemPromise = itemPromiseFromKnownSlot(slot); - } else { - // Return a complete promise for a non-existent slot - if (released) { - itemPromise = new Promise(function () { }); - itemPromise.cancel(); - } else { - itemPromise = Promise.wrap(null); - } - defineHandleProperty(itemPromise, null); - // Only implement retain and release methods if a notification handler has been supplied - if (notificationHandler) { - itemPromise.retain = function () { return itemPromise; }; - itemPromise.release = function () { }; - } - } - - moveCursor(slot); - - return itemPromise; - } - - /// - /// - /// An interface that enables a client to read from the list and receive notifications for changes that affect - /// those portions of the list that the client already read. IListBinding can also enumerate through lists - /// that can change at any time. - /// - /// - var listBinding = { - _retainItem: function (slot, listenerID) { - retainItem(slot, listenerID); - }, - - _releaseItem: function (handle) { - releaseItem(handle); - }, - - jumpToItem: function (item) { - /// - /// - /// Makes the specified item the current item. - /// - /// - /// The IItem or IItemPromise to make the current item. - /// - /// - /// An object that implements the IItemPromise interface and serves as a promise for the specified item. If - /// the specified item is not in the list, the promise completes with a value of null. - /// - /// - - return itemPromiseFromSlot(item ? handleMap[item.handle] : null); - }, - - current: function () { - /// - /// - /// Retrieves the current item. - /// - /// - /// An object that implements the IItemPromise interface and serves as a promise for the current item. - /// If the cursor has moved past the start or end of the list, the promise completes with a value - /// of null. If the current item has been deleted or moved, the promise returns an error. - /// - /// - - return itemPromiseFromSlot(slotCurrent); - }, - - previous: function () { - /// - /// - /// Retrieves the item before the current item and makes it the current item. - /// - /// - /// An object that implements the IItemPromise interface and serves as a promise for the previous item. - /// If the cursor moves past the start of the list, the promise completes with a value of null. - /// - /// - - return itemPromiseFromSlot(slotCurrent ? requestSlotBefore(slotCurrent) : null); - }, - - next: function () { - /// - /// - /// Retrieves the item after the current item and makes it the current item. - /// - /// - /// An object that implements the IItemPromise interface and serves as a promise for the next item. If - /// the cursor moves past the end of the list, the promise completes with a value of null. - /// - /// - - return itemPromiseFromSlot(slotCurrent ? requestSlotAfter(slotCurrent) : null); - }, - - releaseItem: function (item) { - /// - /// - /// Creates a request to stop change notfications for the specified item. The item is released only when the - /// number of release calls matches the number of IItemPromise.retain calls. The number of release calls cannot - /// exceed the number of retain calls. This method is present only if you passed an IListNotificationHandler - /// to IListDataSource.createListBinding when it created this IListBinding. - /// - /// - /// The IItem or IItemPromise to release. - /// - /// - - this._releaseItem(item.handle); - }, - - release: function () { - /// - /// - /// Releases resources, stops notifications, and cancels outstanding promises - /// for all tracked items that this IListBinding returned. - /// - /// - - released = true; - - releaseSlotForCursor(slotCurrent); - slotCurrent = null; - - for (var slot = slotsStart.next; slot !== slotsEnd;) { - var slotNext = slot.next; - - var fetchListeners = slot.fetchListeners; - for (var listenerID in fetchListeners) { - var listener = fetchListeners[listenerID]; - if (listener.listBindingID === listBindingID) { - listener.promise.cancel(); - delete fetchListeners[listenerID]; - } - } - - if (slot.bindingMap && slot.bindingMap[listBindingID]) { - releaseSlotFromListBinding(slot); - } - - slot = slotNext; - } - - delete bindingMap[listBindingID]; - } - }; - - // Only implement each navigation method if the data adapter implements certain methods - - if (itemsFromStart || itemsFromIndex) { - listBinding.first = function () { - /// - /// - /// Retrieves the first item in the list and makes it the current item. - /// - /// - /// An IItemPromise that serves as a promise for the requested item. - /// If the list is empty, the Promise completes with a value of null. - /// - /// - - return itemPromiseFromSlot(requestSlotAfter(slotsStart)); - }; - } - - if (itemsFromEnd) { - listBinding.last = function () { - /// - /// - /// Retrieves the last item in the list and makes it the current item. - /// - /// - /// An IItemPromise that serves as a promise for the requested item. - /// If the list is empty, the Promise completes with a value of null. - /// - /// - - return itemPromiseFromSlot(requestSlotBefore(slotListEnd)); - }; - } - - if (itemsFromKey) { - listBinding.fromKey = function (key, hints) { - /// - /// - /// Retrieves the item with the specified key and makes it the current item. - /// - /// - /// The key of the requested item. It must be a non-empty string. - /// - /// - /// Domain-specific hints to the IListDataAdapter - /// about the location of the item to improve retrieval time. - /// - /// - /// An IItemPromise that serves as a promise for the requested item. - /// If the list doesn't contain an item with the specified key, the Promise completes with a value of null. - /// - /// - - return itemPromiseFromSlot(slotFromKey(key, hints)); - }; - } - - if (itemsFromIndex || (itemsFromStart && itemsFromKey)) { - listBinding.fromIndex = function (index) { - /// - /// - /// Retrieves the item with the specified index and makes it the current item. - /// - /// - /// A value greater than or equal to 0 that is the index of the item to retrieve. - /// - /// - /// An IItemPromise that serves as a promise for the requested item. - /// If the list doesn't contain an item with the specified index, the IItemPromise completes with a value of null. - /// - /// - - return itemPromiseFromSlot(slotFromIndex(index)); - }; - } - - if (itemsFromDescription) { - listBinding.fromDescription = function (description) { - /// - /// - /// Retrieves the item with the specified description and makes it the current item. - /// - /// - /// The domain-specific description of the requested item, to be interpreted by the list data adapter. - /// - /// - /// A Promise for the requested item. If the list doesn't contain an item with the specified description, - /// the IItemPromise completes with a value of null. - /// - /// - - return itemPromiseFromSlot(slotFromDescription(description)); - }; - } - - return listBinding; - }; - - this.invalidateAll = function () { - /// - /// - /// Makes the data source refresh its cached items by re-requesting them from the data adapter. - /// The data source generates notifications if the data has changed. - /// - /// - /// A Promise that completes when the data has been completely refreshed and all change notifications have been - /// sent. - /// - /// - - return requestRefresh(); - }; - - // Create a helper which issues new promises for the result of the input promise - // but have their cancelations ref-counted so that any given consumer canceling - // their promise doesn't result in the incoming promise being canceled unless - // all consumers are no longer interested in the result. - // - var countedCancelation = function (incomingPromise, dataSource) { - var signal = new WinJS._Signal(); - incomingPromise.then( - function (v) { signal.complete(v); }, - function (e) { signal.error(e); } - ); - var resultPromise = signal.promise.then(null, function (e) { - if (e.name === "WinJS.UI.VirtualizedDataSource.resetCount") { - getCountPromise = null; - return incomingPromise = dataSource.getCount(); - } - return Promise.wrapError(e); - }); - var count = 0; - var currentGetCountPromise = { - get: function () { - count++; - return new Promise( - function (c, e) { resultPromise.then(c, e); }, - function () { - if (--count === 0) { - // when the count reaches zero cancel the incoming promise - signal.promise.cancel() - incomingPromise.cancel(); - if (currentGetCountPromise === getCountPromise) { - getCountPromise = null; - } - } - } - ); - }, - reset: function () { - signal.error(new WinJS.ErrorFromName("WinJS.UI.VirtualizedDataSource.resetCount")); - }, - cancel: function () { - // if explicitly asked to cancel the incoming promise - signal.promise.cancel() - incomingPromise.cancel(); - if (currentGetCountPromise === getCountPromise) { - getCountPromise = null; - } - } - }; - return currentGetCountPromise; - } - - this.getCount = function () { - /// - /// - /// Retrieves the number of items in the data source. - /// - /// - - if (listDataAdapter.getCount) { - // Always do a fetch, even if there is a cached result - // - var that = this; - return Promise.wrap().then(function () { - if (editsInProgress || editsQueued) { - return knownCount; - } - - var requestPromise; - - if (!getCountPromise) { - - var relatedGetCountPromise; - - // Make a request for the count - // - requestPromise = listDataAdapter.getCount(); - var synchronous; - requestPromise.then( - function () { - if (getCountPromise === relatedGetCountPromise) { - getCountPromise = null; - } - synchronous = true; - }, - function () { - if (getCountPromise === relatedGetCountPromise) { - getCountPromise = null; - } - synchronous = true; - } - ); - - // Every time we make a new request for the count we can consider the - // countDelta to be invalidated - // - countDelta = 0; - - // Wrap the result in a cancelation counter which will block cancelation - // of the outstanding promise unless all consumers cancel. - // - if (!synchronous) { - relatedGetCountPromise = getCountPromise = countedCancelation(requestPromise, that); - } - } - - return getCountPromise ? getCountPromise.get() : requestPromise; - - }).then(function (count) { - if (!isNonNegativeInteger(count) && count !== undefined) { - throw new WinJS.ErrorFromName("WinJS.UI.ListDataSource.InvalidRequestedCountReturned", strings.invalidRequestedCountReturned); - } - - if (count !== knownCount) { - if (knownCount === CountResult.unknown) { - knownCount = count; - } else { - changeCount(count); - finishNotifications(); - } - } - - if (count === 0) { - if (slotsStart.next !== slotListEnd || slotListEnd.next !== slotsEnd) { - // A contradiction has been found - beginRefresh(); - } else if (slotsStart.lastInSequence) { - // Now we know the list is empty - mergeSequences(slotsStart); - slotListEnd.index = 0; - } - } - - return count; - }).then(null, function (error) { - if (error.name === UI.CountError.noResponse) { - // Report the failure, but still report last known count - setStatus(DataSourceStatus.failure); - return knownCount; - } - return WinJS.Promise.wrapError(error); - }); - } else { - // If the data adapter doesn't support the count method, return the VirtualizedDataSource's - // reckoning of the count. - return Promise.wrap(knownCount); - } - }; - - if (itemsFromKey) { - this.itemFromKey = function (key, hints) { - /// - /// - /// Retrieves the item with the specified key. - /// - /// - /// The key of the requested item. It must be a non-empty string. - /// - /// - /// Domain-specific hints to IListDataAdapter about the location of the item - /// to improve the retrieval time. - /// - /// - /// A Promise for the requested item. If the list doesn't contain an item with the specified key, - /// the Promise completes with a value of null. - /// - /// - - return itemDirectlyFromSlot(slotFromKey(key, hints)); - }; - } - - if (itemsFromIndex || (itemsFromStart && itemsFromKey)) { - this.itemFromIndex = function (index) { - /// - /// - /// Retrieves the item at the specified index. - /// - /// - /// A value greater than or equal to zero that is the index of the requested item. - /// - /// - /// A Promise for the requested item. If the list doesn't contain an item with the specified index, - /// the Promise completes with a value of null. - /// - /// - - return itemDirectlyFromSlot(slotFromIndex(index)); - }; - } - - if (itemsFromDescription) { - this.itemFromDescription = function (description) { - /// - /// - /// Retrieves the item with the specified description. - /// - /// - /// Domain-specific info that describes the item to retrieve, to be interpreted by the IListDataAdapter, - /// - /// - /// A Promise for the requested item. If the list doesn't contain an item with the specified description, - /// the Promise completes with a value of null. - /// - /// - - return itemDirectlyFromSlot(slotFromDescription(description)); - }; - } - - this.beginEdits = function () { - /// - /// - /// Notifies the data source that a sequence of edits is about to begin. The data source calls - /// IListNotificationHandler.beginNotifications and endNotifications each one time for a sequence of edits. - /// - /// - - editsInProgress = true; - }; - - // Only implement each editing method if the data adapter implements the corresponding ListDataAdapter method - - if (listDataAdapter.insertAtStart) { - this.insertAtStart = function (key, data) { - /// - /// - /// Adds an item to the beginning of the data source. - /// - /// - /// The key of the item to insert, if known; otherwise, null. - /// - /// - /// The data for the item to add. - /// - /// - /// A Promise that contains the IItem that was added or an EditError if an error occurred. - /// - /// - - // Add item to start of list, only notify if the first item was requested - return insertItem( - key, data, - - // slotInsertBefore, append - (slotsStart.lastInSequence ? null : slotsStart.next), true, - - // applyEdit - function () { - return listDataAdapter.insertAtStart(key, data); - } - ); - }; - } - - if (listDataAdapter.insertBefore) { - this.insertBefore = function (key, data, nextKey) { - /// - /// - /// Inserts an item before another item. - /// - /// - /// The key of the item to insert, if known; otherwise, null. - /// - /// - /// The data for the item to insert. - /// - /// - /// The key of an item in the data source. The new data is inserted before this item. - /// - /// - /// A Promise that contains the IItem that was added or an EditError if an error occurred. - /// - /// - - var slotNext = getSlotForEdit(nextKey); - - // Add item before given item and send notification - return insertItem( - key, data, - - // slotInsertBefore, append - slotNext, false, - - // applyEdit - function () { - return listDataAdapter.insertBefore(key, data, nextKey, adjustedIndex(slotNext)); - } - ); - }; - } - - if (listDataAdapter.insertAfter) { - this.insertAfter = function (key, data, previousKey) { - /// - /// - /// Inserts an item after another item. - /// - /// - /// The key of the item to insert, if known; otherwise, null. - /// - /// - /// The data for the item to insert. - /// - /// - /// The key for an item in the data source. The new item is added after this item. - /// - /// - /// A Promise that contains the IItem that was added or an EditError if an error occurred. - /// - /// - - var slotPrev = getSlotForEdit(previousKey); - - // Add item after given item and send notification - return insertItem( - key, data, - - // slotInsertBefore, append - (slotPrev ? slotPrev.next : null), true, - - // applyEdit - function () { - return listDataAdapter.insertAfter(key, data, previousKey, adjustedIndex(slotPrev)); - } - ); - }; - } - - if (listDataAdapter.insertAtEnd) { - this.insertAtEnd = function (key, data) { - /// - /// - /// Adds an item to the end of the data source. - /// - /// - /// The key of the item to insert, if known; otherwise, null. - /// - /// - /// The data for the item to insert. - /// - /// - /// A Promise that contains the IItem that was added or an EditError if an error occurred. - /// - /// - - // Add item to end of list, only notify if the last item was requested - return insertItem( - key, data, - - // slotInsertBefore, append - (slotListEnd.firstInSequence ? null : slotListEnd), false, - - // applyEdit - function () { - return listDataAdapter.insertAtEnd(key, data); - } - ); - }; - } - - if (listDataAdapter.change) { - this.change = function (key, newData) { - /// - /// - /// Overwrites the data of the specified item. - /// - /// - /// The key for the item to replace. - /// - /// - /// The new data for the item. - /// - /// - /// A Promise that contains the IItem that was updated or an EditError if an error occurred. - /// - /// - - var slot = getSlotForEdit(key); - - return new Promise(function (complete, error) { - var itemOld; - - queueEdit( - // applyEdit - function () { - return listDataAdapter.change(key, newData, adjustedIndex(slot)); - }, - - EditType.change, complete, error, - - // keyUpdate - null, - - // updateSlots - function () { - itemOld = slot.item; - - slot.itemNew = { - key: key, - data: newData - }; - - if (itemOld) { - changeSlot(slot); - } else { - completeFetchPromises(slot); - } - }, - - // undo - function () { - if (itemOld) { - slot.itemNew = itemOld; - changeSlot(slot); - } else { - beginRefresh(); - } - } - ); - }); - }; - } - - if (listDataAdapter.moveToStart) { - this.moveToStart = function (key) { - /// - /// - /// Moves the specified item to the beginning of the data source. - /// - /// - /// The key of the item to move. - /// - /// - /// A Promise that contains the IItem that was moved or an EditError if an error occurred. - /// - /// - - var slot = getSlotForEdit(key); - - return moveItem( - slot, - - // slotMoveBefore, append - slotsStart.next, true, - - // applyEdit - function () { - return listDataAdapter.moveToStart(key, adjustedIndex(slot)); - } - ); - }; - } - - if (listDataAdapter.moveBefore) { - this.moveBefore = function (key, nextKey) { - /// - /// - /// Moves the specified item before another item. - /// - /// - /// The key of the item to move. - /// - /// - /// The key of another item in the data source. The item specified by the key parameter - /// is moved to a position immediately before this item. - /// - /// - /// A Promise that contains the IItem that was moved or an EditError if an error occurred. - /// - /// - - var slot = getSlotForEdit(key), - slotNext = getSlotForEdit(nextKey); - - return moveItem( - slot, - - // slotMoveBefore, append - slotNext, false, - - // applyEdit - function () { - return listDataAdapter.moveBefore(key, nextKey, adjustedIndex(slot), adjustedIndex(slotNext)); - } - ); - }; - } - - if (listDataAdapter.moveAfter) { - this.moveAfter = function (key, previousKey) { - /// - /// - /// Moves an item after another item. - /// - /// - /// The key of the item to move. - /// - /// - /// The key of another item in the data source. The item specified by the key parameter will - /// is moved to a position immediately after this item. - /// - /// - /// A Promise that contains the IItem that was moved or an EditError if an error occurred. - /// - /// - - var slot = getSlotForEdit(key), - slotPrev = getSlotForEdit(previousKey); - - return moveItem( - slot, - - // slotMoveBefore, append - slotPrev.next, true, - - // applyEdit - function () { - return listDataAdapter.moveAfter(key, previousKey, adjustedIndex(slot), adjustedIndex(slotPrev)); - } - ); - }; - } - - if (listDataAdapter.moveToEnd) { - this.moveToEnd = function (key) { - /// - /// - /// Moves an item to the end of the data source. - /// - /// - /// The key of the item to move. - /// - /// - /// A Promise that contains the IItem that was moved or an EditError if an error occurred. - /// - /// - - var slot = getSlotForEdit(key); - - return moveItem( - slot, - - // slotMoveBefore, append - slotListEnd, false, - - // applyEdit - function () { - return listDataAdapter.moveToEnd(key, adjustedIndex(slot)); - } - ); - }; - } - - if (listDataAdapter.remove) { - this.remove = function (key) { - /// - /// - /// Removes an item from the data source. - /// - /// - /// The key of the item to remove. - /// - /// - /// A Promise that contains nothing if the operation was successful or an EditError if an error occurred. - /// - /// - - validateKey(key); - - var slot = keyMap[key]; - - return new Promise(function (complete, error) { - var slotNext, - firstInSequence, - lastInSequence; - - queueEdit( - // applyEdit - function () { - return listDataAdapter.remove(key, adjustedIndex(slot)); - }, - - EditType.remove, complete, error, - - // keyUpdate - null, - - // updateSlots - function () { - if (slot) { - slotNext = slot.next; - firstInSequence = slot.firstInSequence; - lastInSequence = slot.lastInSequence; - - updateNewIndices(slot, -1); - deleteSlot(slot, false); - } - }, - - // undo - function () { - if (slot) { - reinsertSlot(slot, slotNext, !firstInSequence, !lastInSequence); - updateNewIndices(slot, 1); - sendInsertedNotification(slot); - } - } - ); - }); - }; - } - - this.endEdits = function () { - /// - /// - /// Notifies the data source that a sequence of edits has ended. The data source will call - /// IListNotificationHandler.beginNotifications and endNotifications once each for a sequence of edits. - /// - /// - - editsInProgress = false; - completeEdits(); - }; - - } // _baseDataSourceConstructor - - var VDS = WinJS.Class.define(function () { - /// - /// - /// Use as a base class when defining a custom data source. Do not instantiate directly. - /// - /// - /// Raised when the status of the VirtualizedDataSource changes between ready, waiting, and failure states. - /// - /// - }, { - _baseDataSourceConstructor: _baseDataSourceConstructor - }, { // Static Members - supportedForProcessing: false, - }); - WinJS.Class.mix(VDS, WinJS.Utilities.eventMixin); - return VDS; - }), - - }); - - var DataSourceStatus = WinJS.UI.DataSourceStatus, - CountResult = WinJS.UI.CountResult, - FetchError = WinJS.UI.FetchError, - EditError = WinJS.UI.EditError; - -})(); - - -// Group Data Source - -(function groupDataSourceInit() { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - - _GroupDataSource: WinJS.Namespace._lazy(function () { - var UI = WinJS.UI; - var Promise = WinJS.Promise, - Scheduler = WinJS.Utilities.Scheduler; - - // Private statics - - function errorDoesNotExist() { - return new WinJS.ErrorFromName(UI.FetchError.doesNotExist); - } - - var batchSizeDefault = 101; - - function groupReady(group) { - return group && group.firstReached && group.lastReached; - } - - var ListNotificationHandler = WinJS.Class.define(function ListNotificationHandler_ctor(groupDataAdapter) { - // Constructor - - this._groupDataAdapter = groupDataAdapter; - }, { - // Public methods - - beginNotifications: function () { - }, - - // itemAvailable: not implemented - - inserted: function (itemPromise, previousHandle, nextHandle) { - this._groupDataAdapter._inserted(itemPromise, previousHandle, nextHandle); - }, - - changed: function (newItem, oldItem) { - this._groupDataAdapter._changed(newItem, oldItem); - }, - - moved: function (itemPromise, previousHandle, nextHandle) { - this._groupDataAdapter._moved(itemPromise, previousHandle, nextHandle); - }, - - removed: function (handle, mirage) { - this._groupDataAdapter._removed(handle, mirage); - }, - - countChanged: function (newCount, oldCount) { - if (newCount === 0 && oldCount !== 0) { - this._groupDataAdapter.invalidateGroups(); - } - }, - - indexChanged: function (handle, newIndex, oldIndex) { - this._groupDataAdapter._indexChanged(handle, newIndex, oldIndex); - }, - - endNotifications: function () { - this._groupDataAdapter._endNotifications(); - }, - - reload: function () { - this._groupDataAdapter._reload(); - } - }, { - supportedForProcessing: false, - }); - - var GroupDataAdapter = WinJS.Class.define(function GroupDataAdapater_ctor(listDataSource, groupKey, groupData, options) { - // Constructor - - this._listBinding = listDataSource.createListBinding(new ListNotificationHandler(this)); - - this._groupKey = groupKey; - this._groupData = groupData; - - // _initializeState clears the count, so call this before processing the groupCountEstimate option - this._initializeState(); - - this._batchSize = batchSizeDefault; - this._count = null; - - if (options) { - if (typeof options.groupCountEstimate === "number") { - this._count = (options.groupCountEstimate < 0 ? null : Math.max(options.groupCountEstimate, 1)); - } - if (typeof options.batchSize === "number") { - this._batchSize = options.batchSize + 1; - } - } - - if (this._listBinding.last) { - this.itemsFromEnd = function (count) { - var that = this; - return this._fetchItems( - // getGroup - function () { - return that._lastGroup; - }, - - // mayExist - function (failed) { - if (failed) { - return false; - } - var count = that._count; - if (+count !== count) { - return true; - } - if (count > 0) { - return true; - } - }, - - // fetchInitialBatch - function () { - that._fetchBatch(that._listBinding.last(), that._batchSize - 1, 0); - }, - - count - 1, 0 - ); - }; - } - }, { - // Public members - - setNotificationHandler: function (notificationHandler) { - this._listDataNotificationHandler = notificationHandler; - }, - - // The ListDataSource should always compare these items by identity; in rare cases, it will do some unnecessary - // rerendering, but at least fetching will not stringify items we already know to be valid and that we know - // have not changed. - compareByIdentity: true, - - // itemsFromStart: not implemented - - // itemsFromEnd: implemented in constructor - - itemsFromKey: function (key, countBefore, countAfter, hints) { - var that = this; - return this._fetchItems( - // getGroup - function () { - return that._keyMap[key]; - }, - - // mayExist - function (failed) { - var lastGroup = that._lastGroup; - if (!lastGroup) { - return true; - } - if (+lastGroup.index !== lastGroup.index) { - return true; - } - }, - - // fetchInitialBatch - function () { - hints = hints || {}; - var itemPromise = ( - typeof hints.groupMemberKey === "string" && that._listBinding.fromKey ? - that._listBinding.fromKey(hints.groupMemberKey) : - typeof hints.groupMemberIndex === "number" && that._listBinding.fromIndex ? - that._listBinding.fromIndex(hints.groupMemberIndex) : - hints.groupMemberDescription !== undefined && that._listBinding.fromDescription ? - that._listBinding.fromDescription(hints.groupMemberDescription) : - that._listBinding.first() - ); - - var fetchBefore = Math.floor(0.5 * (that._batchSize - 1)); - that._fetchBatch(itemPromise, fetchBefore, that._batchSize - 1 - fetchBefore); - }, - - countBefore, countAfter - ); - }, - - itemsFromIndex: function (index, countBefore, countAfter) { - var that = this; - return this._fetchItems( - // getGroup - function () { - return that._indexMap[index]; - }, - - // mayExist - function (failed) { - var lastGroup = that._lastGroup; - if (!lastGroup) { - return true; - } - if (+lastGroup.index !== lastGroup.index) { - return true; - } - if (index <= lastGroup.index) { - return true; - } - }, - - // fetchInitialBatch - function () { - that._fetchNextIndex(); - }, - - countBefore, countAfter - ); - }, - - // itemsFromDescription: not implemented - - getCount: function () { - if (this._lastGroup && typeof this._lastGroup.index === "number") { - //#DBG _ASSERT(this._count === this._lastGroup.index); - - return Promise.wrap(this._count); - } else { - // Even if there's a current estimate for _count, consider this call to be a request to determine the true - // count. - - var that = this; - var countPromise = new Promise(function (complete) { - var fetch = { - initialBatch: function () { - that._fetchNextIndex(); - }, - getGroup: function () { return null; }, - countBefore: 0, - countAfter: 0, - complete: function (failed) { - if (failed) { - that._count = 0; - } - - var count = that._count; - if (typeof count === "number") { - complete(count); - return true; - } else { - return false; - } - } - }; - - that._fetchQueue.push(fetch); - - if (!that._itemBatch) { - //#DBG _ASSERT(that._fetchQueue[0] === fetch); - that._continueFetch(fetch); - } - }); - - return (typeof this._count === "number" ? Promise.wrap(this._count) : countPromise); - } - }, - - invalidateGroups: function () { - this._beginRefresh(); - this._initializeState(); - }, - - // Editing methods not implemented - - // Private members - - _initializeState: function () { - this._count = null; - this._indexMax = null; - - this._keyMap = {}; - this._indexMap = {}; - this._lastGroup = null; - this._handleMap = {}; - - this._fetchQueue = []; - - this._itemBatch = null; - this._itemsToFetch = 0; - - this._indicesChanged = false; - }, - - _releaseItem: function (item) { - delete this._handleMap[item.handle]; - this._listBinding.releaseItem(item); - }, - - _processBatch: function () { - var previousItem = null, - previousGroup = null, - firstItemInGroup = null, - itemsSinceStart = 0, - failed = true; - for (var i = 0; i < this._batchSize; i++) { - var item = this._itemBatch[i], - groupKey = (item ? this._groupKey(item) : null); - - if (item) { - failed = false; - } - - if (previousGroup && groupKey !== null && groupKey === previousGroup.key) { - // This item is in the same group as the last item. The only thing to do is advance the group's - // lastItem if this is definitely the last item that has been processed for the group. - itemsSinceStart++; - if (previousGroup.lastItem === previousItem) { - if (previousGroup.lastItem.handle !== previousGroup.firstItem.handle) { - this._releaseItem(previousGroup.lastItem); - } - previousGroup.lastItem = item; - this._handleMap[item.handle] = previousGroup; - - previousGroup.size++; - } else if (previousGroup.firstItem === item) { - if (previousGroup.firstItem.handle !== previousGroup.lastItem.handle) { - this._releaseItem(previousGroup.firstItem); - } - previousGroup.firstItem = firstItemInGroup; - this._handleMap[firstItemInGroup.handle] = previousGroup; - - previousGroup.size += itemsSinceStart; - } - } else { - var index = null; - - if (previousGroup) { - previousGroup.lastReached = true; - - if (typeof previousGroup.index === "number") { - index = previousGroup.index + 1; - } - } - - if (item) { - // See if the current group has already been processed - var group = this._keyMap[groupKey]; - - if (!group) { - group = { - key: groupKey, - data: this._groupData(item), - firstItem: item, - lastItem: item, - size: 1 - }; - this._keyMap[group.key] = group; - this._handleMap[item.handle] = group; - } - - if (i > 0) { - group.firstReached = true; - - if (!previousGroup) { - index = 0; - } - } - - if (typeof group.index !== "number" && typeof index === "number") { - // Set the indices of as many groups as possible - for (var group2 = group; group2; group2 = this._nextGroup(group2)) { - //#DBG _ASSERT(typeof this._indexMap[index] !== "number"); - group2.index = index; - this._indexMap[index] = group2; - - index++; - } - - this._indexMax = index; - if (typeof this._count === "number" && !this._lastGroup && this._count <= this._indexMax) { - this._count = this._indexMax + 1; - } - } - - firstItemInGroup = item; - itemsSinceStart = 0; - - previousGroup = group; - } else { - if (previousGroup) { - this._lastGroup = previousGroup; - - if (typeof previousGroup.index === "number") { - this._count = (previousGroup.index + 1); - } - - // Force a client refresh (which should be fast) to ensure that a countChanged notification is - // sent. - this._listDataNotificationHandler.invalidateAll(); - - previousGroup = null; - } - } - } - - previousItem = item; - } - - // See how many fetches have now completed - var fetch; - for (fetch = this._fetchQueue[0]; fetch && fetch.complete(failed) ; fetch = this._fetchQueue[0]) { - this._fetchQueue.splice(0, 1); - } - - // Continue work on the next fetch, if any - if (fetch) { - var that = this; - // Avoid reentering _processBatch - Scheduler.schedule(function () { - that._continueFetch(fetch); - }, Scheduler.Priority.normal, null, "WinJS.UI._GroupDataSource._continueFetch"); - } else { - this._itemBatch = null; - } - }, - - _processPromise: function (itemPromise, batchIndex) { - itemPromise.retain(); - - this._itemBatch[batchIndex] = itemPromise; - - var that = this; - itemPromise.then(function (item) { - that._itemBatch[batchIndex] = item; - if (--that._itemsToFetch === 0) { - that._processBatch(); - } - }); - }, - - _fetchBatch: function (itemPromise, countBefore, countAfter) { - //#DBG _ASSERT(countBefore + 1 + countAfter === this._batchSize); - this._itemBatch = new Array(this._batchSize); - this._itemsToFetch = this._batchSize; - - this._processPromise(itemPromise, countBefore); - - var batchIndex; - - this._listBinding.jumpToItem(itemPromise); - for (batchIndex = countBefore - 1; batchIndex >= 0; batchIndex--) { - this._processPromise(this._listBinding.previous(), batchIndex); - } - - this._listBinding.jumpToItem(itemPromise); - for (batchIndex = countBefore + 1; batchIndex < this._batchSize; batchIndex++) { - this._processPromise(this._listBinding.next(), batchIndex); - } - }, - - _fetchAdjacent: function (item, after) { - // Batches overlap by one so group boundaries always fall within at least one batch - this._fetchBatch( - (this._listBinding.fromKey ? this._listBinding.fromKey(item.key) : this._listBinding.fromIndex(item.index)), - (after ? 0 : this._batchSize - 1), - (after ? this._batchSize - 1 : 0) - ); - }, - - _fetchNextIndex: function () { - var groupHighestIndex = this._indexMap[this._indexMax - 1]; - if (groupHighestIndex) { - // We've already fetched some of the first items, so continue where we left off - //#DBG _ASSERT(groupHighestIndex.firstReached); - this._fetchAdjacent(groupHighestIndex.lastItem, true); - } else { - // Fetch one non-existent item before the list so _processBatch knows the start was reached - this._fetchBatch(this._listBinding.first(), 1, this._batchSize - 2); - } - }, - - _continueFetch: function (fetch) { - if (fetch.initialBatch) { - fetch.initialBatch(); - fetch.initialBatch = null; - } else { - var group = fetch.getGroup(); - if (group) { - var groupPrev, - groupNext; - - if (!group.firstReached) { - this._fetchAdjacent(group.firstItem, false); - } else if (!group.lastReached) { - this._fetchAdjacent(group.lastItem, true); - } else if (fetch.countBefore > 0 && group.index !== 0 && !groupReady(groupPrev = this._previousGroup(group))) { - this._fetchAdjacent((groupPrev && groupPrev.lastReached ? groupPrev.firstItem : group.firstItem), false); - } else { - groupNext = this._nextGroup(group); - //#DBG _ASSERT(fetch.countAfter > 0 && !groupReady(groupNext)); - this._fetchAdjacent((groupNext && groupNext.firstReached ? groupNext.lastItem : group.lastItem), true); - } - } else { - // Assume we're searching for a key, index or the count by brute force - this._fetchNextIndex(); - } - } - }, - - _fetchComplete: function (group, countBefore, countAfter, firstRequest, complete, error) { - if (groupReady(group)) { - // Check if the minimal requirements for the request are met - var groupPrev = this._previousGroup(group); - if (firstRequest || groupReady(groupPrev) || group.index === 0 || countBefore === 0) { - var groupNext = this._nextGroup(group); - if (firstRequest || groupReady(groupNext) || this._lastGroup === group || countAfter === 0) { - // Time to return the fetch results - - // Find the first available group to return (don't return more than asked for) - var countAvailableBefore = 0, - groupFirst = group; - while (countAvailableBefore < countBefore) { - groupPrev = this._previousGroup(groupFirst); - - if (!groupReady(groupPrev)) { - break; - } - - groupFirst = groupPrev; - countAvailableBefore++; - } - - // Find the last available group to return - var countAvailableAfter = 0, - groupLast = group; - while (countAvailableAfter < countAfter) { - groupNext = this._nextGroup(groupLast); - - if (!groupReady(groupNext)) { - break; - } - - groupLast = groupNext; - countAvailableAfter++; - } - - // Now create the items to return - var len = countAvailableBefore + 1 + countAvailableAfter, - items = new Array(len); - - for (var i = 0; i < len; i++) { - var item = { - key: groupFirst.key, - data: groupFirst.data, - firstItemKey: groupFirst.firstItem.key, - groupSize: groupFirst.size - }; - - var firstItemIndex = groupFirst.firstItem.index; - if (typeof firstItemIndex === "number") { - item.firstItemIndexHint = firstItemIndex; - } - - items[i] = item; - - groupFirst = this._nextGroup(groupFirst); - } - - var result = { - items: items, - offset: countAvailableBefore - }; - - result.totalCount = ( - typeof this._count === "number" ? - this._count : - UI.CountResult.unknown - ); - - if (typeof group.index === "number") { - result.absoluteIndex = group.index; - } - - if (groupLast === this._lastGroup) { - result.atEnd = true; - } - - complete(result); - return true; - } - } - } - - return false; - }, - - _fetchItems: function (getGroup, mayExist, fetchInitialBatch, countBefore, countAfter) { - var that = this; - return new Promise(function (complete, error) { - var group = getGroup(), - firstRequest = !group, - failureCount = 0; - - function fetchComplete(failed) { - var group2 = getGroup(); - - if (group2) { - return that._fetchComplete(group2, countBefore, countAfter, firstRequest, complete, error); - } else if (firstRequest && !mayExist(failed)) { - error(errorDoesNotExist()); - return true; - } else if (failureCount > 2) { - error(errorDoesNotExist()); - return true; - } else { - // only consider consecutive failures - if (failed) { - failureCount++; - } else { - failureCount = 0; - } - // _continueFetch will switch to a brute force search - return false; - } - } - - if (!fetchComplete()) { - var fetch = { - initialBatch: firstRequest ? fetchInitialBatch : null, - getGroup: getGroup, - countBefore: countBefore, - countAfter: countAfter, - complete: fetchComplete - }; - - that._fetchQueue.push(fetch); - - if (!that._itemBatch) { - //#DBG _ASSERT(that._fetchQueue[0] === fetch); - that._continueFetch(fetch); - } - } - }); - }, - - _previousGroup: function (group) { - if (group && group.firstReached) { - this._listBinding.jumpToItem(group.firstItem); - - return this._handleMap[this._listBinding.previous().handle]; - } else { - return null; - } - }, - - _nextGroup: function (group) { - if (group && group.lastReached) { - this._listBinding.jumpToItem(group.lastItem); - - return this._handleMap[this._listBinding.next().handle]; - } else { - return null; - } - }, - - _invalidateIndices: function (group) { - this._count = null; - this._lastGroup = null; - - if (typeof group.index === "number") { - this._indexMax = (group.index > 0 ? group.index : null); - } - - // Delete the indices of this and all subsequent groups - for (var group2 = group; group2 && typeof group2.index === "number"; group2 = this._nextGroup(group2)) { - delete this._indexMap[group2.index]; - group2.index = null; - } - }, - - _releaseGroup: function (group) { - this._invalidateIndices(group); - - delete this._keyMap[group.key]; - - if (this._lastGroup === group) { - this._lastGroup = null; - } - - if (group.firstItem !== group.lastItem) { - this._releaseItem(group.firstItem); - } - this._releaseItem(group.lastItem); - }, - - _beginRefresh: function () { - // Abandon all current fetches - - this._fetchQueue = []; - - if (this._itemBatch) { - for (var i = 0; i < this._batchSize; i++) { - var item = this._itemBatch[i]; - if (item) { - if (item.cancel) { - item.cancel(); - } - this._listBinding.releaseItem(item); - } - } - - this._itemBatch = null; - } - - this._itemsToFetch = 0; - - this._listDataNotificationHandler.invalidateAll(); - }, - - _processInsertion: function (item, previousHandle, nextHandle) { - var groupPrev = this._handleMap[previousHandle], - groupNext = this._handleMap[nextHandle], - groupKey = null; - - if (groupPrev) { - // If an item in a different group from groupPrev is being inserted after it, no need to discard groupPrev - if (!groupPrev.lastReached || previousHandle !== groupPrev.lastItem.handle || (groupKey = this._groupKey(item)) === groupPrev.key) { - this._releaseGroup(groupPrev); - } else if (this._lastGroup === groupPrev) { - this._lastGroup = null; - this._count = null; - } - this._beginRefresh(); - } - - if (groupNext && groupNext !== groupPrev) { - this._invalidateIndices(groupNext); - - // If an item in a different group from groupNext is being inserted before it, no need to discard groupNext - if (!groupNext.firstReached || nextHandle !== groupNext.firstItem.handle || (groupKey !== null ? groupKey : this._groupKey(item)) === groupNext.key) { - this._releaseGroup(groupNext); - } - this._beginRefresh(); - } - }, - - _processRemoval: function (handle) { - var group = this._handleMap[handle]; - - if (group && (handle === group.firstItem.handle || handle === group.lastItem.handle)) { - this._releaseGroup(group); - this._beginRefresh(); - } else if (this._itemBatch) { - for (var i = 0; i < this._batchSize; i++) { - var item = this._itemBatch[i]; - if (item && item.handle === handle) { - this._beginRefresh(); - break; - } - } - } - }, - - _inserted: function (itemPromise, previousHandle, nextHandle) { - var that = this; - itemPromise.then(function (item) { - that._processInsertion(item, previousHandle, nextHandle); - }); - }, - - _changed: function (newItem, oldItem) { - // A change to the first item could affect the group item - var group = this._handleMap[newItem.handle]; - if (group && newItem.handle === group.firstItem.handle) { - this._releaseGroup(group); - this._beginRefresh(); - } - - // If the item is now in a different group, treat this as a move - if (this._groupKey(newItem) !== this._groupKey(oldItem)) { - this._listBinding.jumpToItem(newItem); - var previousHandle = this._listBinding.previous().handle; - this._listBinding.jumpToItem(newItem); - var nextHandle = this._listBinding.next().handle; - - this._processRemoval(newItem.handle); - this._processInsertion(newItem, previousHandle, nextHandle); - } - }, - - _moved: function (itemPromise, previousHandle, nextHandle) { - this._processRemoval(itemPromise.handle); - - var that = this; - itemPromise.then(function (item) { - that._processInsertion(item, previousHandle, nextHandle); - }); - }, - - _removed: function (handle, mirage) { - // Mirage removals will just result in null items, which can be ignored - if (!mirage) { - this._processRemoval(handle); - } - }, - - _indexChanged: function (handle, newIndex, oldIndex) { - if (typeof oldIndex === "number") { - this._indicesChanged = true; - } - }, - - _endNotifications: function () { - if (this._indicesChanged) { - this._indicesChanged = false; - - // Update the group sizes - for (var key in this._keyMap) { - var group = this._keyMap[key]; - - if (group.firstReached && group.lastReached) { - var newSize = group.lastItem.index + 1 - group.firstItem.index; - if (!isNaN(newSize)) { - group.size = newSize; - } - } - } - - // Invalidate the client, since some firstItemIndexHint properties have probably changed - this._beginRefresh(); - } - }, - - _reload: function () { - this._initializeState(); - this._listDataNotificationHandler.reload(); - } - }, { - supportedForProcessing: false, - }); - - return WinJS.Class.derive(UI.VirtualizedDataSource, function (listDataSource, groupKey, groupData, options) { - var groupDataAdapter = new GroupDataAdapter(listDataSource, groupKey, groupData, options); - - this._baseDataSourceConstructor(groupDataAdapter); - - this.extensions = { - invalidateGroups: function () { - groupDataAdapter.invalidateGroups(); - } - }; - }, { - /* empty */ - }, { - supportedForProcessing: false, - }); - }) - - }); - -})(); - - -// Grouped Item Data Source - -(function groupedItemDataSourceInit() { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - - computeDataSourceGroups: function (listDataSource, groupKey, groupData, options) { - /// - /// - /// Returns a data source that adds group information to the items of another data source. The "groups" property - /// of this data source evaluates to yet another data source that enumerates the groups themselves. - /// - /// - /// The data source for the individual items to group. - /// - /// - /// A callback function that takes an item in the list as an argument. The function is called - /// for each item in the list and returns the group key for the item as a string. - /// - /// - /// A callback function that takes an item in the IListDataSource as an argument. - /// The function is called on one item in each group and returns - /// an object that represents the header of that group. - /// - /// - /// An object that can contain properties that specify additional options: - /// - /// groupCountEstimate: - /// A Number value that is the initial estimate for the number of groups. If you specify -1, - /// this function returns no result is until the actual number of groups - /// has been determined. - /// - /// batchSize: - /// A Number greater than 0 that specifies the number of items to fetch during each processing pass when - /// searching for groups. (In addition to the number specified, one item from the previous batch - /// is always included.) - /// - /// - /// An IListDataSource that contains the items in the original data source and provides additional - /// group info in a "groups" property. The "groups" property returns another - /// IListDataSource that enumerates the different groups in the list. - /// - /// - - var groupedItemDataSource = Object.create(listDataSource); - - function createGroupedItem(item) { - if (item) { - var groupedItem = Object.create(item); - - groupedItem.groupKey = groupKey(item); - - if (groupData) { - groupedItem.groupData = groupData(item); - } - - return groupedItem; - } else { - return null; - } - } - - function createGroupedItemPromise(itemPromise) { - var groupedItemPromise = Object.create(itemPromise); - - groupedItemPromise.then = function (onComplete, onError, onCancel) { - return itemPromise.then(function (item) { - return onComplete(createGroupedItem(item)); - }, onError, onCancel); - }; - - return groupedItemPromise; - } - - groupedItemDataSource.createListBinding = function (notificationHandler) { - var groupedNotificationHandler; - - if (notificationHandler) { - groupedNotificationHandler = Object.create(notificationHandler); - - groupedNotificationHandler.inserted = function (itemPromise, previousHandle, nextHandle) { - return notificationHandler.inserted(createGroupedItemPromise(itemPromise), previousHandle, nextHandle); - }; - - groupedNotificationHandler.changed = function (newItem, oldItem) { - return notificationHandler.changed(createGroupedItem(newItem), createGroupedItem(oldItem)); - }; - - groupedNotificationHandler.moved = function (itemPromise, previousHandle, nextHandle) { - return notificationHandler.moved(createGroupedItemPromise(itemPromise), previousHandle, nextHandle); - }; - } else { - groupedNotificationHandler = null; - } - - var listBinding = listDataSource.createListBinding(groupedNotificationHandler), - groupedItemListBinding = Object.create(listBinding); - - var listBindingMethods = [ - "first", - "last", - "fromDescription", - "jumpToItem", - "current" - ]; - - for (var i = 0, len = listBindingMethods.length; i < len; i++) { - (function (listBindingMethod) { - if (listBinding[listBindingMethod]) { - groupedItemListBinding[listBindingMethod] = function () { - return createGroupedItemPromise(listBinding[listBindingMethod].apply(listBinding, arguments)); - } - } - })(listBindingMethods[i]); - } - - // The following methods should be fast - - if (listBinding.fromKey) { - groupedItemListBinding.fromKey = function (key) { - return createGroupedItemPromise(listBinding.fromKey(key)); - }; - } - - if (listBinding.fromIndex) { - groupedItemListBinding.fromIndex = function (index) { - return createGroupedItemPromise(listBinding.fromIndex(index)); - }; - } - - groupedItemListBinding.prev = function () { - return createGroupedItemPromise(listBinding.prev()); - }; - - groupedItemListBinding.next = function () { - return createGroupedItemPromise(listBinding.next()); - }; - - return groupedItemListBinding; - }; - - var listDataSourceMethods = [ - "itemFromKey", - "itemFromIndex", - "itemFromDescription", - "insertAtStart", - "insertBefore", - "insertAfter", - "insertAtEnd", - "change", - "moveToStart", - "moveBefore", - "moveAfter", - "moveToEnd" - // remove does not return an itemPromise - ]; - - for (var i = 0, len = listDataSourceMethods.length; i < len; i++) { - (function (listDataSourceMethod) { - if (listDataSource[listDataSourceMethod]) { - groupedItemDataSource[listDataSourceMethod] = function () { - return createGroupedItemPromise(listDataSource[listDataSourceMethod].apply(listDataSource, arguments)); - } - } - })(listDataSourceMethods[i]); - } - - ["addEventListener", "removeEventListener", "dispatchEvent"].forEach(function (methodName) { - if (listDataSource[methodName]) { - groupedItemDataSource[methodName] = function () { - return listDataSource[methodName].apply(listDataSource, arguments); - } - } - }); - - var groupDataSource = null; - - Object.defineProperty(groupedItemDataSource, "groups", { - get: function () { - if (!groupDataSource) { - groupDataSource = new WinJS.UI._GroupDataSource(listDataSource, groupKey, groupData, options); - } - return groupDataSource; - }, - enumerable: true, - configurable: true - }); - - return groupedItemDataSource; - } - - }); - -})(); - - -// Storage Item Data Source - -(function storageDataSourceInit(global) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - StorageDataSource: WinJS.Namespace._lazy(function () { - var StorageDataAdapter = WinJS.Class.define(function StorageDataAdapter_ctor(query, options) { - // Constructor - msWriteProfilerMark("WinJS.UI.StorageDataSource:constructor,StartTM"); - - var mode = Windows.Storage.FileProperties.ThumbnailMode.singleItem, - size = 256, - flags = Windows.Storage.FileProperties.ThumbnailOptions.useCurrentScale, - delayLoad = true, - library; - - if (query === "Pictures") { - mode = Windows.Storage.FileProperties.ThumbnailMode.picturesView; - library = Windows.Storage.KnownFolders.picturesLibrary; - size = 190; - } else if (query === "Music") { - mode = Windows.Storage.FileProperties.ThumbnailMode.musicView; - library = Windows.Storage.KnownFolders.musicLibrary; - size = 256; - } else if (query === "Documents") { - mode = Windows.Storage.FileProperties.ThumbnailMode.documentsView; - library = Windows.Storage.KnownFolders.documentsLibrary; - size = 40; - } else if (query === "Videos") { - mode = Windows.Storage.FileProperties.ThumbnailMode.videosView; - library = Windows.Storage.KnownFolders.videosLibrary; - size = 190; - } - - if (!library) { - this._query = query; - } else { - var queryOptions = new Windows.Storage.Search.QueryOptions; - queryOptions.folderDepth = Windows.Storage.Search.FolderDepth.deep; - queryOptions.indexerOption = Windows.Storage.Search.IndexerOption.useIndexerWhenAvailable; - this._query = library.createFileQueryWithOptions(queryOptions); - } - - if (options) { - if (typeof options.mode === "number") { - mode = options.mode; - } - if (typeof options.requestedThumbnailSize === "number") { - size = Math.max(1, Math.min(options.requestedThumbnailSize, 1024)); - } else { - switch (mode) { - case Windows.Storage.FileProperties.ThumbnailMode.picturesView: - case Windows.Storage.FileProperties.ThumbnailMode.videosView: - size = 190; - break; - case Windows.Storage.FileProperties.ThumbnailMode.documentsView: - case Windows.Storage.FileProperties.ThumbnailMode.listView: - size = 40; - break; - case Windows.Storage.FileProperties.ThumbnailMode.musicView: - case Windows.Storage.FileProperties.ThumbnailMode.singleItem: - size = 256; - break; - } - } - if (typeof options.thumbnailOptions === "number") { - flags = options.thumbnailOptions; - } - if (typeof options.waitForFileLoad === "boolean") { - delayLoad = !options.waitForFileLoad; - } - } - - this._loader = new Windows.Storage.BulkAccess.FileInformationFactory(this._query, mode, size, flags, delayLoad); - this.compareByIdentity = false; - this.firstDataRequest = true; - msWriteProfilerMark("WinJS.UI.StorageDataSource:constructor,StopTM"); - }, { - // Public members - - setNotificationHandler: function (notificationHandler) { - this._notificationHandler = notificationHandler; - this._query.addEventListener("contentschanged", function () { - notificationHandler.invalidateAll(); - }); - this._query.addEventListener("optionschanged", function () { - notificationHandler.invalidateAll(); - }); - }, - - itemsFromEnd: function (count) { - var that = this; - msWriteProfilerMark("WinJS.UI.StorageDataSource:itemsFromEnd,info"); - return this.getCount().then(function (totalCount) { - if (totalCount === 0) { - return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist)); - } - // Intentionally passing countAfter = 1 to go one over the end so that itemsFromIndex will - // report the vector size since its known. - return that.itemsFromIndex(totalCount - 1, Math.min(totalCount - 1, count - 1), 1); - }); - }, - - itemsFromIndex: function (index, countBefore, countAfter) { - // don't allow more than 64 items to be retrieved at once - if (countBefore + countAfter > 64) { - countBefore = Math.min(countBefore, 32); - countAfter = 64 - (countBefore + 1); - } - - var first = (index - countBefore), - count = (countBefore + 1 + countAfter); - var that = this; - // Fetch a minimum of 32 items on the first request for smoothness. Otherwise - // listview displays 2 items first and then the rest of the page. - if (that.firstDataRequest) { - that.firstDataRequest = false; - count = Math.max(count, 32); - } - function listener(ev) { - that._notificationHandler.changed(that._item(ev.target)); - }; - - var perfId = "WinJS.UI.StorageDataSource:itemsFromIndex(" + first + "-" + (first + count - 1) + ")"; - msWriteProfilerMark(perfId + ",StartTM"); - return this._loader.getItemsAsync(first, count).then(function (itemsVector) { - var vectorSize = itemsVector.size; - if (vectorSize <= countBefore) { - return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist)); - } - var items = new Array(vectorSize); - var localItemsVector = new Array(vectorSize); - itemsVector.getMany(0, localItemsVector); - for (var i = 0; i < vectorSize; i++) { - items[i] = that._item(localItemsVector[i]); - localItemsVector[i].addEventListener("propertiesupdated", listener); - } - var result = { - items: items, - offset: countBefore, - absoluteIndex: index - }; - // set the totalCount only when we know it (when we retrieived fewer items than were asked for) - if (vectorSize < count) { - result.totalCount = first + vectorSize; - } - msWriteProfilerMark(perfId + ",StopTM"); - return result; - }); - }, - - itemsFromDescription: function (description, countBefore, countAfter) { - var that = this; - msWriteProfilerMark("WinJS.UI.StorageDataSource:itemsFromDescription,info"); - return this._query.findStartIndexAsync(description).then(function (index) { - return that.itemsFromIndex(index, countBefore, countAfter); - }); - }, - - getCount: function () { - msWriteProfilerMark("WinJS.UI.StorageDataSource:getCount,info"); - return this._query.getItemCountAsync(); - }, - - itemSignature: function (item) { - return item.folderRelativeId; - }, - - // compareByIdentity: set in constructor - // itemsFromStart: not implemented - // itemsFromKey: not implemented - // insertAtStart: not implemented - // insertBefore: not implemented - // insertAfter: not implemented - // insertAtEnd: not implemented - // change: not implemented - // moveToStart: not implemented - // moveBefore: not implemented - // moveAfter: not implemented - // moveToEnd: not implemented - // remove: not implemented - - // Private members - - _item: function (item) { - return { - key: item.path || item.folderRelativeId, - data: item - }; - } - }, { - supportedForProcessing: false, - }); - - return WinJS.Class.derive(WinJS.UI.VirtualizedDataSource, function (query, options) { - /// - /// - /// Creates a data source that enumerates an IStorageQueryResultBase. - /// - /// - /// The object to enumerate. It must support IStorageQueryResultBase. - /// - /// - /// An object that specifies options for the data source. This parameter is optional. It can contain these properties: - /// - /// mode: - /// A Windows.Storage.FileProperties.ThumbnailMode - a value that specifies whether to request - /// thumbnails and the type of thumbnails to request. - /// - /// requestedThumbnailSize: - /// A Number that specifies the size of the thumbnails. - /// - /// thumbnailOptions: - /// A Windows.Storage.FileProperties.ThumbnailOptions value that specifies additional options for the thumbnails. - /// - /// waitForFileLoad: - /// If you set this to true, the data source returns items only after it loads their properties and thumbnails. - /// - /// - /// - this._baseDataSourceConstructor(new StorageDataAdapter(query, options)); - }, { - /* empty */ - }, { - loadThumbnail: function (item, image) { - /// - /// - /// Returns a promise for an image element that completes when the full quality thumbnail of the provided item is drawn to the - /// image element. - /// - /// - /// The item to retrieve a thumbnail for. - /// - /// - /// The image element to use. If not provided, a new image element is created. - /// - /// - var thumbnailUpdateHandler, - thumbnailPromise, - shouldRespondToThumbnailUpdate = false; - - return new WinJS.Promise(function (complete, error, progress) { - // Load a thumbnail if it exists. The promise completes when a full quality thumbnail is visible. - var tagSupplied = (image ? true : false); - var processThumbnail = function (thumbnail) { - if (thumbnail) { - var url = URL.createObjectURL(thumbnail, {oneTimeOnly: true}); - - // If this is the first version of the thumbnail we're loading, fade it in. - if (!thumbnailPromise) { - thumbnailPromise = item.loadImage(url, image).then(function (image) { - // Wrapping the fadeIn call in a promise for the image returned by loadImage allows us to - // pipe the result of loadImage to further chained promises. This is necessary because the - // image element provided to loadThumbnail is optional, and loadImage will create an image - // element if none is provided. - return item.isOnScreen().then(function (visible) { - var imagePromise; - if (visible && tagSupplied) { - imagePromise = WinJS.UI.Animation.fadeIn(image).then(function () { - return image; - }); - } else { - image.style.opacity = 1; - imagePromise = WinJS.Promise.wrap(image); - } - return imagePromise; - }); - }); - } - // Otherwise, replace the existing version without animation. - else { - thumbnailPromise = thumbnailPromise.then(function (image) { - return item.loadImage(url, image); - }); - } - - // If we have the full resolution thumbnail, we can cancel further updates and complete the promise - // when current work is complete. - if ((thumbnail.type != Windows.Storage.FileProperties.ThumbnailType.icon) && !thumbnail.returnedSmallerCachedSize) { - msWriteProfilerMark("WinJS.UI.StorageDataSource:loadThumbnail complete,info"); - item.data.removeEventListener("thumbnailupdated", thumbnailUpdateHandler); - shouldRespondToThumbnailUpdate = false; - thumbnailPromise = thumbnailPromise.then(function (image) { - thumbnailUpdateHandler = null; - thumbnailPromise = null; - complete(image); - }); - } - } - }; - - thumbnailUpdateHandler = function (e) { - // Ensure that a zombie update handler does not get invoked. - if (shouldRespondToThumbnailUpdate) { - processThumbnail(e.target.thumbnail); - } - }; - item.data.addEventListener("thumbnailupdated", thumbnailUpdateHandler); - shouldRespondToThumbnailUpdate = true; - - // If we already have a thumbnail we should render it now. - processThumbnail(item.data.thumbnail); - }, function () { - item.data.removeEventListener("thumbnailupdated", thumbnailUpdateHandler); - shouldRespondToThumbnailUpdate = false; - thumbnailUpdateHandler = null; - if (thumbnailPromise) { - thumbnailPromise.cancel(); - thumbnailPromise = null; - } - }); - }, - - supportedForProcessing: false, - }); - }) - }); - -})(); -// Items Manager - -(function itemsManagerInit(global) { - "use strict"; - - /*#DBG - function dbg_stackTraceDefault() { return "add global function dbg_stackTrace to see stack traces"; } - - global.dbg_stackTrace = global.dbg_stackTrace || dbg_stackTraceDefault; - #DBG*/ - - var markSupportedForProcessing = WinJS.Utilities.markSupportedForProcessing; - - WinJS.Namespace.define("WinJS.UI", { - _normalizeRendererReturn: function (v) { - if (v) { - if (typeof v === "object" && v.element) { - var elementPromise = WinJS.Promise.as(v.element); - return elementPromise.then(function (e) { return { element: e, renderComplete: WinJS.Promise.as(v.renderComplete) } }); - } - else { - var elementPromise = WinJS.Promise.as(v); - return elementPromise.then(function (e) { return { element: e, renderComplete: WinJS.Promise.as() } }); - } - } - else { - return { element: null, renderComplete: WinJS.Promise.as() }; - } - }, - simpleItemRenderer: function (f) { - return markSupportedForProcessing(function (itemPromise, element) { - return itemPromise.then(function (item) { - return (item ? f(item, element) : null); - }); - }); - } - }); - - var Promise = WinJS.Promise; - var Signal = WinJS._Signal; - var Scheduler = WinJS.Utilities.Scheduler; - var UI = WinJS.UI; - - // Private statics - - var strings = { - get listDataSourceIsInvalid() { return WinJS.Resources._getWinJSString("ui/listDataSourceIsInvalid").value; }, - get itemRendererIsInvalid() { return WinJS.Resources._getWinJSString("ui/itemRendererIsInvalid").value; }, - get itemIsInvalid() { return WinJS.Resources._getWinJSString("ui/itemIsInvalid").value; }, - get invalidItemsManagerCallback() { return WinJS.Resources._getWinJSString("ui/invalidItemsManagerCallback").value; } - }; - - var imageLoader; - var lastSort = new Date(); - var minDurationBetweenImageSort = 64; - - // This optimization is good for a couple of reasons: - // - It is a global optimizer, which means that all on screen images take precedence over all off screen images. - // - It avoids resorting too frequently by only resorting when a new image loads and it has been at least 64 ms since - // the last sort. - // Also, it is worth noting that "sort" on an empty queue does no work (besides the function call). - function compareImageLoadPriority(a, b) { - var aon = false; - var bon = false; - - // Currently isOnScreen is synchronous and fast for list view - a.isOnScreen().then(function (v) { aon = v; }); - b.isOnScreen().then(function (v) { bon = v; }); - - return (aon ? 0 : 1) - (bon ? 0 : 1); - } - - var nextImageLoaderId = 0; - var seenUrls = {}; - var seenUrlsMRU = []; - var SEEN_URLS_MAXSIZE = 250; - var SEEN_URLS_MRU_MAXSIZE = 1000; - - function seenUrl(srcUrl) { - if ((/^blob:/i).test(srcUrl)) { - return; - } - - seenUrls[srcUrl] = true; - seenUrlsMRU.push(srcUrl); - - if (seenUrlsMRU.length > SEEN_URLS_MRU_MAXSIZE) { - var mru = seenUrlsMRU; - seenUrls = {}; - seenUrlsMRU = []; - - for (var count = 0, i = mru.length - 1; i >= 0 && count < SEEN_URLS_MAXSIZE; i--) { - var url = mru[i]; - if (!seenUrls[url]) { - seenUrls[url] = true; - count++; - } - } - } - } - - // Exposing the seenUrl related members to use them in unit tests - WinJS.Namespace.define("WinJS.UI", { - _seenUrl: seenUrl, - _getSeenUrls: function () { - return seenUrls; - }, - _getSeenUrlsMRU: function () { - return seenUrlsMRU; - }, - _seenUrlsMaxSize: SEEN_URLS_MAXSIZE, - _seenUrlsMRUMaxSize: SEEN_URLS_MRU_MAXSIZE - }); - - function loadImage(srcUrl, image, data) { - var imageId = nextImageLoaderId++; - imageLoader = imageLoader || new WinJS.UI._ParallelWorkQueue(6); - return imageLoader.queue(function () { - return new WinJS.Promise(function (c, e, p) { - Scheduler.schedule(function (jobInfo) { - if (!image) { - image = document.createElement("img"); - } - - var seen = seenUrls[srcUrl]; - - if (!seen) { - jobInfo.setPromise(new WinJS.Promise(function (imageLoadComplete) { - var tempImage = document.createElement("img"); - - var cleanup = function () { - tempImage.removeEventListener("load", loadComplete, false); - tempImage.removeEventListener("error", loadError, false); - - // One time use blob images are cleaned up as soon as they are not referenced by images any longer. - // We set the image src before clearing the tempImage src to make sure the blob image is always - // referenced. - image.src = srcUrl; - - var currentDate = new Date(); - if (currentDate - lastSort > minDurationBetweenImageSort) { - lastSort = currentDate; - imageLoader.sort(compareImageLoadPriority); - } - } - - var loadComplete = function () { - imageLoadComplete(jobComplete); - }; - var loadError = function () { - imageLoadComplete(jobError); - }; - - var jobComplete = function () { - seenUrl(srcUrl); - cleanup(); - c(image); - }; - var jobError = function () { - cleanup(); - e(image); - }; - - tempImage.addEventListener("load", loadComplete, false); - tempImage.addEventListener("error", loadError, false); - tempImage.src = srcUrl; - })); - } else { - seenUrl(srcUrl); - image.src = srcUrl; - c(image); - } - }, Scheduler.Priority.normal, null, "WinJS.UI._ImageLoader._image" + imageId); - }); - }, data); - } - - function isImageCached(srcUrl) { - return seenUrls[srcUrl]; - } - - function defaultRenderer(item) { - return document.createElement("div"); - } - - // Type-checks a callback parameter, since a failure will be hard to diagnose when it occurs - function checkCallback(callback, name) { - if (typeof callback !== "function") { - throw new WinJS.ErrorFromName("WinJS.UI.ItemsManager.CallbackIsInvalid", WinJS.Resources._formatString(strings.invalidItemsManagerCallback, name)); - } - } - - // Public definitions - - WinJS.Namespace.define("WinJS.UI", { - _createItemsManager: WinJS.Namespace._lazy(function () { - var ListNotificationHandler = WinJS.Class.define(function ListNotificationHandler_ctor(itemsManager) { - // Constructor - - this._itemsManager = itemsManager; - /*#DBG - this._notificationsCount = 0; - #DBG*/ - }, { - // Public methods - - beginNotifications: function () { - /*#DBG - if (this._notificationsCount !== 0) { - throw new "ACK! Unbalanced beginNotifications call"; - } - this._notificationsCount++; - #DBG*/ - this._itemsManager._versionManager.beginNotifications(); - this._itemsManager._beginNotifications(); - }, - - // itemAvailable: not implemented - - inserted: function (itemPromise, previousHandle, nextHandle) { - this._itemsManager._versionManager.receivedNotification(); - this._itemsManager._inserted(itemPromise, previousHandle, nextHandle); - }, - - changed: function (newItem, oldItem) { - this._itemsManager._versionManager.receivedNotification(); - this._itemsManager._changed(newItem, oldItem); - }, - - moved: function (itemPromise, previousHandle, nextHandle) { - this._itemsManager._versionManager.receivedNotification(); - this._itemsManager._moved(itemPromise, previousHandle, nextHandle); - }, - - removed: function (handle, mirage) { - this._itemsManager._versionManager.receivedNotification(); - this._itemsManager._removed(handle, mirage); - }, - - countChanged: function (newCount, oldCount) { - this._itemsManager._versionManager.receivedNotification(); - this._itemsManager._countChanged(newCount, oldCount); - }, - - indexChanged: function (handle, newIndex, oldIndex) { - this._itemsManager._versionManager.receivedNotification(); - this._itemsManager._indexChanged(handle, newIndex, oldIndex); - }, - - affectedRange: function (range) { - this._itemsManager._versionManager.receivedNotification(); - this._itemsManager._affectedRange(range); - }, - - endNotifications: function () { - /*#DBG - if (this._notificationsCount !== 1) { - throw new "ACK! Unbalanced endNotifications call"; - } - this._notificationsCount--; - #DBG*/ - this._itemsManager._versionManager.endNotifications(); - this._itemsManager._endNotifications(); - }, - - reload: function () { - this._itemsManager._versionManager.receivedNotification(); - this._itemsManager._reload(); - } - }, { // Static Members - supportedForProcessing: false, - }); - - var ItemsManager = WinJS.Class.define(function ItemsManager_ctor(listDataSource, itemRenderer, elementNotificationHandler, options) { - // Constructor - - if (!listDataSource) { - throw new WinJS.ErrorFromName("WinJS.UI.ItemsManager.ListDataSourceIsInvalid", strings.listDataSourceIsInvalid); - } - if (!itemRenderer) { - throw new WinJS.ErrorFromName("WinJS.UI.ItemsManager.ItemRendererIsInvalid", strings.itemRendererIsInvalid); - } - - this.$pipeline_callbacksMap = {}; - - this._listDataSource = listDataSource; - - this.dataSource = this._listDataSource; - - this._elementNotificationHandler = elementNotificationHandler; - - this._listBinding = this._listDataSource.createListBinding(new ListNotificationHandler(this)); - - if (options) { - if (options.ownerElement) { - this._ownerElement = options.ownerElement; - } - this._profilerId = options.profilerId; - this._versionManager = options.versionManager || new WinJS.UI._VersionManager(); - } - - this._indexInView = options && options.indexInView; - this._itemRenderer = itemRenderer; - this._viewCallsReady = options && options.viewCallsReady; - - // Map of (the uniqueIDs of) elements to records for items - this._elementMap = {}; - - // Map of handles to records for items - this._handleMap = {}; - - // Owner for use with jobs on the scheduler. Allows for easy cancellation of jobs during clean up. - this._jobOwner = Scheduler.createOwnerToken(); - - // Boolean to track whether endNotifications needs to be called on the ElementNotificationHandler - this._notificationsSent = false; - - // Only enable the lastItem method if the data source implements the itemsFromEnd method - if (this._listBinding.last) { - this.lastItem = function () { - return this._elementForItem(this._listBinding.last()); - }; - } - }, { - _itemFromItemPromise: function (itemPromise) { - return this._waitForElement(this._elementForItem(itemPromise)) - }, - // If stage 0 is not yet complete, caller is responsible for transitioning the item from stage 0 to stage 1 - _itemFromItemPromiseThrottled: function (itemPromise) { - return this._waitForElement(this._elementForItem(itemPromise, true)) - }, - _itemAtIndex: function (index) { - /*#DBG - var that = this; - var startVersion = that._versionManager.version; - #DBG*/ - var itemPromise = this._itemPromiseAtIndex(index) - var result = this._itemFromItemPromise(itemPromise)/*#DBG . - then(function (v) { - var rec = that._recordFromElement(v); - var endVersion = that._versionManager.version; - if (rec.item.index !== index) { - throw "ACK! inconsistent index"; - } - if (startVersion !== endVersion) { - throw "ACK! inconsistent version"; - } - if (WinJS.Utilities.data(v).itemData && - WinJS.Utilities.data(v).itemData.itemsManagerRecord.item.index !== index) { - throw "ACK! inconsistent itemData.index"; - } - return v; - }) #DBG*/; - return result.then(null, function (e) { - itemPromise.cancel(); - return WinJS.Promise.wrapError(e); - }); - }, - _itemPromiseAtIndex: function (index) { - /*#DBG - var that = this; - var startVersion = that._versionManager.version; - if (that._versionManager.locked) { - throw "ACK! Attempt to get an item while editing"; - } - #DBG*/ - var itemPromise = this._listBinding.fromIndex(index); - /*#DBG - itemPromise.then(function (item) { - var endVersion = that._versionManager.version; - if (item.index !== index) { - throw "ACK! inconsistent index"; - } - if (startVersion !== endVersion) { - throw "ACK! inconsistent version"; - } - return item; - }); - #DBG*/ - return itemPromise; - }, - _waitForElement: function (possiblePlaceholder) { - var that = this; - return new WinJS.Promise(function (c, e, p) { - if (possiblePlaceholder) { - if (!that.isPlaceholder(possiblePlaceholder)) { - c(possiblePlaceholder); - } - else { - var placeholderID = possiblePlaceholder.uniqueID; - var callbacks = that.$pipeline_callbacksMap[placeholderID]; - if (!callbacks) { - that.$pipeline_callbacksMap[placeholderID] = [c]; - } else { - callbacks.push(c); - } - } - } - else { - c(possiblePlaceholder); - } - }); - }, - _updateElement: function (newElement, oldElement) { - var placeholderID = oldElement.uniqueID; - var callbacks = this.$pipeline_callbacksMap[placeholderID]; - if (callbacks) { - delete this.$pipeline_callbacksMap[placeholderID]; - callbacks.forEach(function (c) { c(newElement); }); - } - }, - _firstItem: function () { - return this._waitForElement(this._elementForItem(this._listBinding.first())); - }, - _lastItem: function () { - return this._waitForElement(this._elementForItem(this._listBinding.last())); - }, - _previousItem: function (element) { - this._listBinding.jumpToItem(this._itemFromElement(element)); - return this._waitForElement(this._elementForItem(this._listBinding.previous())); - }, - _nextItem: function (element) { - this._listBinding.jumpToItem(this._itemFromElement(element)); - return this._waitForElement(this._elementForItem(this._listBinding.next())); - }, - _itemFromPromise: function (itemPromise) { - return this._waitForElement(this._elementForItem(itemPromise)); - }, - isPlaceholder: function (item) { - return !!this._recordFromElement(item).elementIsPlaceholder; - }, - - itemObject: function (element) { - return this._itemFromElement(element); - }, - - release: function () { - this._listBinding.release(); - this._elementNotificationHandler = null; - this._listBinding = null; - this._jobOwner.cancelAll(); - this._released = true; - }, - - releaseItemPromise: function (itemPromise) { - var handle = itemPromise.handle; - var record = this._handleMap[handle]; - if (!record) { - // The item promise is not in our handle map so we didn't even try to render it yet. - itemPromise.cancel(); - } else { - this._releaseRecord(record); - } - }, - - releaseItem: function (element) { - var record = this._elementMap[element.uniqueID]; - this._releaseRecord(record); - }, - - _releaseRecord: function (record) { - if (!record) { return; } - - /*#DBG - if (record.released) { - throw "ACK! Double release on item"; - } - #DBG*/ - - if (record.renderPromise) { - record.renderPromise.cancel(); - } - if (record.itemPromise) { - record.itemPromise.cancel(); - } - if (record.imagePromises) { - record.imagePromises.forEach(function (promise) { - promise.cancel(); - }); - } - if (record.itemReadyPromise) { - record.itemReadyPromise.cancel(); - } - if (record.renderComplete) { - record.renderComplete.cancel(); - } - - this._removeEntryFromElementMap(record.element); - this._removeEntryFromHandleMap(record.itemPromise.handle, record); - - if (record.item) { - this._listBinding.releaseItem(record.item); - } - - /*#DBG - record.released = true; - if (record.updater) { - throw "ACK! attempt to release item current held by updater"; - } - #DBG*/ - }, - - refresh: function () { - return this._listDataSource.invalidateAll(); - }, - - // Private members - - _handlerToNotifyCaresAboutItemAvailable: function () { - return !!(this._elementNotificationHandler && this._elementNotificationHandler.itemAvailable); - }, - - _handlerToNotify: function () { - if (!this._notificationsSent) { - this._notificationsSent = true; - - if (this._elementNotificationHandler && this._elementNotificationHandler.beginNotifications) { - this._elementNotificationHandler.beginNotifications(); - } - } - return this._elementNotificationHandler; - }, - - _defineIndexProperty: function (itemForRenderer, item, record) { - record.indexObserved = false; - Object.defineProperty(itemForRenderer, "index", { - get: function () { - record.indexObserved = true; - return item.index; - } - }); - }, - - _renderPlaceholder: function (record) { - var itemForRenderer = {}; - var elementPlaceholder = defaultRenderer(itemForRenderer); - record.elementIsPlaceholder = true; - return elementPlaceholder; - }, - - _renderItem: function (itemPromise, record, callerThrottlesStage1) { - var that = this; - var indexInView = that._indexInView || function () { return true; }; - var stage1Signal = new Signal(); - var readySignal = new Signal(); - var perfItemPromiseId = "_renderItem(" + record.item.index + "):itemPromise"; - - var stage0RunningSync = true; - var stage0Ran = false; - itemPromise.then(function (item) { - stage0Ran = true; - if (stage0RunningSync) { - stage1Signal.complete(item); - } - }); - stage0RunningSync = false; - - var itemForRendererPromise = stage1Signal.promise.then(function (item) { - if (item) { - var itemForRenderer = Object.create(item); - // Derive a new item and override its index property, to track whether it is read - that._defineIndexProperty(itemForRenderer, item, record); - itemForRenderer.ready = readySignal.promise; - itemForRenderer.isOnScreen = function () { - return Promise.wrap(indexInView(item.index)); - }; - itemForRenderer.loadImage = function (srcUrl, image) { - var loadImagePromise = loadImage(srcUrl, image, itemForRenderer); - if (record.imagePromises) { - record.imagePromises.push(loadImagePromise); - } else { - record.imagePromises = [loadImagePromise]; - } - return loadImagePromise; - }; - itemForRenderer.isImageCached = isImageCached; - return itemForRenderer; - } else { - return WinJS.Promise.cancel; - } - }); - - function queueAsyncStage1() { - itemPromise.then(function (item) { - that._writeProfilerMark(perfItemPromiseId + ",StartTM"); - stage1Signal.complete(item); - that._writeProfilerMark(perfItemPromiseId + ",StopTM"); - }); - } - if (!stage0Ran) { - if (callerThrottlesStage1) { - record.stage0 = itemPromise; - record.startStage1 = function () { - record.startStage1 = null; - queueAsyncStage1(); - } - } else { - queueAsyncStage1(); - } - } - - itemForRendererPromise.handle = itemPromise.handle; - record.itemPromise = itemForRendererPromise; - record.itemReadyPromise = readySignal.promise; - record.readyComplete = false; - - // perfRendererWorkId = stage 1 rendering (if itemPromise is async) or stage 1+2 (if itemPromise is sync and ran inline) - // perfItemPromiseId = stage 2 rendering only (should only be emitted if itemPromise was async) - // perfItemReadyId = stage 3 rendering - var perfRendererWorkId = "_renderItem(" + record.item.index + (stage0Ran ? "):syncItemPromise" : "):placeholder"); - var perfItemReadyId = "_renderItem(" + record.item.index + "):itemReady"; - - this._writeProfilerMark(perfRendererWorkId + ",StartTM"); - var rendererPromise = WinJS.Promise.as(that._itemRenderer(itemForRendererPromise, record.element)). - then(WinJS.UI._normalizeRendererReturn). - then(function (v) { - if (that._released) { - return WinJS.Promise.cancel; - } - - itemForRendererPromise.then(function (item) { - // Store pending ready callback off record so ScrollView can call it during realizePage. Otherwise - // call it ourselves. - record.pendingReady = function () { - if (record.pendingReady) { - record.pendingReady = null; - record.readyComplete = true; - that._writeProfilerMark(perfItemReadyId + ",StartTM"); - readySignal.complete(item); - that._writeProfilerMark(perfItemReadyId + ",StopTM"); - } - } - if (!that._viewCallsReady) { - var job = Scheduler.schedule(record.pendingReady, Scheduler.Priority.normal, - record, "WinJS.UI._ItemsManager._pendingReady"); - job.owner = that._jobOwner; - } - }); - return v; - }); - - this._writeProfilerMark(perfRendererWorkId + ",StopTM"); - return rendererPromise; - }, - - _replaceElement: function (record, elementNew) { - /*#DBG - if (!this._handleInHandleMap(record.item.handle)) { - throw "ACK! replacing element not present in handle map"; - } - #DBG*/ - this._removeEntryFromElementMap(record.element); - record.element = elementNew; - this._addEntryToElementMap(elementNew, record); - }, - - _changeElement: function (record, elementNew, elementNewIsPlaceholder) { - //#DBG _ASSERT(elementNew); - record.renderPromise = null; - var elementOld = record.element, - itemOld = record.item; - - if (record.newItem) { - record.item = record.newItem; - record.newItem = null; - } - - this._replaceElement(record, elementNew); - - if (record.item && record.elementIsPlaceholder && !elementNewIsPlaceholder) { - record.elementDelayed = null; - record.elementIsPlaceholder = false; - this._updateElement(record.element, elementOld); - if (this._handlerToNotifyCaresAboutItemAvailable()) { - this._handlerToNotify().itemAvailable(record.element, elementOld); - } - } else { - this._handlerToNotify().changed(elementNew, elementOld, itemOld); - } - }, - - _elementForItem: function (itemPromise, callerThrottlesStage1) { - var handle = itemPromise.handle, - record = this._recordFromHandle(handle, true), - element; - - if (!handle) { - return null; - } - - if (record) { - element = record.element; - } else { - // Create a new record for this item - record = { - item: itemPromise, - itemPromise: itemPromise - }; - this._addEntryToHandleMap(handle, record); - - var that = this; - var mirage = false; - var synchronous = false; - - var renderPromise = - that._renderItem(itemPromise, record, callerThrottlesStage1). - then(function (v) { - var elementNew = v.element; - record.renderComplete = v.renderComplete; - - itemPromise.then(function (item) { - record.item = item; - if (!item) { - mirage = true; - element = null; - } - }); - - synchronous = true; - record.renderPromise = null; - - if (elementNew) { - if (element) { - that._presentElements(record, elementNew); - } else { - element = elementNew; - } - } - }); - - if (!mirage) { - if (!synchronous) { - record.renderPromise = renderPromise; - } - - if (!element) { - element = this._renderPlaceholder(record); - } - - record.element = element; - this._addEntryToElementMap(element, record); - - itemPromise.retain(); - } - } - - return element; - }, - - _addEntryToElementMap: function (element, record) { - /*#DBG - if (WinJS.Utilities.data(element).itemsManagerRecord) { - throw "ACK! Extra call to _addEntryToElementMap, ref counting error"; - } - WinJS.Utilities.data(element).itemsManagerRecord = record; - #DBG*/ - this._elementMap[element.uniqueID] = record; - }, - - _removeEntryFromElementMap: function (element) { - /*#DBG - if (!WinJS.Utilities.data(element).itemsManagerRecord) { - throw "ACK! Extra call to _removeEntryFromElementMap, ref counting error"; - } - WinJS.Utilities.data(element).removeElementMapRecord = WinJS.Utilities.data(element).itemsManagerRecord; - WinJS.Utilities.data(element).removeEntryMapStack = dbg_stackTrace(); - delete WinJS.Utilities.data(element).itemsManagerRecord; - #DBG*/ - delete this._elementMap[element.uniqueID]; - }, - - _recordFromElement: function (element, ignoreFailure) { - var record = this._elementMap[element.uniqueID]; - if (!record) { - /*#DBG - var removeElementMapRecord = WinJS.Utilities.data(element).removeElementMapRecord; - var itemsManagerRecord = WinJS.Utilities.data(element).itemsManagerRecord; - #DBG*/ - this._writeProfilerMark("_recordFromElement:ItemIsInvalidError,info"); - throw new WinJS.ErrorFromName("WinJS.UI.ItemsManager.ItemIsInvalid", strings.itemIsInvalid); - } - - return record; - }, - - _addEntryToHandleMap: function (handle, record) { - /*#DBG - if (this._handleMap[handle]) { - throw "ACK! Extra call to _addEntryToHandleMap, ref counting error"; - } - this._handleMapLeak = this._handleMapLeak || {}; - this._handleMapLeak[handle] = { record: record, addHandleMapStack: dbg_stackTrace() }; - #DBG*/ - this._handleMap[handle] = record; - }, - - _removeEntryFromHandleMap: function (handle, record) { - /*#DBG - if (!this._handleMap[handle]) { - throw "ACK! Extra call to _removeEntryFromHandleMap, ref counting error"; - } - this._handleMapLeak[handle].removeHandleMapStack = dbg_stackTrace(); - #DBG*/ - delete this._handleMap[handle]; - }, - - _handleInHandleMap: function (handle) { - return !!this._handleMap[handle]; - }, - - _recordFromHandle: function (handle, ignoreFailure) { - var record = this._handleMap[handle]; - if (!record && !ignoreFailure) { - /*#DBG - var leak = this._handleMapLeak[handle]; - #DBG*/ - throw new WinJS.ErrorFromName("WinJS.UI.ItemsManager.ItemIsInvalid", strings.itemIsInvalid); - } - return record; - }, - - _foreachRecord: function (callback) { - var records = this._handleMap; - for (var property in records) { - var record = records[property]; - callback(record); - } - }, - - _itemFromElement: function (element) { - return this._recordFromElement(element).item; - }, - - _elementFromHandle: function (handle) { - if (handle) { - var record = this._recordFromHandle(handle, true); - - if (record && record.element) { - return record.element; - } - } - - return null; - }, - - _inserted: function (itemPromise, previousHandle, nextHandle) { - this._handlerToNotify().inserted(itemPromise, previousHandle, nextHandle); - }, - - _changed: function (newItem, oldItem) { - if (!this._handleInHandleMap(oldItem.handle)) { return; } - - var record = this._recordFromHandle(oldItem.handle); - - //#DBG _ASSERT(record); - if (record.renderPromise) { - record.renderPromise.cancel(); - } - if (record.itemPromise) { - record.itemPromise.cancel(); - } - if (record.imagePromises) { - record.imagePromises.forEach(function (promise) { - promise.cancel(); - }); - } - if (record.itemReadyPromise) { - record.itemReadyPromise.cancel(); - } - if (record.renderComplete) { - record.renderComplete.cancel(); - } - - record.newItem = newItem; - - var that = this; - var newItemPromise = WinJS.Promise.as(newItem); - newItemPromise.handle = record.itemPromise.handle; - record.renderPromise = this._renderItem(newItemPromise, record). - then(function (v) { - record.renderComplete = v.renderComplete; - that._changeElement(record, v.element, false); - that._presentElements(record); - }); - }, - - _moved: function (itemPromise, previousHandle, nextHandle) { - // no check for haveHandle, as we get move notification for items we - // are "next" to, so we handle the "null element" cases below - // - var element = this._elementFromHandle(itemPromise.handle); - var previous = this._elementFromHandle(previousHandle); - var next = this._elementFromHandle(nextHandle); - - this._handlerToNotify().moved(element, previous, next, itemPromise); - this._presentAllElements(); - }, - - _removed: function (handle, mirage) { - if (this._handleInHandleMap(handle)) { - var element = this._elementFromHandle(handle); - - //#DBG _ASSERT(element); - this._handlerToNotify().removed(element, mirage, handle); - this.releaseItem(element); - this._presentAllElements(); - } else { - this._handlerToNotify().removed(null, mirage, handle); - } - }, - - _countChanged: function (newCount, oldCount) { - if (this._elementNotificationHandler && this._elementNotificationHandler.countChanged) { - this._handlerToNotify().countChanged(newCount, oldCount); - } - }, - - _indexChanged: function (handle, newIndex, oldIndex) { - var element; - if (this._handleInHandleMap(handle)) { - var record = this._recordFromHandle(handle); - if (record.indexObserved) { - if (!record.elementIsPlaceholder) { - if (record.item.index !== newIndex) { - if (record.renderPromise) { - record.renderPromise.cancel(); - } - if (record.renderComplete) { - record.renderComplete.cancel(); - } - - var itemToRender = record.newItem || record.item; - itemToRender.index = newIndex; - - var newItemPromise = WinJS.Promise.as(itemToRender); - newItemPromise.handle = record.itemPromise.handle; - - var that = this; - record.renderPromise = this._renderItem(newItemPromise, record). - then(function (v) { - record.renderComplete = v.renderComplete; - that._changeElement(record, v.element, false); - that._presentElements(record); - }); - } - } else { - this._changeElement(record, this._renderPlaceholder(record), true); - } - } - element = record.element; - } - if (this._elementNotificationHandler && this._elementNotificationHandler.indexChanged) { - this._handlerToNotify().indexChanged(element, newIndex, oldIndex); - } - }, - - _affectedRange: function (range) { - if (this._elementNotificationHandler && this._elementNotificationHandler.updateAffectedRange) { - this._handlerToNotify().updateAffectedRange(range); - } - }, - - _beginNotifications: function () { - // accessing _handlerToNotify will force the call to beginNotifications on the client - // - this._externalBegin = true; - var x = this._handlerToNotify(); - }, - _endNotifications: function () { - if (this._notificationsSent) { - this._notificationsSent = false; - this._externalBegin = false; - - if (this._elementNotificationHandler && this._elementNotificationHandler.endNotifications) { - this._elementNotificationHandler.endNotifications(); - } - } - }, - - _reload: function () { - if (this._elementNotificationHandler && this._elementNotificationHandler.reload) { - this._elementNotificationHandler.reload(); - } - }, - - // Some functions may be called synchronously or asynchronously, so it's best to post _endNotifications to avoid - // calling it prematurely. - _postEndNotifications: function () { - if (this._notificationsSent && !this._externalBegin && !this._endNotificationsPosted) { - this._endNotificationsPosted = true; - var that = this; - Scheduler.schedule(function () { - that._endNotificationsPosted = false; - that._endNotifications(); - }, Scheduler.Priority.high, null, "WinJS.UI._ItemsManager._postEndNotifications"); - } - }, - - _presentElement: function (record) { - var elementOld = record.element; - //#DBG _ASSERT(elementOld); - - // Finish modifying the slot before calling back into user code, in case there is a reentrant call - this._replaceElement(record, record.elementDelayed); - record.elementDelayed = null; - - record.elementIsPlaceholder = false; - this._updateElement(record.element, elementOld); - if (this._handlerToNotifyCaresAboutItemAvailable()) { - this._handlerToNotify().itemAvailable(record.element, elementOld); - } - }, - - _presentElements: function (record, elementDelayed) { - if (elementDelayed) { - record.elementDelayed = elementDelayed; - } - - this._listBinding.jumpToItem(record.item); - if (record.elementDelayed) { - this._presentElement(record); - } - - this._postEndNotifications(); - }, - - // Presents all delayed elements - _presentAllElements: function () { - var that = this; - this._foreachRecord(function (record) { - if (record.elementDelayed) { - that._presentElement(record); - } - }); - }, - - _writeProfilerMark: function (text) { - var message = "WinJS.UI._ItemsManager:" + (this._profilerId ? (this._profilerId + ":") : ":") + text; - msWriteProfilerMark(message); - } - }, { // Static Members - supportedForProcessing: false, - }); - - return function (dataSource, itemRenderer, elementNotificationHandler, options) { - return new ItemsManager(dataSource, itemRenderer, elementNotificationHandler, options); - }; - }) - }); - -})(this); - - -(function parallelWorkQueueInit(global) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - _ParallelWorkQueue : WinJS.Namespace._lazy(function () { - return WinJS.Class.define(function ParallelWorkQueue_ctor(maxRunning) { - var workIndex = 0; - var workItems = {}; - var workQueue = []; - - maxRunning = maxRunning || 3; - var running = 0; - var processing = 0; - function runNext() { - running--; - // if we have fallen out of this loop, then we know we are already - // async, so "post" is OK. If we are still in the loop, then the - // loop will continue to run, so we don't need to "post" or - // recurse. This avoids stack overflow in the sync case. - // - if (!processing) { - WinJS.Utilities.Scheduler.schedule(run, WinJS.Utilities.Scheduler.Priority.normal, - null, "WinJS._ParallelWorkQueue.runNext"); - } - } - function run() { - processing++; - for (; running < maxRunning; running++) { - var next; - var nextWork; - do { - next = workQueue.shift(); - nextWork = next && workItems[next]; - } while (next && !nextWork); - - if (nextWork) { - delete workItems[next] - try { - nextWork().then(runNext, runNext); - } - catch (err) { - // this will only get hit if there is a queued item that - // fails to return something that conforms to the Promise - // contract - // - runNext(); - } - } - else { - break; - } - } - processing--; - } - function queue(f, data, first) { - var id = "w" + (workIndex++); - var workPromise; - return new WinJS.Promise( - function (c, e, p) { - var w = function () { - workPromise = f().then(c, e, p); - return workPromise; - }; - w.data = data; - workItems[id] = w; - if (first) { - workQueue.unshift(id); - } - else { - workQueue.push(id); - } - run(); - }, - function () { - delete workItems[id]; - if (workPromise) { - workPromise.cancel(); - } - } - ); - } - - this.sort = function (f) { - workQueue.sort(function (a, b) { - a = workItems[a]; - b = workItems[b]; - return a === undefined && b === undefined ? 0 : a === undefined ? 1 : b === undefined ? -1 : f(a.data, b.data); - }); - }; - this.queue = queue; - }, { - /* empty */ - }, { - supportedForProcessing: false, - }); - }) - }); - -})(this); - - -(function versionManagerInit(global) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - _VersionManager: WinJS.Namespace._lazy(function () { - return WinJS.Class.define(function _VersionManager_ctor() { - this._unlocked = new WinJS._Signal(); - this._unlocked.complete(); - }, { - _cancelCount: 0, - _notificationCount: 0, - _updateCount: 0, - _version: 0, - - // This should be used generally for all logic that should be suspended while data changes are happening - // - locked: { get: function () { return this._notificationCount !== 0 || this._updateCount !== 0; } }, - - // this should only be accessed by the update logic in ListViewImpl.js - // - noOutstandingNotifications: { get: function () { return this._notificationCount === 0; } }, - version: { get: function () { return this._version; } }, - - unlocked: { get: function () { return this._unlocked.promise; } }, - - _dispose: function () { - if (this._unlocked) { - this._unlocked.cancel(); - this._unlocked = null; - } - }, - - beginUpdating: function () { - this._checkLocked(); - /*#DBG - if (this._updateCount !== 0) { - throw "ACK! incorrect begin/endUpdating pair on version manager"; - } - #DBG*/ - this._updateCount++; - }, - endUpdating: function() { - this._updateCount--; - /*#DBG - if (this._updateCount < 0) { - throw "ACK! incorrect begin/endUpdating pair on version manager"; - } - #DBG*/ - this._checkUnlocked(); - }, - beginNotifications: function () { - this._checkLocked(); - this._notificationCount++; - }, - endNotifications: function () { - this._notificationCount--; - /*#DBG - if (this._notificationCount < 0) { - throw "ACK! incorrect begin/endNotifications pair on version manager"; - } - #DBG*/ - this._checkUnlocked(); - }, - _checkLocked: function () { - if (!this.locked) { - this._dispose(); - this._unlocked = new WinJS._Signal(); - } - }, - _checkUnlocked: function () { - if (!this.locked) { - this._unlocked.complete(); - } - }, - receivedNotification: function () { - this._version++; - if (this._cancel) { - var cancel = this._cancel; - this._cancel = null; - cancel.forEach(function (p) { p && p.cancel(); }); - } - }, - cancelOnNotification: function (promise) { - if (!this._cancel) { - this._cancel = []; - this._cancelCount = 0; - } - this._cancel[this._cancelCount++] = promise; - return this._cancelCount - 1; - }, - clearCancelOnNotification: function (token) { - if (this._cancel) { - delete this._cancel[token]; - } - } - }, { - supportedForProcessing: false, - }); - }) - }); - -})(); - - -(function flipperInit(WinJS) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// Displays a collection, such as a set of photos, one item at a time. - /// - /// - /// - /// ]]> - /// Raised when the number of items in the itemDataSource changes. - /// Raised when a FlipView page becomes visible or invisible. - /// Raised when the FlipView flips to a page. - /// Raised when the FlipView flips to a page and its renderer function completes. - /// The entire FlipView control. - /// The general class for all FlipView navigation buttons. - /// The left navigation button. - /// The right navigation button. - /// The top navigation button. - /// The bottom navigation button. - /// - /// - /// - FlipView: WinJS.Namespace._lazy(function () { - var thisWinUI = WinJS.UI; - var utilities = WinJS.Utilities; - var Scheduler = WinJS.Utilities.Scheduler; - var animation = WinJS.UI.Animation; - - // Class names - var navButtonClass = "win-navbutton", - flipViewClass = "win-flipview", - navButtonLeftClass = "win-navleft", - navButtonRightClass = "win-navright", - navButtonTopClass = "win-navtop", - navButtonBottomClass = "win-navbottom"; - - // Aria labels - var previousButtonLabel = "Previous", - nextButtonLabel = "Next"; - - var buttonFadeDelay = 3000, - avoidTrapDelay = 500, - leftArrowGlyph = "", - rightArrowGlyph = "", - topArrowGlyph = "", - bottomArrowGlyph = "", - animationMoveDelta = 40; - - function flipViewPropertyChanged(list) { - var that = list[0].target.winControl; - if (that && that instanceof WinJS.UI.FlipView) { - if (list.some(function (record) { - if (record.attributeName === "dir") { - return true; - } else if (record.attributeName === "style") { - return (that._cachedStyleDir != record.target.style.direction); - } else { - return false; - } - })) { - that._cachedStyleDir = that._flipviewDiv.style.direction; - that._rtl = window.getComputedStyle(that._flipviewDiv, null).direction === "rtl"; - that._setupOrientation(); - } - } - } - - function flipviewResized(e) { - var that = e.srcElement && e.srcElement.winControl; - if (that && that instanceof WinJS.UI.FlipView) { - msWriteProfilerMark("WinJS.UI.FlipView:resize,StartTM"); - that._resize(); - } - } - - var strings = { - get badAxis() { return WinJS.Resources._getWinJSString("ui/badAxis").value; }, - get badCurrentPage() { return WinJS.Resources._getWinJSString("ui/badCurrentPage").value; }, - get noitemsManagerForCount() { return WinJS.Resources._getWinJSString("ui/noitemsManagerForCount").value; }, - get badItemSpacingAmount() { return WinJS.Resources._getWinJSString("ui/badItemSpacingAmount").value; }, - get navigationDuringStateChange() { return WinJS.Resources._getWinJSString("ui/flipViewNavigationDuringStateChange").value; }, - get panningContainerAriaLabel() { return WinJS.Resources._getWinJSString("ui/flipViewPanningContainerAriaLabel").value; } - }; - - var FlipView = WinJS.Class.define(function FlipView_ctor(element, options) { - /// - /// - /// Creates a new FlipView. - /// - /// - /// The DOM element that hosts the control. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. - /// Each property of the options object corresponds to one of the control's properties or events. - /// Event names must begin with "on". For example, to provide a handler for the pageselected event, - /// add a property named "onpageselected" to the options object and set its value to the event handler. - /// This parameter is optional. - /// - /// - /// The new FlipView control. - /// - /// - msWriteProfilerMark("WinJS.UI.FlipView:constructor,StartTM"); - - this._disposed = false; - - element = element || document.createElement("div"); - - var horizontal = true, - dataSource = null, - itemRenderer = WinJS.UI._trivialHtmlRenderer, - initialIndex = 0, - itemSpacing = 0; - - if (options) { - // flipAxis parameter checking. Must be a string, either "horizontal" or "vertical" - if (options.orientation) { - if (typeof options.orientation === "string") { - switch (options.orientation.toLowerCase()) { - case "horizontal": - horizontal = true; - break; - - case "vertical": - horizontal = false; - break; - } - } - } - - if (options.currentPage) { - initialIndex = options.currentPage >> 0; - initialIndex = initialIndex < 0 ? 0 : initialIndex; - } - - if (options.itemDataSource) { - dataSource = options.itemDataSource; - } - - if (options.itemTemplate) { - itemRenderer = this._getItemRenderer(options.itemTemplate); - } - - if (options.itemSpacing) { - itemSpacing = options.itemSpacing >> 0; - itemSpacing = itemSpacing < 0 ? 0 : itemSpacing; - } - } - - if (!dataSource) { - var list = new WinJS.Binding.List(); - dataSource = list.dataSource; - } - utilities.empty(element); - - this._initializeFlipView(element, horizontal, dataSource, itemRenderer, initialIndex, itemSpacing); - - element.winControl = this; - WinJS.Utilities.addClass(element, "win-disposable"); - - // Call _setOption with eventsOnly flag on - WinJS.UI._setOptions(this, options, true); - - this._avoidTrappingTime = 0; - this._windowWheelHandlerBound = this._windowWheelHandler.bind(this); - window.addEventListener('wheel', this._windowWheelHandlerBound); - - msWriteProfilerMark("WinJS.UI.FlipView:constructor,StopTM"); - }, { - - // Public methods - - dispose: function FlipView_dispose() { - /// - /// - /// Disposes this FlipView. - /// - /// - msWriteProfilerMark("WinJS.UI.FlipView:dispose,StopTM"); - if (this._disposed) { - return; - } - - window.removeEventListener('wheel', this._windowWheelHandlerBound); - - - this._disposed = true; - this._pageManager.dispose(); - this._itemsManager.release(); - this.itemDataSource = null; - }, - - next: function FlipView_next() { - /// - /// - /// Navigates to the next item. - /// - /// - /// true if the FlipView begins navigating to the next page; - /// false if the FlipView is at the last page or is in the middle of another navigation animation. - /// - /// - msWriteProfilerMark("WinJS.UI.FlipView:next,info"); - var cancelAnimationCallback = this._nextAnimation ? null : this._cancelDefaultAnimation; - return this._navigate(true, cancelAnimationCallback); - }, - - previous: function FlipView_previous() { - /// - /// - /// Navigates to the previous item. - /// - /// - /// true if FlipView begins navigating to the previous page; - /// false if the FlipView is already at the first page or is in the middle of another navigation animation. - /// - /// - msWriteProfilerMark("WinJS.UI.FlipView:prev,info"); - var cancelAnimationCallback = this._prevAnimation ? null : this._cancelDefaultAnimation; - return this._navigate(false, cancelAnimationCallback); - }, - - /// - element: { - get: function () { - return this._flipviewDiv; - } - }, - - /// - /// Gets or sets the index of the currently displayed page. The minimum value is 0 and the maximum value is one less than the total number of items returned by the data source. - /// - currentPage: { - get: function () { - return this._getCurrentIndex(); - }, - set: function (index) { - msWriteProfilerMark("WinJS.UI.FlipView:set_currentPage,info"); - - if (this._pageManager._notificationsEndedSignal) { - var that = this; - this._pageManager._notificationsEndedSignal.promise.done(function () { - that._pageManager._notificationsEndedSignal = null; - that.currentPage = index; - }); - return; - } - - if (this._animating && !this._cancelAnimation()) { - return; - } - - index = index >> 0; - index = index < 0 ? 0 : index; - - if (this._refreshTimer) { - this._indexAfterRefresh = index; - } else { - if (this._pageManager._cachedSize > 0) { - index = Math.min(this._pageManager._cachedSize - 1, index); - } else if (this._pageManager._cachedSize === 0) { - index = 0; - } - - var that = this; - if (this._jumpingToIndex === index) { - return; - } - var clearJumpToIndex = function () { - that._jumpingToIndex = null; - }; - this._jumpingToIndex = index; - var jumpAnimation = (this._jumpAnimation ? this._jumpAnimation : this._defaultAnimation.bind(this)), - cancelAnimationCallback = (this._jumpAnimation ? null : this._cancelDefaultAnimation), - completionCallback = function () { that._completeJump(); }; - this._pageManager.startAnimatedJump(index, cancelAnimationCallback, completionCallback). - then(function (elements) { - if (elements) { - that._animationsStarted(); - var currElement = elements.oldPage.pageRoot; - var newCurrElement = elements.newPage.pageRoot; - that._contentDiv.appendChild(currElement); - that._contentDiv.appendChild(newCurrElement); - - that._completeJumpPending = true; - jumpAnimation(currElement, newCurrElement). - then(function () { - if (that._completeJumpPending) { - completionCallback(); - msWriteProfilerMark("WinJS.UI.FlipView:set_currentPage.animationComplete,info"); - } - }).done(clearJumpToIndex, clearJumpToIndex); - } else { - clearJumpToIndex(); - } - }, clearJumpToIndex); - } - } - }, - - /// - /// Gets or sets the layout orientation of the FlipView, horizontal or vertical. - /// - orientation: { - get: function () { - return this._axisAsString(); - }, - set: function (orientation) { - msWriteProfilerMark("WinJS.UI.FlipView:set_orientation,info"); - var horizontal = orientation === "horizontal"; - if (horizontal !== this._horizontal) { - this._horizontal = horizontal; - this._setupOrientation(); - this._pageManager.setOrientation(this._horizontal); - } - } - }, - - /// - /// Gets or sets the data source that provides the FlipView with items to display. - /// The FlipView displays one item at a time, each on its own page. - /// - itemDataSource: { - get: function () { - return this._dataSource; - }, - - set: function (dataSource) { - msWriteProfilerMark("WinJS.UI.FlipView:set_itemDataSource,info"); - this._dataSourceAfterRefresh = dataSource || new WinJS.Binding.List().dataSource; - this._refresh(); - } - }, - - /// - /// Gets or sets a WinJS.Binding.Template or a function that defines the HTML for each item's page. - /// - itemTemplate: { - get: function () { - return this._itemRenderer; - }, - - set: function (itemTemplate) { - msWriteProfilerMark("WinJS.UI.FlipView:set_itemTemplate,info"); - this._itemRendererAfterRefresh = this._getItemRenderer(itemTemplate); - this._refresh(); - } - }, - - /// - /// Gets or sets the spacing between items, in pixels. - /// - itemSpacing: { - get: function () { - return this._pageManager.getItemSpacing(); - }, - - set: function (spacing) { - msWriteProfilerMark("WinJS.UI.FlipView:set_itemSpacing,info"); - spacing = spacing >> 0; - spacing = spacing < 0 ? 0 : spacing; - this._pageManager.setItemSpacing(spacing); - } - }, - - count: function FlipView_count() { - /// - /// - /// Returns the number of items in the FlipView object's itemDataSource. - /// - /// - /// A Promise that contains the number of items in the list - /// or WinJS.UI.CountResult.unknown if the count is unavailable. - /// - /// - - msWriteProfilerMark("WinJS.UI.FlipView:count,info"); - var that = this; - return new WinJS.Promise(function (complete, error) { - if (that._itemsManager) { - if (that._pageManager._cachedSize === WinJS.UI.CountResult.unknown || that._pageManager._cachedSize >= 0) { - complete(that._pageManager._cachedSize); - } else { - that._dataSource.getCount().then(function (count) { - that._pageManager._cachedSize = count; - complete(count); - }); - } - } else { - error(thisWinUI.FlipView.noitemsManagerForCount); - } - }); - }, - - setCustomAnimations: function FlipView_setCustomAnimations(animations) { - /// - /// - /// Sets custom animations for the FlipView to use when navigating between pages. - /// - /// - /// An object containing up to three fields, one for each navigation action: next, previous, and jump - /// Each of those fields must be a function with this signature: function (outgoingPage, incomingPage). - /// This function returns a WinJS.Promise object that completes once the animations are finished. - /// If a field is null or undefined, the FlipView reverts to its default animation for that action. - /// - /// - msWriteProfilerMark("WinJS.UI.FlipView:setCustomAnimations,info"); - - if (animations.next !== undefined) { - this._nextAnimation = animations.next; - } - if (animations.previous !== undefined) { - this._prevAnimation = animations.previous; - } - if (animations.jump !== undefined) { - this._jumpAnimation = animations.jump; - } - }, - - forceLayout: function FlipView_forceLayout() { - /// - /// - /// Forces the FlipView to update its layout. - /// Use this function when making the FlipView visible again after its style.display property had been set to "none". - /// - /// - msWriteProfilerMark("WinJS.UI.FlipView:forceLayout,info"); - - this._pageManager.resized(); - }, - - // Private members - - _initializeFlipView: function FlipView_initializeFlipView(element, horizontal, dataSource, itemRenderer, initialIndex, itemSpacing) { - this._flipviewDiv = element; - utilities.addClass(this._flipviewDiv, flipViewClass); - this._contentDiv = document.createElement("div"); - this._panningDivContainer = document.createElement("div"); - this._panningDivContainer.className = "win-surface"; - this._panningDiv = document.createElement("div"); - this._prevButton = document.createElement("button"); - this._nextButton = document.createElement("button"); - this._horizontal = horizontal; - this._dataSource = dataSource; - this._itemRenderer = itemRenderer; - this._itemsManager = null; - this._pageManager = null; - - var accName = this._flipviewDiv.getAttribute("aria-label"); - if (!accName) { - this._flipviewDiv.setAttribute("aria-label", ""); - } - - this._flipviewDiv.setAttribute("role", "listbox"); - if (!this._flipviewDiv.style.overflow) { - this._flipviewDiv.style.overflow = "hidden"; - } - this._contentDiv.style.position = "relative"; - this._contentDiv.style.zIndex = 0; - this._contentDiv.style.width = "100%"; - this._contentDiv.style.height = "100%"; - this._panningDiv.style.position = "relative"; - this._panningDivContainer.style.position = "relative"; - this._panningDivContainer.style.width = "100%"; - this._panningDivContainer.style.height = "100%"; - this._panningDivContainer.setAttribute("role", "group"); - this._panningDivContainer.setAttribute("aria-label", strings.panningContainerAriaLabel); - - this._contentDiv.appendChild(this._panningDivContainer); - this._flipviewDiv.appendChild(this._contentDiv); - - this._panningDiv.style.width = "100%"; - this._panningDiv.style.height = "100%"; - this._setupOrientation(); - function setUpButton(button) { - button.setAttribute("aria-hidden", true); - button.style.visibility = "hidden"; - button.style.opacity = 0.0; - button.tabIndex = -1; - button.style.zIndex = 1000; - } - setUpButton(this._prevButton); - setUpButton(this._nextButton); - this._prevButton.setAttribute("aria-label", previousButtonLabel); - this._nextButton.setAttribute("aria-label", nextButtonLabel); - this._prevButton.setAttribute("type", "button"); - this._nextButton.setAttribute("type", "button"); - this._panningDivContainer.appendChild(this._panningDiv); - this._contentDiv.appendChild(this._prevButton); - this._contentDiv.appendChild(this._nextButton); - - var that = this; - - this._itemsManagerCallback = { - // Callbacks for itemsManager - inserted: function FlipView_inserted(itemPromise, previousHandle, nextHandle) { - that._itemsManager._itemFromPromise(itemPromise).then(function (element) { - var previous = that._itemsManager._elementFromHandle(previousHandle); - var next = that._itemsManager._elementFromHandle(nextHandle); - that._pageManager.inserted(element, previous, next, true); - }); - }, - - countChanged: function FlipView_countChanged(newCount, oldCount) { - that._pageManager._cachedSize = newCount; - - // Don't fire the datasourcecountchanged event when there is a state transition - if (oldCount !== WinJS.UI.CountResult.unknown) { - that._fireDatasourceCountChangedEvent(); - } - }, - - changed: function FlipView_changed(newElement, oldElement) { - that._pageManager.changed(newElement, oldElement); - }, - - moved: function FlipView_moved(element, prev, next, itemPromise) { - var elementReady = function (element) { - //#DBG _ASSERT(element); - that._pageManager.moved(element, prev, next); - }; - - // If we haven't instantiated this item yet, do so now - if (!element) { - that._itemsManager._itemFromPromise(itemPromise).then(elementReady); - } - else { - elementReady(element); - } - - }, - - removed: function FlipView_removed(element, mirage) { - if (element) { - that._pageManager.removed(element, mirage, true); - } - }, - - knownUpdatesComplete: function FlipView_knownUpdatesComplete() { - }, - - beginNotifications: function FlipView_beginNotifications() { - that._cancelAnimation(); - that._pageManager.notificationsStarted(); - }, - - endNotifications: function FlipView_endNotifications() { - that._pageManager.notificationsEnded(); - }, - - itemAvailable: function FlipView_itemAvailable(real, placeholder) { - that._pageManager.itemRetrieved(real, placeholder); - }, - - reload: function FlipView_reload() { - that._pageManager.reload(); - } - }; - - if (this._dataSource) { - this._itemsManager = thisWinUI._createItemsManager(this._dataSource, this._itemRenderer, this._itemsManagerCallback, { - ownerElement: this._flipviewDiv - }); - } - - this._pageManager = new thisWinUI._FlipPageManager(this._flipviewDiv, this._panningDiv, this._panningDivContainer, this._itemsManager, itemSpacing, - { - hidePreviousButton: function () { - that._hasPrevContent = false; - that._fadeOutButton("prev"); - that._prevButton.setAttribute("aria-hidden", true); - }, - - showPreviousButton: function () { - that._hasPrevContent = true; - that._fadeInButton("prev"); - that._prevButton.setAttribute("aria-hidden", false); - }, - - hideNextButton: function () { - that._hasNextContent = false; - that._fadeOutButton("next"); - that._nextButton.setAttribute("aria-hidden", true); - }, - - showNextButton: function () { - that._hasNextContent = true; - that._fadeInButton("next"); - that._nextButton.setAttribute("aria-hidden", false); - } - }); - - this._pageManager.initialize(initialIndex, this._horizontal); - - this._dataSource.getCount().then(function (count) { - that._pageManager._cachedSize = count; - }); - - this._prevButton.addEventListener("click", function () { - that.previous(); - }, false); - - this._nextButton.addEventListener("click", function () { - that.next(); - }, false); - - new MutationObserver(flipViewPropertyChanged).observe(this._flipviewDiv, { attributes: true, attributeFilter: ["dir", "style"] }); - this._cachedStyleDir = this._flipviewDiv.style.direction; - - this._flipviewDiv.addEventListener("mselementresize", flipviewResized); - - this._contentDiv.addEventListener("mouseleave", function () { - that._mouseInViewport = false; - }, false); - - var PT_TOUCH = MSPointerEvent.MSPOINTER_TYPE_TOUCH || "touch"; - function handleShowButtons(e) { - if (e.pointerType !== PT_TOUCH) { - that._touchInteraction = false; - if (e.screenX === that._lastMouseX && e.screenY === that._lastMouseY) { - return; - } - that._lastMouseX = e.screenX; - that._lastMouseY = e.screenY; - that._mouseInViewport = true; - that._fadeInButton("prev"); - that._fadeInButton("next"); - that._fadeOutButtons(); - } - } - - this._contentDiv.addEventListener("pointermove", handleShowButtons, false); - - this._contentDiv.addEventListener("pointerdown", function (e) { - if (e.pointerType === PT_TOUCH) { - that._mouseInViewport = false; - that._touchInteraction = true; - that._fadeOutButtons(true); - } else { - that._touchInteraction = false; - if (!that._isInteractive(e.srcElement)) { - // Disable the default behavior of the mouse wheel button to avoid auto-scroll - if ((e.buttons & 4) !== 0) { - e.stopPropagation(); - e.preventDefault(); - } - } - } - }, false); - - this._contentDiv.addEventListener("pointerup", function (e) { - if (e.pointerType !== PT_TOUCH) { - that._touchInteraction = false; - } - }, false); - - this._panningDivContainer.addEventListener("scroll", function () { - that._scrollPosChanged(); - }, false); - - this._panningDiv.addEventListener("deactivate", function (event) { - if (!that._touchInteraction) { - that._fadeOutButtons(); - } - }, true); - - // When an element is removed and inserted, its scroll position gets reset to 0 (and no onscroll event is generated). This is a major problem - // for the flipview thanks to the fact that we 1) Do a lot of inserts/removes of child elements, and 2) Depend on our scroll location being right to - // display the right stuff. The page manager preserves scroll location. When a flipview element is reinserted, it'll fire DOMNodeInserted and we can reset - // its scroll location there. - // This event handler won't be hit in IE8. - this._flipviewDiv.addEventListener("DOMNodeInserted", function (event) { - if (event.target === that._flipviewDiv) { - that._pageManager.resized(); - } - }, false); - - this._flipviewDiv.addEventListener("keydown", function (event) { - function isInteractive(element) { - if (element.parentNode) { - var matches = element.parentNode.querySelectorAll(".win-interactive, .win-interactive *"); - for (var i = 0, len = matches.length; i < len; i++) { - if (matches[i] === element) { - return true; - } - } - } - return false; - } - var cancelBubbleIfHandled = true; - if (!that._isInteractive(event.srcElement)) { - var Key = utilities.Key, - handled = false; - if (that._horizontal) { - switch (event.keyCode) { - case Key.leftArrow: - (that._rtl ? that.next() : that.previous()); - handled = true; - break; - - case Key.pageUp: - that.previous(); - handled = true; - break; - - case Key.rightArrow: - (that._rtl ? that.previous() : that.next()); - handled = true; - break; - - case Key.pageDown: - that.next(); - handled = true; - break; - - // Prevent scrolling pixel by pixel, but let the event bubble up - case Key.upArrow: - case Key.downArrow: - handled = true; - cancelBubbleIfHandled = false; - break; - } - } else { - switch (event.keyCode) { - case Key.upArrow: - case Key.pageUp: - that.previous(); - handled = true; - break; - - case Key.downArrow: - case Key.pageDown: - that.next(); - handled = true; - break; - - case Key.space: - handled = true; - break; - } - } - - switch (event.keyCode) { - case Key.home: - that.currentPage = 0; - handled = true; - break; - - case Key.end: - if (that._pageManager._cachedSize > 0) { - that.currentPage = that._pageManager._cachedSize - 1; - } - handled = true; - break; - } - - if (handled) { - event.preventDefault(); - event.cancelBubble = cancelBubbleIfHandled; - return true; - } - } - }, false); - }, - - _windowWheelHandler: function FlipView_windowWheelHandler(ev) { - // When you are using the mouse wheel to scroll a horizontal area such as a WinJS.UI.Hub and one of the sections - // has a WinJS.UI.FlipView you may get stuck on that item. This logic is to allow a scroll event to skip the flipview's - // overflow scroll div and instead go to the parent scroller. We only skip the scroll wheel event for a fixed amount of time - var wheelWithinFlipper = ev.srcElement && (this._flipviewDiv.contains(ev.srcElement) || this._flipviewDiv === ev.srcElement); - var that = this; - var now = performance.now(); - var withinAvoidTime = this._avoidTrappingTime > now; - - if (!wheelWithinFlipper || withinAvoidTime) { - this._avoidTrappingTime = now + avoidTrapDelay; - } - - if (wheelWithinFlipper && withinAvoidTime) { - this._panningDivContainer.style["overflow-x"] = "hidden"; - this._panningDivContainer.style["overflow-y"] = "hidden"; - setImmediate(function () { - // Avoid being stuck between items - that._pageManager._ensureCentered(); - - if (that._horizontal) { - that._panningDivContainer.style["overflow-x"] = "scroll"; - that._panningDivContainer.style["overflow-y"] = "hidden"; - } else { - that._panningDivContainer.style["overflow-y"] = "scroll"; - that._panningDivContainer.style["overflow-x"] = "hidden"; - } - }); - } - }, - - _isInteractive: function FlipView_isInteractive(element) { - if (element.parentNode) { - var matches = element.parentNode.querySelectorAll(".win-interactive, .win-interactive *"); - for (var i = 0, len = matches.length; i < len; i++) { - if (matches[i] === element) { - return true; - } - } - } - return false; - }, - - _refreshHandler: function FlipView_refreshHandler() { - var dataSource = this._dataSourceAfterRefresh || this._dataSource, - renderer = this._itemRendererAfterRefresh || this._itemRenderer, - initialIndex = this._indexAfterRefresh || 0; - this._setDatasource(dataSource, renderer, initialIndex); - this._dataSourceAfterRefresh = null; - this._itemRendererAfterRefresh = null; - this._indexAfterRefresh = 0; - this._refreshTimer = false; - }, - - _refresh: function FlipView_refresh() { - if (!this._refreshTimer) { - var that = this; - this._refreshTimer = true; - // Batch calls to _refresh - Scheduler.schedule(function FlipView_refreshHandler() { - if (that._refreshTimer && !that._disposed) { - that._refreshHandler(); - } - }, Scheduler.Priority.high, null, "WinJS.UI.FlipView._refreshHandler"); - } - }, - - _getItemRenderer: function FlipView_getItemRenderer(itemTemplate) { - var itemRenderer = null; - if (typeof itemTemplate === "function") { - var itemPromise = new WinJS.Promise(function (c, e, p) { }); - var itemTemplateResult = itemTemplate(itemPromise); - if (itemTemplateResult.element) { - if (typeof itemTemplateResult.element === "object" && typeof itemTemplateResult.element.then === "function") { - // This renderer returns a promise to an element - itemRenderer = function (itemPromise) { - var elementRoot = document.createElement("div"); - elementRoot.className = "win-template"; - WinJS.Utilities.markDisposable(elementRoot); - return { - element: elementRoot, - renderComplete: itemTemplate(itemPromise).element.then(function (element) { - elementRoot.appendChild(element); - }) - }; - }; - } else { - // This renderer already returns a placeholder - itemRenderer = itemTemplate; - } - } else { - // Return a renderer that has return a placeholder - itemRenderer = function (itemPromise) { - var elementRoot = document.createElement("div"); - elementRoot.className = "win-template"; - WinJS.Utilities.markDisposable(elementRoot); - // The pagecompleted event relies on this elementRoot - // to ensure that we are still looking at the same - // item after the render completes. - return { - element: elementRoot, - renderComplete: itemPromise.then(function (item) { - return WinJS.Promise.as(itemTemplate(itemPromise)).then(function (element) { - elementRoot.appendChild(element); - }); - }) - }; - } - }; - } else if (typeof itemTemplate === "object") { - itemRenderer = itemTemplate.renderItem; - } - return itemRenderer; - }, - - _navigate: function FlipView_navigate(goForward, cancelAnimationCallback) { - if (WinJS.validation && this._refreshTimer) { - throw new WinJS.ErrorFromName("WinJS.UI.FlipView.NavigationDuringStateChange", strings.navigationDuringStateChange); - } - - if (!this._animating) { - this._animatingForward = goForward; - } - this._goForward = goForward; - - if (this._animating && !this._cancelAnimation()) { - return false; - } - var that = this; - var customAnimation = (goForward ? this._nextAnimation : this._prevAnimation), - animation = (customAnimation ? customAnimation : this._defaultAnimation.bind(this)), - completionCallback = function (goForward) { that._completeNavigation(goForward); }, - elements = this._pageManager.startAnimatedNavigation(goForward, cancelAnimationCallback, completionCallback); - if (elements) { - this._animationsStarted(); - var outgoingElement = elements.outgoing.pageRoot, - incomingElement = elements.incoming.pageRoot; - this._contentDiv.appendChild(outgoingElement); - this._contentDiv.appendChild(incomingElement); - - this._completeNavigationPending = true; - animation(outgoingElement, incomingElement).then(function () { - if (that._completeNavigationPending) { - completionCallback(that._goForward); - } - }).done(); - return true; - } else { - return false; - } - }, - - _cancelDefaultAnimation: function FlipView_cancelDefaultAnimation(outgoingElement, incomingElement) { - // Cancel the fadeOut animation - outgoingElement.style.opacity = 0; - - // Cancel the enterContent animation - incomingElement.style.animationName = ""; - incomingElement.style.opacity = 1; - }, - - _cancelAnimation: function FlipView_cancelAnimation() { - if (this._pageManager._navigationAnimationRecord && - this._pageManager._navigationAnimationRecord.completionCallback) { - - var cancelCallback = this._pageManager._navigationAnimationRecord.cancelAnimationCallback; - if (cancelCallback) { - cancelCallback = cancelCallback.bind(this); - } - - if (this._pageManager._navigationAnimationRecord && this._pageManager._navigationAnimationRecord.elementContainers) { - var outgoingPage = this._pageManager._navigationAnimationRecord.elementContainers[0], - incomingPage = this._pageManager._navigationAnimationRecord.elementContainers[1], - outgoingElement = outgoingPage.pageRoot, - incomingElement = incomingPage.pageRoot; - - // Invoke the function that will cancel the animation - if (cancelCallback) { - cancelCallback(outgoingElement, incomingElement); - } - - // Invoke the completion function after cancelling the animation - this._pageManager._navigationAnimationRecord.completionCallback(this._animatingForward); - - return true; - } - } - return false; - }, - - _completeNavigation: function FlipView_completeNavigation(goForward) { - if (this._disposed) { - return; - } - - this._pageManager._resizing = false; - if (this._pageManager._navigationAnimationRecord && - this._pageManager._navigationAnimationRecord.elementContainers) { - - var outgoingPage = this._pageManager._navigationAnimationRecord.elementContainers[0], - incomingPage = this._pageManager._navigationAnimationRecord.elementContainers[1], - outgoingElement = outgoingPage.pageRoot, - incomingElement = incomingPage.pageRoot; - - if (outgoingElement.parentNode) { - outgoingElement.parentNode.removeChild(outgoingElement); - } - if (incomingElement.parentNode) { - incomingElement.parentNode.removeChild(incomingElement); - } - this._pageManager.endAnimatedNavigation(goForward, outgoingPage, incomingPage); - this._fadeOutButtons(); - this._scrollPosChanged(); - this._pageManager._ensureCentered(true); - this._animationsFinished(); - } - this._completeNavigationPending = false; - }, - - _completeJump: function FlipView_completeJump() { - if (this._disposed) { - return; - } - - this._pageManager._resizing = false; - if (this._pageManager._navigationAnimationRecord && - this._pageManager._navigationAnimationRecord.elementContainers) { - - var outgoingPage = this._pageManager._navigationAnimationRecord.elementContainers[0], - incomingPage = this._pageManager._navigationAnimationRecord.elementContainers[1], - outgoingElement = outgoingPage.pageRoot, - incomingElement = incomingPage.pageRoot; - - if (outgoingElement.parentNode) { - outgoingElement.parentNode.removeChild(outgoingElement); - } - if (incomingElement.parentNode) { - incomingElement.parentNode.removeChild(incomingElement); - } - - this._pageManager.endAnimatedJump(outgoingPage, incomingPage); - this._animationsFinished(); - } - this._completeJumpPending = false; - }, - - _resize: function FlipView_resize() { - this._pageManager.resized(); - }, - - _setCurrentIndex: function FlipView_setCurrentIndex(index) { - return this._pageManager.jumpToIndex(index); - }, - - _getCurrentIndex: function FlipView_getCurrentIndex() { - return this._pageManager.currentIndex(); - }, - - _setDatasource: function FlipView_setDatasource(source, template, index) { - if (this._animating) { - this._cancelAnimation(); - } - - var initialIndex = 0; - if (index !== undefined) { - initialIndex = index; - } - this._dataSource = source; - this._itemRenderer = template; - var oldItemsManager = this._itemsManager; - this._itemsManager = thisWinUI._createItemsManager(this._dataSource, this._itemRenderer, this._itemsManagerCallback, { - ownerElement: this._flipviewDiv - }); - this._dataSource = this._itemsManager.dataSource; - - var that = this; - this._dataSource.getCount().then(function (count) { - that._pageManager._cachedSize = count; - }); - this._pageManager.setNewItemsManager(this._itemsManager, initialIndex); - oldItemsManager && oldItemsManager.release(); - }, - - _fireDatasourceCountChangedEvent: function FlipView_fireDatasourceCountChangedEvent() { - var that = this; - Scheduler.schedule(function FlipView_dispatchDataSourceCountChangedEvent() { - var event = document.createEvent("Event"); - event.initEvent(thisWinUI.FlipView.datasourceCountChangedEvent, true, true); - msWriteProfilerMark("WinJS.UI.FlipView:dataSourceCountChangedEvent,info"); - that._flipviewDiv.dispatchEvent(event); - }, Scheduler.Priority.normal, null, "WinJS.UI.FlipView._dispatchDataSourceCountChangedEvent"); - }, - - _scrollPosChanged: function FlipView_scrollPosChanged() { - this._pageManager.scrollPosChanged(); - }, - - _axisAsString: function FlipView_axisAsString() { - return (this._horizontal ? "horizontal" : "vertical"); - }, - - _setupOrientation: function FlipView_setupOrientation() { - if (this._horizontal) { - this._panningDivContainer.style["overflow-x"] = "scroll"; - this._panningDivContainer.style["overflow-y"] = "hidden"; - var rtl = window.getComputedStyle(this._flipviewDiv, null).direction === "rtl"; - this._rtl = rtl; - if (rtl) { - this._prevButton.className = navButtonClass + " " + navButtonRightClass; - this._nextButton.className = navButtonClass + " " + navButtonLeftClass; - } else { - this._prevButton.className = navButtonClass + " " + navButtonLeftClass; - this._nextButton.className = navButtonClass + " " + navButtonRightClass; - } - this._prevButton.innerHTML = (rtl ? rightArrowGlyph : leftArrowGlyph); - this._nextButton.innerHTML = (rtl ? leftArrowGlyph : rightArrowGlyph); - } else { - this._panningDivContainer.style["overflow-y"] = "scroll"; - this._panningDivContainer.style["overflow-x"] = "hidden"; - this._prevButton.className = navButtonClass + " " + navButtonTopClass; - this._nextButton.className = navButtonClass + " " + navButtonBottomClass; - this._prevButton.innerHTML = topArrowGlyph; - this._nextButton.innerHTML = bottomArrowGlyph; - } - this._panningDivContainer.style["-ms-overflow-style"] = "none"; - }, - - _fadeInButton: function FlipView_fadeInButton(button, forceShow) { - if (this._mouseInViewport || forceShow) { - if (button === "next" && this._hasNextContent) { - if (this._nextButtonAnimation) { - this._nextButtonAnimation.cancel(); - this._nextButtonAnimation = null; - } - - this._nextButton.style.visibility = "visible"; - this._nextButtonAnimation = this._fadeInFromCurrentValue(this._nextButton); - } else if (button === "prev" && this._hasPrevContent) { - if (this._prevButtonAnimation) { - this._prevButtonAnimation.cancel(); - this._prevButtonAnimation = null; - } - - this._prevButton.style.visibility = "visible"; - this._prevButtonAnimation = this._fadeInFromCurrentValue(this._prevButton); - } - } - }, - - _fadeOutButton: function FlipView_fadeOutButton(button) { - var that = this; - if (button === "next") { - if (this._nextButtonAnimation) { - this._nextButtonAnimation.cancel(); - this._nextButtonAnimation = null; - } - - this._nextButtonAnimation = animation.fadeOut(this._nextButton). - then(function () { - that._nextButton.style.visibility = "hidden"; - }); - return this._nextButtonAnimation; - } else { - if (this._prevButtonAnimation) { - this._prevButtonAnimation.cancel(); - this._prevButtonAnimation = null; - } - - this._prevButtonAnimation = animation.fadeOut(this._prevButton). - then(function () { - that._prevButton.style.visibility = "hidden"; - }); - return this._prevButtonAnimation; - } - }, - - _fadeOutButtons: function FlipView_fadeOutButtons(immediately) { - if (this._buttonFadePromise) { - this._buttonFadePromise.cancel(); - this._buttonFadePromise = null; - } - - var that = this; - this._buttonFadePromise = (immediately ? WinJS.Promise.wrap() : WinJS.Promise.timeout(buttonFadeDelay)).then(function () { - that._fadeOutButton("prev"); - that._fadeOutButton("next"); - that._buttonFadePromise = null; - }); - }, - - _animationsStarted: function FlipView_animationsStarted() { - this._animating = true; - }, - - _animationsFinished: function FlipView_animationsFinished() { - this._animating = false; - }, - - _defaultAnimation: function FlipView_defaultAnimation(curr, next) { - var incomingPageMove = {}; - next.style.left = "0px"; - next.style.top = "0px"; - next.style.opacity = 0.0; - var pageDirection = ((curr.itemIndex > next.itemIndex) ? -animationMoveDelta : animationMoveDelta); - incomingPageMove.left = (this._horizontal ? (this._rtl ? -pageDirection : pageDirection) : 0) + "px"; - incomingPageMove.top = (this._horizontal ? 0 : pageDirection) + "px"; - var fadeOutPromise = animation.fadeOut(curr), - enterContentPromise = animation.enterContent(next, [incomingPageMove], { mechanism: "transition" }); - return WinJS.Promise.join([fadeOutPromise, enterContentPromise]); - }, - - _fadeInFromCurrentValue: function FlipView_fadeInFromCurrentValue(shown) { - // Intentionally not using the PVL fadeIn animation because we don't want - // to start always from 0 in some cases - return thisWinUI.executeTransition( - shown, - { - property: "opacity", - delay: 0, - duration: 167, - timing: "linear", - to: 1 - }); - } - }); - - // Statics / Events - - FlipView.datasourceCountChangedEvent = "datasourcecountchanged"; - FlipView.pageVisibilityChangedEvent = "pagevisibilitychanged"; - FlipView.pageSelectedEvent = "pageselected"; - FlipView.pageCompletedEvent = "pagecompleted"; - - WinJS.Class.mix(FlipView, WinJS.Utilities.createEventProperties( - FlipView.datasourceCountChangedEvent, - FlipView.pageVisibilityChangedEvent, - FlipView.pageSelectedEvent, - FlipView.pageCompletedEvent)); - WinJS.Class.mix(FlipView, WinJS.UI.DOMEventMixin); - - return FlipView; - }) - }); - -})(WinJS); - - -(function flipperPageManagerInit(WinJS) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - - // Definition of our private utility - _FlipPageManager: WinJS.Namespace._lazy(function () { - var thisWinUI = WinJS.UI; - - // Utilities are private and global pointer will be deleted so we need to cache it locally - var utilities = WinJS.Utilities; - - var Scheduler = WinJS.Utilities.Scheduler; - - var animations = WinJS.UI.Animation; - - var leftBufferAmount = 50, - itemSelectedEventDelay = 250; - - var strings = { - get badCurrentPage() { return WinJS.Resources._getWinJSString("ui/badCurrentPage").value; } - }; - - function isFlipper(element) { - var control = element.winControl; - if (control && control instanceof WinJS.UI.FlipView) { - return true; - } - - return false; - } - - function flipperPropertyChanged(list) { - list.forEach(function (record) { - var element = record.target; - if (element.winControl && element.tabIndex >= 0) { - element.winControl._pageManager._updateTabIndex(element.tabIndex); - element.tabIndex = -1; - } - var that = element.winControl; - if (that && that instanceof WinJS.UI.FlipView) { - var dirChanged = false; - if (record.attributeName === "dir") { - dirChanged = true; - } else if (record.attributeName === "style") { - dirChanged = (that._cachedStyleDir != element.style.direction); - } - if (dirChanged) { - that._cachedStyleDir = element.style.direction; - that._pageManager._rtl = window.getComputedStyle(that._pageManager._flipperDiv, null).direction === "rtl"; - that._pageManager.resized(); - } - } - }); - } - - var _FlipPageManager = WinJS.Class.define(function _FlipPageManager_ctor(flipperDiv, panningDiv, panningDivContainer, itemsManager, itemSpacing, buttonVisibilityHandler) { - // Construction - this._visibleElements = []; - this._flipperDiv = flipperDiv; - this._panningDiv = panningDiv; - this._panningDivContainer = panningDivContainer; - this._buttonVisibilityHandler = buttonVisibilityHandler; - this._currentPage = null; - this._rtl = window.getComputedStyle(this._flipperDiv, null).direction === "rtl"; - this._itemsManager = itemsManager; - this._itemSpacing = itemSpacing; - this._tabIndex = (flipperDiv.tabIndex !== undefined && flipperDiv.tabIndex >= 0 ? flipperDiv.tabIndex : 0); - flipperDiv.tabIndex = -1; - this._tabManager = new WinJS.UI.TabContainer(this._panningDivContainer); - this._tabManager.tabIndex = this._tabIndex; - this._lastSelectedPage = null; - this._lastSelectedElement = null; - this._bufferSize = thisWinUI._FlipPageManager.flipPageBufferCount; - this._cachedSize = -1; - - var that = this; - this._panningDiv.addEventListener("keydown", function (event) { - if (that._blockTabs && event.keyCode === utilities.Key.tab) { - event.stopImmediatePropagation(); - event.preventDefault(); - } - }, true); - this._flipperDiv.addEventListener("focus", function (event) { - if (event.srcElement === that._flipperDiv) { - if (that._currentPage.element) { - try { - that._currentPage.element.setActive(); - } catch (e) { } - } - } - }, false); - new MutationObserver(flipperPropertyChanged).observe(this._flipperDiv, { attributes: true, attributeFilter: ["dir", "style", "tabindex"] }); - this._cachedStyleDir = this._flipperDiv.style.direction; - this._panningDiv.addEventListener("activate", function (event) { - that._hasFocus = true; - }, true); - this._panningDiv.addEventListener("deactivate", function (event) { - that._hasFocus = false; - }, true); - this._panningDivContainer.addEventListener("MSManipulationStateChanged", function (event) { - that._manipulationState = event.currentState; - if (event.currentState === 0 && event.srcElement === that._panningDivContainer) { - that._itemSettledOn(); - that._ensureCentered(); - } - }, true); - }, { - // Public Methods - - initialize: function (initialIndex, horizontal) { - var currPage = null; - // Every call to offsetWidth/offsetHeight causes an switch from Script to Layout which affects - // the performance of the control. The values will be cached and will be updated when a resize occurs. - this._panningDivContainerOffsetWidth = this._panningDivContainer.offsetWidth; - this._panningDivContainerOffsetHeight = this._panningDivContainer.offsetHeight; - - this._horizontal = horizontal; - if (!this._currentPage) { - this._bufferAriaStartMarker = document.createElement("div"); - this._bufferAriaStartMarker.id = this._bufferAriaStartMarker.uniqueID; - this._panningDiv.appendChild(this._bufferAriaStartMarker); - - this._currentPage = this._createFlipPage(null, this); - currPage = this._currentPage; - this._panningDiv.appendChild(currPage.pageRoot); - - // flipPageBufferCount is added here twice. - // Once for the buffer prior to the current item, and once for the buffer ahead of the current item. - var pagesToInit = 2 * this._bufferSize; - for (var i = 0; i < pagesToInit; i++) { - currPage = this._createFlipPage(currPage, this); - this._panningDiv.appendChild(currPage.pageRoot); - } - - this._bufferAriaEndMarker = document.createElement("div"); - this._bufferAriaEndMarker.id = this._bufferAriaEndMarker.uniqueID; - this._panningDiv.appendChild(this._bufferAriaEndMarker); - } - - this._prevMarker = this._currentPage.prev.prev; - - if (this._itemsManager) { - this.setNewItemsManager(this._itemsManager, initialIndex); - } - }, - - dispose: function () { - var curPage = this._currentPage; - - var tmpPage = curPage; - do { - WinJS.Utilities._disposeElement(tmpPage.element); - tmpPage = tmpPage.next; - } while (tmpPage !== curPage); - }, - - setOrientation: function (horizontal) { - if (this._notificationsEndedSignal) { - var that = this; - this._notificationsEndedSignal.promise.done(function () { - that._notificationsEndedSignal = null; - that.setOrientation(horizontal); - }); - return; - } - - if (horizontal !== this._horizontal) { - this._isOrientationChanging = true; - this._horizontal = horizontal; - this._forEachPage(function (curr) { - var currStyle = curr.pageRoot.style; - currStyle.left = "0px"; - currStyle.top = "0px"; - }); - this._panningDivContainer.scrollLeft = 0; - this._panningDivContainer.scrollTop = 0; - var containerStyle = this._panningDivContainer.style; - containerStyle["overflow-x"] = "hidden"; - containerStyle["overflow-y"] = "hidden"; - - var that = this; - requestAnimationFrame(function () { - that._isOrientationChanging = false; - containerStyle["overflow-x"] = that._horizontal ? "scroll" : "hidden"; - containerStyle["overflow-y"] = that._horizontal ? "hidden" : "scroll"; - that._ensureCentered(); - }); - } - }, - - resetState: function (initialIndex) { - this._writeProfilerMark("WinJS.UI.FlipView:resetState,info"); - if (initialIndex !== 0) { - var indexValid = this.jumpToIndex(initialIndex, true); - if (!indexValid && WinJS.validation) { - throw new WinJS.ErrorFromName("WinJS.UI.FlipView.BadCurrentPage", strings.badCurrentPage); - } - return indexValid; - } else { - WinJS.Utilities.disposeSubTree(this._flipperDiv); - this._resetBuffer(null, true); - var that = this; - var work = WinJS.Promise.wrap(true); - if (this._itemsManager) { - work = that._itemsManager._firstItem().then(function (e) { - that._currentPage.setElement(e); - return that._fetchPreviousItems(true). - then(function () { - return that._fetchNextItems(); - }).then(function () { - that._setButtonStates(); - }); - }); - } - return work.then(function () { - that._tabManager.childFocus = that._currentPage.element; - that._ensureCentered(); - that._itemSettledOn(); - }); - } - }, - - setNewItemsManager: function (manager, initialIndex) { - this._itemsManager = manager; - var that = this; - return this.resetState(initialIndex).then(function () { - // resetState already configures the tabManager, calls _ensureCentered and _itemSettledOn when the initial index is 0 - if (initialIndex !== 0) { - that._tabManager.childFocus = that._currentPage.element; - that._ensureCentered(); - that._itemSettledOn(); - } - }); - }, - - currentIndex: function () { - if (!this._itemsManager) { - return 0; - } - var index = 0; - var element = (this._navigationAnimationRecord ? this._navigationAnimationRecord.newCurrentElement : this._currentPage.element); - if (element) { - index = this._getElementIndex(element); - } - return index; - }, - - resetScrollPos: function () { - this._ensureCentered(); - }, - - scrollPosChanged: function () { - if (!this._itemsManager || !this._currentPage.element || this._isOrientationChanging) { - return; - } - - var newPos = this._viewportStart(), - bufferEnd = (this._lastScrollPos > newPos ? this._getTailOfBuffer() : this._getHeadOfBuffer()); - - if (newPos === this._lastScrollPos) { - return; - } - - while (this._currentPage.element && this._itemStart(this._currentPage) > newPos && this._currentPage.prev.element) { - this._currentPage = this._currentPage.prev; - this._fetchOnePrevious(bufferEnd.prev); - bufferEnd = bufferEnd.prev; - } - - while (this._currentPage.element && this._itemEnd(this._currentPage) <= newPos && this._currentPage.next.element) { - this._currentPage = this._currentPage.next; - this._fetchOneNext(bufferEnd.next); - bufferEnd = bufferEnd.next; - } - this._setButtonStates(); - this._checkElementVisibility(false); - this._blockTabs = true; - this._lastScrollPos = newPos; - this._tabManager.childFocus = this._currentPage.pageRoot; - this._setListEnds(); - - if (!this._manipulationState && this._viewportOnItemStart()) { - // Setup a timeout to invoke _itemSettledOn in cases where the scroll position is changed, and the control - // does not know when it has settled on an item (e.g. 1-finger swipe with narrator touch). - this._currentPage.element.setAttribute("aria-setsize", this._cachedSize); - this._currentPage.element.setAttribute("aria-posinset", this.currentIndex() + 1); - this._timeoutPageSelection(); - } - }, - - itemRetrieved: function (real, placeholder) { - var that = this; - this._forEachPage(function (curr) { - if (curr.element === placeholder) { - if (curr === that._currentPage || curr === that._currentPage.next) { - that._changeFlipPage(curr, placeholder, real); - } else { - curr.setElement(real, true); - } - return true; - } - }); - if (this._navigationAnimationRecord && this._navigationAnimationRecord.elementContainers) { - var animatingElements = this._navigationAnimationRecord.elementContainers; - for (var i = 0, len = animatingElements.length; i < len; i++) { - if (animatingElements[i].element === placeholder) { - that._changeFlipPage(animatingElements[i], placeholder, real); - animatingElements[i].element = real; - } - } - } - this._checkElementVisibility(false); - }, - - resized: function () { - this._panningDivContainerOffsetWidth = this._panningDivContainer.offsetWidth; - this._panningDivContainerOffsetHeight = this._panningDivContainer.offsetHeight; - var that = this; - this._forEachPage(function (curr) { - curr.pageRoot.style.width = that._panningDivContainerOffsetWidth + "px"; - curr.pageRoot.style.height = that._panningDivContainerOffsetHeight + "px"; - }); - - // Call _ensureCentered to adjust all the width/height of the pages in the buffer - this._ensureCentered(); - this._writeProfilerMark("WinJS.UI.FlipView:resize,StopTM"); - }, - - jumpToIndex: function (index, forceJump) { - // If we force jumping to an index, we are not interested in making sure that there is distance - // between the current and the new index. - if (!forceJump) { - if (!this._itemsManager || !this._currentPage.element || index < 0) { - return WinJS.Promise.wrap(false); - } - - // If we have to keep our pages in memory, we need to iterate through every single item from our current position to the desired target - var i, - currIndex = this._getElementIndex(this._currentPage.element), - distance = Math.abs(index - currIndex); - - if (distance === 0) { - return WinJS.Promise.wrap(false); - } - } - - var tail = WinJS.Promise.wrap(true); - var that = this; - - tail = tail.then(function () { - var itemPromise = that._itemsManager._itemPromiseAtIndex(index); - return WinJS.Promise.join({ - element: that._itemsManager._itemFromItemPromise(itemPromise), - item: itemPromise - }).then(function (v) { - var elementAtIndex = v.element; - - // Reset the buffer regardless of whether we have elementAtIndex or not - that._resetBuffer(elementAtIndex, forceJump); - - if (!elementAtIndex) { - return false; - } - - that._currentPage.setElement(elementAtIndex); - return that._fetchNextItems(). - then(function () { - return that._fetchPreviousItems(true); - }). - then(function () { - return true; - }); - }); - }); - tail = tail.then(function (v) { - that._setButtonStates(); - return v; - }); - - return tail; - }, - - startAnimatedNavigation: function (goForward, cancelAnimationCallback, completionCallback) { - this._writeProfilerMark("WinJS.UI.FlipView:startAnimatedNavigation,info"); - if (this._currentPage.element) { - var outgoingPage = this._currentPage, - incomingPage = (goForward ? this._currentPage.next : this._currentPage.prev); - - if (incomingPage.element) { - if (this._hasFocus) { - try { - // Give focus to the panning div ONLY if anything inside the flipview control currently has - // focus; otherwise, it will be lost when the current page is animated during the navigation. - this._panningDiv.setActive(); - } catch (e) { } - } - this._navigationAnimationRecord = {}; - this._navigationAnimationRecord.goForward = goForward; - this._navigationAnimationRecord.cancelAnimationCallback = cancelAnimationCallback; - this._navigationAnimationRecord.completionCallback = completionCallback; - this._navigationAnimationRecord.oldCurrentPage = outgoingPage; - this._navigationAnimationRecord.newCurrentPage = incomingPage; - var outgoingElement = outgoingPage.element; - var incomingElement = incomingPage.element; - this._navigationAnimationRecord.newCurrentElement = incomingElement; - - // When a page element is animated during a navigation, it is temporarily appended on a different container during the animation (see _createDiscardablePage). - // However, updates in the data source can happen (change, remove, insert, etc) during the animation affecting the element that is being animated. - // Therefore, the page object also maintains the elementUniqueID, and the functions that deal with re-building the internal buffer (shifting/remove/etc) - // do all the comparissons, based on the page.elementUniqueID that way even if the element of the page is being animated, we are able to restore/discard it - // into the internal buffer back in the correct place. - outgoingPage.setElement(null, true); - outgoingPage.elementUniqueID = outgoingElement.uniqueID; - incomingPage.setElement(null, true); - incomingPage.elementUniqueID = incomingElement.uniqueID; - - var outgoingFlipPage = this._createDiscardablePage(outgoingElement), - incomingFlipPage = this._createDiscardablePage(incomingElement); - - outgoingFlipPage.pageRoot.itemIndex = this._getElementIndex(outgoingElement); - incomingFlipPage.pageRoot.itemIndex = outgoingFlipPage.pageRoot.itemIndex + (goForward ? 1 : -1); - outgoingFlipPage.pageRoot.style.position = "absolute"; - incomingFlipPage.pageRoot.style.position = "absolute"; - outgoingFlipPage.pageRoot.style.zIndex = 1; - incomingFlipPage.pageRoot.style.zIndex = 2; - this._itemStart(outgoingFlipPage, 0, 0); - this._itemStart(incomingFlipPage, 0, 0); - this._blockTabs = true; - this._visibleElements.push(incomingElement); - this._announceElementVisible(incomingElement); - this._navigationAnimationRecord.elementContainers = [outgoingFlipPage, incomingFlipPage]; - return { - outgoing: outgoingFlipPage, - incoming: incomingFlipPage - }; - } - } - return null; - }, - - endAnimatedNavigation: function (goForward, outgoing, incoming) { - this._writeProfilerMark("WinJS.UI.FlipView:endAnimatedNavigation,info"); - if (this._navigationAnimationRecord && - this._navigationAnimationRecord.oldCurrentPage && - this._navigationAnimationRecord.newCurrentPage) { - var outgoingRemoved = this._restoreAnimatedElement(this._navigationAnimationRecord.oldCurrentPage, outgoing); - this._restoreAnimatedElement(this._navigationAnimationRecord.newCurrentPage, incoming); - if (!outgoingRemoved) { - // Advance only when the element in the current page was not removed because if it did, all the pages - // were shifted. - this._viewportStart(this._itemStart(goForward ? this._currentPage.next : this._currentPage.prev)); - } - this._navigationAnimationRecord = null; - this._itemSettledOn(); - } - }, - - startAnimatedJump: function (index, cancelAnimationCallback, completionCallback) { - this._writeProfilerMark("WinJS.UI.FlipView:startAnimatedJump,info"); - if (this._currentPage.element) { - var oldElement = this._currentPage.element; - var oldIndex = this._getElementIndex(oldElement); - var that = this; - - return that.jumpToIndex(index).then(function (v) { - if (!v) { - return null; - } - that._navigationAnimationRecord = {}; - that._navigationAnimationRecord.cancelAnimationCallback = cancelAnimationCallback; - that._navigationAnimationRecord.completionCallback = completionCallback; - that._navigationAnimationRecord.oldCurrentPage = null; - that._forEachPage(function (curr) { - if (curr.element === oldElement) { - that._navigationAnimationRecord.oldCurrentPage = curr; - return true; - } - }); - that._navigationAnimationRecord.newCurrentPage = that._currentPage; - if (that._navigationAnimationRecord.newCurrentPage === that._navigationAnimationRecord.oldCurrentPage) { - return null; - } - var newElement = that._currentPage.element; - that._navigationAnimationRecord.newCurrentElement = newElement; - - // When a page element is animated during a jump, it is temporarily appended on a different container during the animation (see _createDiscardablePage). - // However, updates in the data source can happen (change, remove, insert, etc) during the animation affecting the element that is being animated. - // Therefore, the page object also maintains the elementUniqueID, and the functions that deal with re-building the internal buffer (shifting/remove/etc) - // do all the comparissons, based on the page.elementUniqueID that way even if the element of the page is being animated, we are able to restore/discard it - // into the internal buffer back in the correct place. - that._currentPage.setElement(null, true); - that._currentPage.elementUniqueID = newElement.uniqueID; - - if (that._navigationAnimationRecord.oldCurrentPage) { - that._navigationAnimationRecord.oldCurrentPage.setElement(null, true); - } - - var oldFlipPage = that._createDiscardablePage(oldElement), - newFlipPage = that._createDiscardablePage(newElement); - oldFlipPage.pageRoot.itemIndex = oldIndex; - newFlipPage.pageRoot.itemIndex = index; - oldFlipPage.pageRoot.style.position = "absolute"; - newFlipPage.pageRoot.style.position = "absolute"; - oldFlipPage.pageRoot.style.zIndex = 1; - newFlipPage.pageRoot.style.zIndex = 2; - that._itemStart(oldFlipPage, 0, 0); - that._itemStart(newFlipPage, that._itemSize(that._currentPage), 0); - that._visibleElements.push(newElement); - that._announceElementVisible(newElement); - that._navigationAnimationRecord.elementContainers = [oldFlipPage, newFlipPage]; - that._blockTabs = true; - return { - oldPage: oldFlipPage, - newPage: newFlipPage - }; - }); - } - - return WinJS.Promise.wrap(null); - }, - - endAnimatedJump: function (oldCurr, newCurr) { - this._writeProfilerMark("WinJS.UI.FlipView:endAnimatedJump,info"); - if (this._navigationAnimationRecord.oldCurrentPage) { - this._navigationAnimationRecord.oldCurrentPage.setElement(oldCurr.element, true); - } else { - if (oldCurr.element.parentNode) { - oldCurr.element.parentNode.removeChild(oldCurr.element); - } - } - this._navigationAnimationRecord.newCurrentPage.setElement(newCurr.element, true); - this._navigationAnimationRecord = null; - this._ensureCentered(); - this._itemSettledOn(); - }, - - inserted: function (element, prev, next, animateInsertion) { - this._writeProfilerMark("WinJS.UI.FlipView:inserted,info"); - var curr = this._prevMarker, - passedCurrent = false, - elementSuccessfullyPlaced = false; - - if (animateInsertion) { - this._createAnimationRecord(element.uniqueID, null); - this._getAnimationRecord(element).inserted = true; - } - - if (!prev) { - if (!next) { - this._currentPage.setElement(element); - } else { - while (curr.next !== this._prevMarker && curr.elementUniqueID !== next.uniqueID) { - if (curr === this._currentPage) { - passedCurrent = true; - } - curr = curr.next; - } - - // We never should go past current if prev is null/undefined. - //#DBG _ASSERT(!passedCurrent); - - if (curr.elementUniqueID === next.uniqueID && curr !== this._prevMarker) { - curr.prev.setElement(element); - elementSuccessfullyPlaced = true; - } else { - this._releaseElementIfNotAnimated(element); - } - } - } else { - do { - if (curr === this._currentPage) { - passedCurrent = true; - } - if (curr.elementUniqueID === prev.uniqueID) { - elementSuccessfullyPlaced = true; - var pageShifted = curr, - lastElementMoved = element, - lastElementMovedUniqueID = element.uniqueID, - temp; - if (passedCurrent) { - while (pageShifted.next !== this._prevMarker) { - temp = pageShifted.next.element; - lastElementMovedUniqueID = pageShifted.next.elementUniqueID; - pageShifted.next.setElement(lastElementMoved, true); - if (!lastElementMoved && lastElementMovedUniqueID) { - // Shift the uniqueID of the page manually since its element is being animated. - // This page will not contain the element until the animation completes. - pageShifted.next.elementUniqueID = lastElementMovedUniqueID; - } - lastElementMoved = temp; - pageShifted = pageShifted.next; - } - } else { - if (curr.elementUniqueID === curr.next.elementUniqueID && curr.elementUniqueID) { - pageShifted = curr.next; - } - while (pageShifted.next !== this._prevMarker) { - temp = pageShifted.element; - lastElementMovedUniqueID = pageShifted.elementUniqueID; - pageShifted.setElement(lastElementMoved, true); - if (!lastElementMoved && lastElementMovedUniqueID) { - // Shift the uniqueID of the page manually since its element is being animated. - // This page will not contain the element until the animation completes. - pageShifted.elementUniqueID = lastElementMovedUniqueID; - } - lastElementMoved = temp; - pageShifted = pageShifted.prev; - } - } - if (lastElementMoved) { - var reused = false; - this._forEachPage(function (curr) { - if (lastElementMoved.uniqueID === curr.elementUniqueID) { - reused = true; - return true; - } - }); - if (!reused) { - this._releaseElementIfNotAnimated(lastElementMoved); - } - } - break; - } - curr = curr.next; - } while (curr !== this._prevMarker); - } - - this._getAnimationRecord(element).successfullyMoved = elementSuccessfullyPlaced; - this._setButtonStates(); - }, - - changed: function (newVal, element) { - this._writeProfilerMark("WinJS.UI.FlipView:changed,info"); - var curr = this._prevMarker; - var that = this; - this._forEachPage(function (curr) { - if (curr.elementUniqueID === element.uniqueID) { - var record = that._animationRecords[curr.elementUniqueID]; - record.changed = true; - record.oldElement = element; - record.newElement = newVal; - curr.element = newVal; // We set curr's element field here so that next/prev works, but we won't update the visual until endNotifications - curr.elementUniqueID = newVal.uniqueID; - that._animationRecords[newVal.uniqueID] = record; - return true; - } - }); - - if (this._navigationAnimationRecord && this._navigationAnimationRecord.elementContainers) { - for (var i = 0, len = this._navigationAnimationRecord.elementContainers.length; i < len; i++) { - var page = this._navigationAnimationRecord.elementContainers[i]; - if (page && page.elementUniqueID === element.uniqueID) { - page.element = newVal; - page.elementUniqueID = newVal.uniqueID; - } - } - - var newElement = this._navigationAnimationRecord.newCurrentElement; - if (newElement && newElement.uniqueID === element.uniqueID) { - this._navigationAnimationRecord.newCurrentElement = newVal; - } - } - }, - - moved: function (element, prev, next) { - this._writeProfilerMark("WinJS.UI.FlipView:moved,info"); - var record = this._getAnimationRecord(element); - - if (!record) { - /*#DBG - // When a moved notification is received, and it doesn't have a record, it shouldn't be in the buffer - this._forEachPage(function (curr) { - _ASSERT(curr.element !== element); - }); - #DBG*/ - record = this._createAnimationRecord(element.uniqueID); - } - - record.moved = true; - this.removed(element, false, false); - if (prev || next) { - this.inserted(element, prev, next, false); - } else { - record.successfullyMoved = false; - } - }, - - removed: function (element, mirage, animateRemoval) { - this._writeProfilerMark("WinJS.UI.FlipView:removed,info"); - var that = this; - var prevMarker = this._prevMarker; - var work = WinJS.Promise.wrap(); - - if (mirage) { - var clearNext = false; - this._forEachPage(function (curr) { - if (curr.elementUniqueID === element.uniqueID || clearNext) { - curr.setElement(null, true); - clearNext = true; - } - }); - this._setButtonStates(); - return; - } - - if (animateRemoval) { - var record = this._getAnimationRecord(element); - if (record) { - record.removed = true; - } - } - if (this._currentPage.elementUniqueID === element.uniqueID) { - if (this._currentPage.next.elementUniqueID) { - this._shiftLeft(this._currentPage); - this._ensureCentered(); - } else if (this._currentPage.prev.elementUniqueID) { - this._shiftRight(this._currentPage); - } else { - this._currentPage.setElement(null, true); - } - } else if (prevMarker.elementUniqueID === element.uniqueID) { - if (prevMarker.next.element) { - work = this._itemsManager._previousItem(prevMarker.next.element). - then(function (e) { - if (e === element) { - // Because the VDS and Binding.List can send notifications in - // different states we accomodate this here by fixing the case - // where VDS hasn't yet removed an item when it sends a removed - // or moved notification. - // - e = that._itemsManager._previousItem(e); - } - return e; - }). - then(function (e) { - prevMarker.setElement(e, true); - }); - } else { - prevMarker.setElement(null, true); - } - } else if (prevMarker.prev.elementUniqueID === element.uniqueID) { - if (prevMarker.prev.prev && prevMarker.prev.prev.element) { - work = this._itemsManager._nextItem(prevMarker.prev.prev.element). - then(function (e) { - if (e === element) { - // Because the VDS and Binding.List can send notifications in - // different states we accomodate this here by fixing the case - // where VDS hasn't yet removed an item when it sends a removed - // or moved notification. - // - e = that._itemsManager._nextItem(e); - } - return e; - }). - then(function (e) { - prevMarker.prev.setElement(e, true); - }); - } else { - prevMarker.prev.setElement(null, true); - } - } else { - var curr = this._currentPage.prev, - handled = false; - while (curr !== prevMarker && !handled) { - if (curr.elementUniqueID === element.uniqueID) { - this._shiftRight(curr); - handled = true; - } - - curr = curr.prev; - } - - curr = this._currentPage.next; - while (curr !== prevMarker && !handled) { - if (curr.elementUniqueID === element.uniqueID) { - this._shiftLeft(curr); - handled = true; - } - - curr = curr.next; - } - } - - return work.then(function () { - that._setButtonStates(); - }); - }, - - reload: function () { - this._writeProfilerMark("WinJS.UI.FlipView:reload,info"); - this.resetState(0); - }, - - getItemSpacing: function () { - return this._itemSpacing; - }, - - setItemSpacing: function (space) { - this._itemSpacing = space; - this._ensureCentered(); - }, - - notificationsStarted: function () { - this._writeProfilerMark("WinJS.UI.FlipView:changeNotifications,StartTM"); - this._logBuffer(); - this._notificationsStarted = this._notificationsStarted || 0; - this._notificationsStarted++; - this._notificationsEndedSignal = new WinJS._Signal(); - this._temporaryKeys = []; - this._animationRecords = {}; - var that = this; - this._forEachPage(function (curr) { - that._createAnimationRecord(curr.elementUniqueID, curr); - }); - - // Since the current item is defined as the left-most item in the view, the only possible elements that can be in view at any time are - // the current item and the item proceeding it. We'll save these two elements for animations during the notificationsEnded cycle - this._animationRecords.currentPage = this._currentPage.element; - this._animationRecords.nextPage = this._currentPage.next.element; - }, - - notificationsEnded: function () { - // The animations are broken down into three parts. - // First, we move everything back to where it was before the changes happened. Elements that were inserted between two pages won't have their flip pages moved. - // Next, we figure out what happened to the two elements that used to be in view. If they were removed/moved, they get animated as appropriate in this order: - // removed, moved - // Finally, we figure out how the items that are now in view got there, and animate them as necessary, in this order: moved, inserted. - // The moved animation of the last part is joined with the moved animation of the previous part, so in the end it is: - // removed -> moved items in view + moved items not in view -> inserted. - var that = this; - this._endNotificationsWork && this._endNotificationsWork.cancel(); - this._endNotificationsWork = this._ensureBufferConsistency().then(function () { - var animationPromises = []; - that._forEachPage(function (curr) { - var record = that._getAnimationRecord(curr.element); - if (record) { - if (record.changed) { - record.oldElement.removedFromChange = true; - animationPromises.push(that._changeFlipPage(curr, record.oldElement, record.newElement)); - } - record.newLocation = curr.location; - that._itemStart(curr, record.originalLocation); - if (record.inserted) { - curr.elementRoot.style.opacity = 0.0; - } - } - }); - - function flipPageFromElement(element) { - var flipPage = null; - that._forEachPage(function (curr) { - if (curr.element === element) { - flipPage = curr; - return true; - } - }); - return flipPage; - } - - function animateOldViewportItemRemoved(record, item) { - that._writeProfilerMark("WinJS.UI.FlipView:_animateOldViewportItemRemoved,info"); - var removedPage = that._createDiscardablePage(item); - that._itemStart(removedPage, record.originalLocation); - animationPromises.push(that._deleteFlipPage(removedPage)); - } - - function animateOldViewportItemMoved(record, item) { - that._writeProfilerMark("WinJS.UI.FlipView:_animateOldViewportItemMoved,info"); - var newLocation = record.originalLocation, - movedPage; - if (!record.successfullyMoved) { - // If the old visible item got moved, but the next/prev of that item don't match up with anything - // currently in our flip page buffer, we need to figure out in which direction it moved. - // The exact location doesn't matter since we'll be deleting it anyways, but we do need to - // animate it going in the right direction. - movedPage = that._createDiscardablePage(item); - var indexMovedTo = that._getElementIndex(item); - var newCurrentIndex = (that._currentPage.element ? that._getElementIndex(that._currentPage.element) : 0); - newLocation += (newCurrentIndex > indexMovedTo ? -100 * that._bufferSize : 100 * that._bufferSize); - } else { - movedPage = flipPageFromElement(item); - newLocation = record.newLocation; - } - if (movedPage) { - that._itemStart(movedPage, record.originalLocation); - animationPromises.push(that._moveFlipPage(movedPage, function () { - that._itemStart(movedPage, newLocation); - })); - } - } - - var oldCurrent = that._animationRecords.currentPage, - oldCurrentRecord = that._getAnimationRecord(oldCurrent), - oldNext = that._animationRecords.nextPage, - oldNextRecord = that._getAnimationRecord(oldNext); - if (oldCurrentRecord && oldCurrentRecord.changed) { - oldCurrent = oldCurrentRecord.newElement; - } - if (oldNextRecord && oldNextRecord.changed) { - oldNext = oldNextRecord.newElement; - } - - if (oldCurrent !== that._currentPage.element || oldNext !== that._currentPage.next.element) { - if (oldCurrentRecord && oldCurrentRecord.removed) { - animateOldViewportItemRemoved(oldCurrentRecord, oldCurrent); - } - if (oldNextRecord && oldNextRecord.removed) { - animateOldViewportItemRemoved(oldNextRecord, oldNext); - } - } - - function joinAnimationPromises() { - if (animationPromises.length === 0) { - animationPromises.push(WinJS.Promise.wrap()); - } - - return WinJS.Promise.join(animationPromises); - } - that._blockTabs = true; - joinAnimationPromises().then(function () { - animationPromises = []; - if (oldCurrentRecord && oldCurrentRecord.moved) { - animateOldViewportItemMoved(oldCurrentRecord, oldCurrent); - } - if (oldNextRecord && oldNextRecord.moved) { - animateOldViewportItemMoved(oldNextRecord, oldNext); - } - var newCurrRecord = that._getAnimationRecord(that._currentPage.element), - newNextRecord = that._getAnimationRecord(that._currentPage.next.element); - that._forEachPage(function (curr) { - var record = that._getAnimationRecord(curr.element); - if (record) { - if (!record.inserted) { - if (record.originalLocation !== record.newLocation) { - if ((record !== oldCurrentRecord && record !== oldNextRecord) || - (record === oldCurrentRecord && !oldCurrentRecord.moved) || - (record === oldNextRecord && !oldNextRecord.moved)) { - animationPromises.push(that._moveFlipPage(curr, function () { - that._itemStart(curr, record.newLocation); - })); - } - } - } else if (record !== newCurrRecord && record !== newNextRecord) { - curr.elementRoot.style.opacity = 1.0; - } - } - }); - joinAnimationPromises().then(function () { - animationPromises = []; - if (newCurrRecord && newCurrRecord.inserted) { - animationPromises.push(that._insertFlipPage(that._currentPage)); - } - if (newNextRecord && newNextRecord.inserted) { - animationPromises.push(that._insertFlipPage(that._currentPage.next)); - } - joinAnimationPromises().then(function () { - that._checkElementVisibility(false); - that._itemSettledOn(); - that._setListEnds(); - that._notificationsStarted--; - if (that._notificationsStarted === 0) { - that._notificationsEndedSignal.complete(); - } - that._writeProfilerMark("WinJS.UI.FlipView:changeNotifications,StopTM"); - that._logBuffer(); - that._endNotificationsWork = null; - }); - }); - }); - }); - }, - - // Private methods - - _timeoutPageSelection: function () { - var that = this; - if (this._lastTimeoutRequest) { - this._lastTimeoutRequest.cancel(); - } - this._lastTimeoutRequest = WinJS.Promise.timeout(itemSelectedEventDelay).then(function () { - that._itemSettledOn(); - }); - }, - - _updateTabIndex: function (newIndex) { - this._forEachPage(function (curr) { - if (curr.element) { - curr.element.tabIndex = newIndex; - } - }); - this._tabIndex = newIndex; - this._tabManager.tabIndex = newIndex; - }, - - _releaseElementIfNotAnimated: function (element) { - var animatedRecord = this._getAnimationRecord(element); - if (!(animatedRecord && (animatedRecord.changed || animatedRecord.inserted || animatedRecord.moved || animatedRecord.removed))) { - this._itemsManager.releaseItem(element); - } - }, - - _getAnimationRecord: function (element) { - return (element ? this._animationRecords[element.uniqueID] : null); - }, - - _createAnimationRecord: function (elementUniqueID, flipPage) { - if (elementUniqueID) { - var record = this._animationRecords[elementUniqueID] = { - removed: false, - changed: false, - inserted: false - }; - - if (flipPage) { - record.originalLocation = flipPage.location; - } - - return record; - } - }, - - _writeProfilerMark: function(message) { - msWriteProfilerMark(message); - if (WinJS.UI.FlipView._enabledDebug) { - WinJS.log && WinJS.log(message, null, "flipviewdebug"); - } - }, - - _getElementIndex: function(element) { - var index = 0; - try { - index = this._itemsManager.itemObject(element).index; - } - catch (e) { - // Failures are expected in cases where items are moved and then deleted. Animations will simply animate as if the item - // moved to the beginning of the list. - } - return index; - }, - - _resetBuffer: function (elementToSave, skipReleases) { - this._writeProfilerMark("WinJS.UI.FlipView:_resetBuffer,info"); - var head = this._currentPage, - curr = head; - do { - if ((curr.element && curr.element === elementToSave) || skipReleases) { - curr.setElement(null, true); - } else { - curr.setElement(null); - } - curr = curr.next; - } while (curr !== head); - }, - - _getHeadOfBuffer: function () { - return this._prevMarker.prev; - }, - - _getTailOfBuffer: function () { - return this._prevMarker; - }, - - _insertNewFlipPage: function (prevElement) { - this._writeProfilerMark("WinJS.UI.FlipView:_insertNewFlipPage,info"); - var newPage = this._createFlipPage(prevElement, this); - this._panningDiv.appendChild(newPage.pageRoot); - return newPage; - }, - - _fetchNextItems: function () { - this._writeProfilerMark("WinJS.UI.FlipView:_fetchNextItems,info"); - var tail = WinJS.Promise.wrap(this._currentPage); - var that = this; - - for (var i = 0; i < this._bufferSize; i++) { - tail = tail.then(function (curr) { - if (curr.next === that._prevMarker) { - that._insertNewFlipPage(curr); - } - if (curr.element) { - return that._itemsManager._nextItem(curr.element). - then(function (element) { - curr.next.setElement(element); - return curr.next; - }); - } else { - curr.next.setElement(null); - return curr.next; - } - }); - } - - return tail; - }, - - _fetchOneNext: function (target) { - this._writeProfilerMark("WinJS.UI.FlipView:_fetchOneNext,info"); - var prevElement = target.prev.element; - // If the target we want to fill with the next item is the end of the circular buffer but we want to keep everything in memory, we've got to increase the buffer size - // so that we don't reuse prevMarker. - if (this._prevMarker === target) { - this._prevMarker = this._prevMarker.next; - } - if (!prevElement) { - target.setElement(null); - return; - } - var that = this; - return this._itemsManager._nextItem(prevElement). - then(function (element) { - target.setElement(element); - that._movePageAhead(target.prev, target); - }); - }, - - _fetchPreviousItems: function (setPrevMarker) { - this._writeProfilerMark("WinJS.UI.FlipView:_fetchPreviousItems,info"); - var that = this; - - var tail = WinJS.Promise.wrap(this._currentPage); - - for (var i = 0; i < this._bufferSize; i++) { - tail = tail.then(function (curr) { - if (curr.element) { - return that._itemsManager._previousItem(curr.element). - then(function (element) { - curr.prev.setElement(element); - return curr.prev; - }); - } else { - curr.prev.setElement(null); - return curr.prev; - } - }); - } - - return tail.then(function (curr) { - if (setPrevMarker) { - that._prevMarker = curr; - } - }); - }, - - _fetchOnePrevious: function (target) { - this._writeProfilerMark("WinJS.UI.FlipView:_fetchOnePrevious,info"); - var nextElement = target.next.element; - - // If the target we want to fill with the previous item is the end of the circular buffer but we want to keep everything in memory, we've got to increase the buffer size - // so that we don't reuse prevMarker. We'll add a new element to be prevMarker's prev, then set prevMarker to point to that new element. - if (this._prevMarker === target.next) { - this._prevMarker = this._prevMarker.prev; - } - if (!nextElement) { - target.setElement(null); - return WinJS.Promise.wrap(); - } - var that = this; - return this._itemsManager._previousItem(nextElement). - then(function (element) { - target.setElement(element); - that._movePageBehind(target.next, target); - }); - }, - - _setButtonStates: function () { - if (this._currentPage.prev.element) { - this._buttonVisibilityHandler.showPreviousButton(); - } else { - this._buttonVisibilityHandler.hidePreviousButton(); - } - - if (this._currentPage.next.element) { - this._buttonVisibilityHandler.showNextButton(); - } else { - this._buttonVisibilityHandler.hideNextButton(); - } - }, - - _ensureCentered: function (delayBoundariesSet) { - this._writeProfilerMark("WinJS.UI.FlipView:_ensureCentered,info"); - this._itemStart(this._currentPage, leftBufferAmount * this._viewportSize()); - var curr = this._currentPage; - while (curr !== this._prevMarker) { - this._movePageBehind(curr, curr.prev); - curr = curr.prev; - } - - curr = this._currentPage; - while (curr.next !== this._prevMarker) { - this._movePageAhead(curr, curr.next); - curr = curr.next; - } - var boundariesSet = false; - if (this._lastScrollPos && !delayBoundariesSet) { - this._setListEnds(); - boundariesSet = true; - } - this._lastScrollPos = this._itemStart(this._currentPage); - this._viewportStart(this._lastScrollPos); - this._checkElementVisibility(true); - this._setupSnapPoints(); - if (!boundariesSet) { - this._setListEnds(); - } - }, - - _ensureBufferConsistency: function () { - var that = this; - var currentElement = this._currentPage.element; - if (!currentElement) { - return WinJS.Promise.wrap(); - } - - var refreshBuffer = false; - var seenUniqueIDs = {}; - var seenLocations = {}; - this._forEachPage(function (page) { - if (page && page.elementUniqueID) { - if (!seenUniqueIDs[page.elementUniqueID]) { - seenUniqueIDs[page.elementUniqueID] = true; - } else { - refreshBuffer = true; - return true; - } - - if (page.location > 0) { - if (!seenLocations[page.location]) { - seenLocations[page.location] = true; - } else { - refreshBuffer = true; - return true; - } - } - } - }); - - var animationKeys = Object.keys(this._animationRecords); - animationKeys.forEach(function (key) { - var record = that._animationRecords[key]; - if (record && (record.changed || record.inserted || record.moved || record.removed)) { - refreshBuffer = true; - } - }); - - if (refreshBuffer) { - this._resetBuffer(null, true); - this._currentPage.setElement(currentElement); - return this._fetchNextItems(). - then(function () { - return that._fetchPreviousItems(true); - }). - then(function () { - that._ensureCentered(); - }); - } else { - return WinJS.Promise.wrap(); - } - }, - - _shiftLeft: function (startingPoint) { - this._writeProfilerMark("WinJS.UI.FlipView:_shiftLeft,info"); - var curr = startingPoint, - nextEl = null; - while (curr !== this._prevMarker && curr.next !== this._prevMarker) { - nextEl = curr.next.element; - if (!nextEl && curr.next.elementUniqueID) { - // Shift the uniqueID of the page manually since its element is being animated. - // This page will not contain the element until the animation completes. - curr.elementUniqueID = curr.next.elementUniqueID; - } - curr.next.setElement(null, true); - curr.setElement(nextEl, true); - curr = curr.next; - } - if (curr !== this._prevMarker && curr.prev.element) { - var that = this; - return this._itemsManager._nextItem(curr.prev.element). - then(function (element) { - curr.setElement(element); - that._createAnimationRecord(curr.elementUniqueID, curr); - }); - } - }, - - _logBuffer: function () { - if (WinJS.UI.FlipView._enabledDebug) { - WinJS.log && WinJS.log(this._currentPage.next.next.next.elementUniqueID + "\t@:" + this._currentPage.next.next.next.location + (this._currentPage.next.next.next.element ? ("\t" + this._currentPage.next.next.next.element.innerText) : ""), null, "flipviewdebug"); - WinJS.log && WinJS.log(this._currentPage.next.next.next.next.elementUniqueID + "\t@:" + this._currentPage.next.next.next.next.location + (this._currentPage.next.next.next.next.element ? ("\t" + this._currentPage.next.next.next.next.element.innerText) : ""), null, "flipviewdebug"); - WinJS.log && WinJS.log("> " + this._currentPage.elementUniqueID + "\t@:" + this._currentPage.location + (this._currentPage.element ? ("\t" + this._currentPage.element.innerText) : ""), null, "flipviewdebug"); - WinJS.log && WinJS.log(this._currentPage.next.elementUniqueID + "\t@:" + this._currentPage.next.location + (this._currentPage.next.element ? ("\t" + this._currentPage.next.element.innerText) : ""), null, "flipviewdebug"); - WinJS.log && WinJS.log(this._currentPage.next.next.elementUniqueID + "\t@:" + this._currentPage.next.next.location + (this._currentPage.next.next.element ? ("\t" + this._currentPage.next.next.element.innerText) : ""), null, "flipviewdebug"); - - var keys = Object.keys(this._itemsManager._elementMap); - var bufferKeys = []; - this._forEachPage(function (page) { - if (page && page.elementUniqueID) { - bufferKeys.push(page.elementUniqueID); - } - }); - WinJS.log && WinJS.log("itemsmanager = [" + keys.join(" ") + "] flipview [" + bufferKeys.join(" ") + "]", null, "flipviewdebug"); - } - }, - - _shiftRight: function (startingPoint) { - this._writeProfilerMark("WinJS.UI.FlipView:_shiftRight,info"); - var curr = startingPoint, - prevEl = null; - while (curr !== this._prevMarker) { - prevEl = curr.prev.element; - if (!prevEl && curr.prev.elementUniqueID) { - // Shift the uniqueID of the page manually since its element is being animated. - // This page will not contain the element until the animation completes. - curr.elementUniqueID = curr.prev.elementUniqueID; - } - curr.prev.setElement(null, true); - curr.setElement(prevEl, true); - curr = curr.prev; - } - if (curr.next.element) { - var that = this; - return this._itemsManager._previousItem(curr.next.element). - then(function (element) { - curr.setElement(element); - that._createAnimationRecord(curr.elementUniqueID, curr); - }); - } - }, - - _checkElementVisibility: function (viewWasReset) { - var i, - len; - if (viewWasReset) { - var currentElement = this._currentPage.element; - for (i = 0, len = this._visibleElements.length; i < len; i++) { - if (this._visibleElements[i] !== currentElement) { - this._announceElementInvisible(this._visibleElements[i]); - } - } - - this._visibleElements = []; - if (currentElement) { - this._visibleElements.push(currentElement); - this._announceElementVisible(currentElement); - } - } else { - // Elements that have been removed completely from the flipper still need to raise pageVisibilityChangedEvents if they were visible prior to being removed, - // so before going through all the elements we go through the ones that we knew were visible and see if they're missing a parentNode. If they are, - // the elements were removed and we announce them as invisible. - for (i = 0, len = this._visibleElements.length; i < len; i++) { - if (!this._visibleElements[i].parentNode || this._visibleElements[i].removedFromChange) { - this._announceElementInvisible(this._visibleElements[i]); - } - } - this._visibleElements = []; - var that = this; - this._forEachPage(function (curr) { - var element = curr.element; - if (element) { - if (that._itemInView(curr)) { - that._visibleElements.push(element); - that._announceElementVisible(element); - } else { - that._announceElementInvisible(element); - } - } - }); - } - }, - - _announceElementVisible: function (element) { - if (element && !element.visible) { - element.visible = true; - - var event = document.createEvent("CustomEvent"); - this._writeProfilerMark("WinJS.UI.FlipView:pageVisibilityChangedEvent(visible:true),info"); - event.initCustomEvent(thisWinUI.FlipView.pageVisibilityChangedEvent, true, false, { source: this._flipperDiv, visible: true }); - - element.dispatchEvent(event); - } - }, - - _announceElementInvisible: function (element) { - if (element && element.visible) { - element.visible = false; - - // Elements that have been removed from the flipper still need to fire invisible events, but they can't do that without being in the DOM. - // To fix that, we add the element back into the flipper, fire the event, then remove it. - var addedToDomForEvent = false; - if (!element.parentNode) { - addedToDomForEvent = true; - this._panningDivContainer.appendChild(element); - } - - var event = document.createEvent("CustomEvent"); - this._writeProfilerMark("WinJS.UI.FlipView:pageVisibilityChangedEvent(visible:false),info"); - event.initCustomEvent(thisWinUI.FlipView.pageVisibilityChangedEvent, true, false, { source: this._flipperDiv, visible: false }); - - element.dispatchEvent(event); - if (addedToDomForEvent) { - this._panningDivContainer.removeChild(element); - } - } - }, - - _createDiscardablePage: function (content) { - var pageDivs = this._createPageContainer(), - page = { - pageRoot: pageDivs.root, - elementRoot: pageDivs.elementContainer, - discardable: true, - element: content, - elementUniqueID: content.uniqueID, - discard: function () { - if (page.pageRoot.parentNode) { - page.pageRoot.parentNode.removeChild(page.pageRoot); - } - if (page.element.parentNode) { - page.element.parentNode.removeChild(page.element); - } - } - }; - page.pageRoot.style.top = "0px"; - page.elementRoot.appendChild(content); - this._panningDiv.appendChild(page.pageRoot); - return page; - }, - - _createPageContainer: function () { - var width = this._panningDivContainerOffsetWidth, - height = this._panningDivContainerOffsetHeight, - parentDiv = document.createElement("div"), - pageStyle = parentDiv.style, - flexBox = document.createElement("div"); - flexBox.className = "win-item"; - pageStyle.position = "absolute"; - pageStyle.overflow = "hidden"; - pageStyle.width = width + "px"; - pageStyle.height = height + "px"; - - parentDiv.appendChild(flexBox); - return { - root: parentDiv, - elementContainer: flexBox - }; - }, - - _createFlipPage: function (prev, manager) { - var page = {}; - page.element = null; - page.elementUniqueID = null; - - // The flip pages are managed as a circular doubly-linked list. this.currentItem should always refer to the current item in view, and this._prevMarker marks the point - // in the list where the last previous item is stored. Why a circular linked list? - // The virtualized flipper reuses its flip pages. When a new item is requested, the flipper needs to reuse an old item from the buffer. In the case of previous items, - // the flipper has to go all the way back to the farthest next item in the buffer and recycle it (which is why having a .prev pointer on the farthest previous item is really useful), - // and in the case of the next-most item, it needs to recycle next's next (ie, the this._prevMarker). The linked structure comes in really handy when iterating through the list - // and separating out prev items from next items (like removed and ensureCentered do). If we were to use a structure like an array it would be pretty messy to do that and still - // maintain a buffer of recyclable items. - if (!prev) { - page.next = page; - page.prev = page; - } else { - page.prev = prev; - page.next = prev.next; - page.next.prev = page; - prev.next = page; - } - var pageContainer = this._createPageContainer(); - page.elementRoot = pageContainer.elementContainer; - page.elementRoot.style["-ms-overflow-style"] = "auto"; - page.pageRoot = pageContainer.root; - - // Sets the element to display in this flip page - page.setElement = function (element, isReplacement) { - if (element === undefined) { - element = null; - } - if (element === page.element) { - if (!element) { - // If there are data source updates during the animation (e.g. item removed), a page element can be set to null when the shiftLeft/Right functions - // call this function with a null element. However, since the element in the page is in the middle of an animation its page.elementUniqueID - // is still set, so we need to explicitly clear its value so that when the animation completes, the animated element is not - // restored back into the internal buffer. - page.elementUniqueID = null; - } - return; - } - if (page.element) { - if (!isReplacement) { - manager._itemsManager.releaseItem(page.element); - WinJS.Utilities._disposeElement(page.element); - } - } - page.element = element; - page.elementUniqueID = (element ? element.uniqueID : null); - utilities.empty(page.elementRoot); - - if (page.element) { - if (!isFlipper(page.element)) { - page.element.tabIndex = manager._tabIndex; - page.element.setAttribute("role", "option"); - page.element.setAttribute("aria-selected", false); - if (!page.element.id) { - page.element.id = page.element.uniqueID; - } - - var setFlowAttribute = function (source, target, attributeName) { - source.setAttribute(attributeName, target.id); - } - - var isEnd = !page.next.element || page === manager._prevMarker.prev; - if (isEnd) { - setFlowAttribute(page.element, manager._bufferAriaEndMarker, "aria-flowto"); - setFlowAttribute(manager._bufferAriaEndMarker, page.element, "x-ms-aria-flowfrom"); - } - - if (page !== manager._prevMarker && page.prev.element) { - setFlowAttribute(page.prev.element, page.element, "aria-flowto"); - setFlowAttribute(page.element, page.prev.element, "x-ms-aria-flowfrom"); - } - if (page.next !== manager._prevMarker && page.next.element) { - setFlowAttribute(page.element, page.next.element, "aria-flowto"); - setFlowAttribute(page.next.element, page.element, "x-ms-aria-flowfrom"); - } - - if (!page.prev.element) { - setFlowAttribute(page.element, manager._bufferAriaStartMarker, "x-ms-aria-flowfrom"); - // aria-flowto in the start marker is configured in itemSettledOn to point to the current page in view - } - } - page.elementRoot.appendChild(page.element); - } - }; - - return page; - }, - - _itemInView: function (flipPage) { - return this._itemEnd(flipPage) > this._viewportStart() && this._itemStart(flipPage) < this._viewportEnd(); - }, - - _viewportStart: function (newValue) { - if (!this._panningDivContainer.parentNode) { - return; - } - - if (this._horizontal) { - if (newValue === undefined) { - return this._panningDivContainer.scrollLeft; - } - this._panningDivContainer.scrollLeft = newValue; - } else { - if (newValue === undefined) { - return this._panningDivContainer.scrollTop; - } - - this._panningDivContainer.scrollTop = newValue; - } - }, - - _viewportEnd: function () { - var element = this._panningDivContainer; - if (this._horizontal) { - if (this._rtl) { - return this._viewportStart() + this._panningDivContainerOffsetWidth; - } else { - return element.scrollLeft + this._panningDivContainerOffsetWidth; - } - } else { - return element.scrollTop + this._panningDivContainerOffsetHeight; - } - }, - - _viewportSize: function () { - return this._horizontal ? this._panningDivContainerOffsetWidth : this._panningDivContainerOffsetHeight; - }, - - _itemStart: function (flipPage, newValue) { - if (newValue === undefined) { - return flipPage.location; - } - - if (this._horizontal) { - flipPage.pageRoot.style.left = (this._rtl ? -newValue : newValue) + "px"; - } else { - flipPage.pageRoot.style.top = newValue + "px"; - } - - flipPage.location = newValue; - }, - - _itemEnd: function (flipPage) { - return (this._horizontal ? flipPage.location + this._panningDivContainerOffsetWidth : flipPage.location + this._panningDivContainerOffsetHeight) + this._itemSpacing; - }, - - _itemSize: function (flipPage) { - return this._horizontal ? this._panningDivContainerOffsetWidth : this._panningDivContainerOffsetHeight; - }, - - _movePageAhead: function (referencePage, pageToPlace) { - var delta = this._itemSize(referencePage) + this._itemSpacing; - this._itemStart(pageToPlace, this._itemStart(referencePage) + delta); - }, - - _movePageBehind: function (referencePage, pageToPlace) { - var delta = this._itemSize(referencePage) + this._itemSpacing; - this._itemStart(pageToPlace, this._itemStart(referencePage) - delta); - }, - - _setupSnapPoints: function () { - var containerStyle = this._panningDivContainer.style; - containerStyle["-ms-scroll-snap-type"] = "mandatory"; - var viewportSize = this._viewportSize(); - var snapInterval = viewportSize + this._itemSpacing; - var propertyName = "-ms-scroll-snap-points"; - var startSnap = 0; - var currPos = this._itemStart(this._currentPage); - startSnap = currPos % (viewportSize + this._itemSpacing); - containerStyle[(this._horizontal ? propertyName + "-x" : propertyName + "-y")] = "snapInterval(" + startSnap + "px, " + snapInterval + "px)"; - }, - - _setListEnds: function () { - if (this._currentPage.element) { - var containerStyle = this._panningDivContainer.style, - startScroll = 0, - endScroll = 0, - startNonEmptyPage = this._getTailOfBuffer(), - endNonEmptyPage = this._getHeadOfBuffer(), - startBoundaryStyle = "-ms-scroll-limit-" + (this._horizontal ? "x-min" : "y-min"), - endBoundaryStyle = "-ms-scroll-limit-" + (this._horizontal ? "x-max" : "y-max"); - - while (!endNonEmptyPage.element) { - endNonEmptyPage = endNonEmptyPage.prev; - - // We started at the item before prevMarker (going backwards), so we will exit if all - // the pages in the buffer are empty. - if (endNonEmptyPage == this._prevMarker.prev) { - break; - } - } - - while (!startNonEmptyPage.element) { - startNonEmptyPage = startNonEmptyPage.next; - - // We started at prevMarker (going forward), so we will exit if all the pages in the - // buffer are empty. - if (startNonEmptyPage == this._prevMarker) { - break; - } - } - - endScroll = this._itemStart(endNonEmptyPage); - startScroll = this._itemStart(startNonEmptyPage); - containerStyle[startBoundaryStyle] = startScroll + "px"; - containerStyle[endBoundaryStyle] = endScroll + "px"; - } - }, - - _viewportOnItemStart: function () { - return this._itemStart(this._currentPage) === this._viewportStart(); - }, - - _restoreAnimatedElement: function (oldPage, discardablePage) { - var removed = true; - // Restore the element in the old page only if it still matches the uniqueID, and the page - // does not have new updated content. If the element was removed, it won't be restore in the - // old page. - if (oldPage.elementUniqueID === discardablePage.element.uniqueID && !oldPage.element) { - oldPage.setElement(discardablePage.element, true); - removed = false; - } else { - // Iterate through the pages to see if the element was moved - this._forEachPage(function (curr) { - if (curr.elementUniqueID === discardablePage.elementUniqueID && !curr.element) { - curr.setElement(discardablePage.element, true); - removed = false; - } - }); - } - return removed; - }, - - _itemSettledOn: function () { - if (this._lastTimeoutRequest) { - this._lastTimeoutRequest.cancel(); - this._lastTimeoutRequest = null; - } - - var that = this; - // Need to yield to the host here - setImmediate(function () { - if (that._viewportOnItemStart()) { - that._blockTabs = false; - if (that._currentPage.element) { - if (that._hasFocus) { - try { - that._currentPage.element.setActive(); - that._tabManager.childFocus = that._currentPage.element; - } catch (e) { } - } - if (that._lastSelectedElement !== that._currentPage.element) { - if (that._lastSelectedPage && that._lastSelectedPage.element && !isFlipper(that._lastSelectedPage.element)) { - that._lastSelectedPage.element.setAttribute("aria-selected", false); - } - that._lastSelectedPage = that._currentPage; - that._lastSelectedElement = that._currentPage.element; - if (!isFlipper(that._currentPage.element)) { - that._currentPage.element.setAttribute("aria-selected", true); - } - - // Need to schedule this: - // - to be able to register for the pageselected event after instantiating the control and still get the event - // - in case a FlipView navigation is triggered inside the pageselected listener (avoid reentering _itemSettledOn) - Scheduler.schedule(function FlipView_dispatchPageSelectedEvent() { - if (that._currentPage.element) { - var event = document.createEvent("CustomEvent"); - event.initCustomEvent(thisWinUI.FlipView.pageSelectedEvent, true, false, { source: that._flipperDiv }); - that._writeProfilerMark("WinJS.UI.FlipView:pageSelectedEvent,info"); - that._currentPage.element.dispatchEvent(event); - - // Fire the pagecompleted event when the render completes if we are still looking at the same element. - // Check that the current element is not null, since the app could've triggered a navigation inside the - // pageselected event handler. - var originalElement = that._currentPage.element; - if (originalElement) { - var record = that._itemsManager._recordFromElement(originalElement, true); - if (record) { - record.renderComplete.then(function () { - if (originalElement === that._currentPage.element) { - that._currentPage.element.setAttribute("aria-setsize", that._cachedSize); - that._currentPage.element.setAttribute("aria-posinset", that.currentIndex() + 1); - that._bufferAriaStartMarker.setAttribute("aria-flowto", that._currentPage.element.id); - event = document.createEvent("CustomEvent"); - event.initCustomEvent(thisWinUI.FlipView.pageCompletedEvent, true, false, { source: that._flipperDiv }); - that._writeProfilerMark("WinJS.UI.FlipView:pageCompletedEvent,info"); - that._currentPage.element.dispatchEvent(event); - } - }); - } - } - } - }, Scheduler.Priority.normal, null, "WinJS.UI.FlipView._dispatchPageSelectedEvent"); - } - } - } - }); - }, - - _forEachPage: function (callback) { - var go = true; - var curr = this._prevMarker; - while (go) { - if (callback(curr)) { - break; - } - curr = curr.next; - go = (curr !== this._prevMarker); - } - }, - - _changeFlipPage: function (page, oldElement, newElement) { - this._writeProfilerMark("WinJS.UI.FlipView:_changeFlipPage,info"); - page.element = null; - if (page.setElement) { - page.setElement(newElement, true); - } else { - // Discardable pages that are created for animations aren't full fleged pages, and won't have some of the functions a normal page would. - // changeFlipPage will be called on them when an item that's animating gets fetched. When that happens, we need to replace its element - // manually, then center it. - oldElement.parentNode.removeChild(oldElement); - page.elementRoot.appendChild(newElement); - } - - var style = oldElement.style; - style.position = "absolute"; - style.left = "0px"; - style.top = "0px"; - style.opacity = 1.0; - - page.pageRoot.appendChild(oldElement); - oldElement.style.left = Math.max(0, (page.pageRoot.offsetWidth - oldElement.offsetWidth) / 2) + "px"; - oldElement.style.top = Math.max(0, (page.pageRoot.offsetHeight - oldElement.offsetHeight) / 2) + "px"; - - return animations.fadeOut(oldElement).then(function () { - oldElement.parentNode && oldElement.parentNode.removeChild(oldElement); - }); - }, - - _deleteFlipPage: function (page) { - msWriteProfilerMark("WinJS.UI.FlipView:_deleteFlipPage,info"); - page.elementRoot.style.opacity = 0; - var animation = animations.createDeleteFromListAnimation([page.elementRoot]); - - var that = this; - return animation.execute().then(function () { - if (page.discardable) { - page.discard(); - that._itemsManager.releaseItem(page.element); - } - }); - }, - - _insertFlipPage: function (page) { - msWriteProfilerMark("WinJS.UI.FlipView:_insertFlipPage,info"); - page.elementRoot.style.opacity = 1.0; - var animation = animations.createAddToListAnimation([page.elementRoot]); - - return animation.execute().then(function () { - if (page.discardable) { - page.discard(); - } - }); - }, - - _moveFlipPage: function (page, move) { - msWriteProfilerMark("WinJS.UI.FlipView:_moveFlipPage,info"); - var animation = animations.createRepositionAnimation(page.pageRoot); - - move(); - - var that = this; - return animation.execute().then(function () { - if (page.discardable) { - page.discard(); - var animationRecord = that._getAnimationRecord(page.element); - if (animationRecord && !animationRecord.successfullyMoved) { - // If the animationRecord was not succesfully moved, the item is now outside of the buffer, - // and we can release it. - that._itemsManager.releaseItem(page.element); - } - } - }); - } - }, { - supportedForProcessing: false, - }); - _FlipPageManager.flipPageBufferCount = 2; // The number of items that should surround the current item as a buffer at any time - return _FlipPageManager; - }) - }); - -})(WinJS); - -(function browseModeInit(global, WinJS, undefined) { - "use strict"; - - // This component is responsible for handling input in Browse Mode. - // When the user clicks on an item in this mode itemInvoked event is fired. - WinJS.Namespace.define("WinJS.UI", { - _getCursorPos: function (eventObject) { - var docElement = document.documentElement; - - return { - left: eventObject.clientX + (document.body.dir === "rtl" ? -docElement.scrollLeft : docElement.scrollLeft), - top: eventObject.clientY + docElement.scrollTop - }; - }, - - _getElementsByClasses: function (parent, classes) { - var retVal = [] - - for (var i = 0, len = classes.length; i < len; i++) { - var element = parent.querySelector("." + classes[i]); - if (element) { - retVal.push(element); - } - } - return retVal; - }, - - _SelectionMode: WinJS.Namespace._lazy(function () { - var utilities = WinJS.Utilities, - Promise = WinJS.Promise, - Animation = WinJS.UI.Animation; - - function clampToRange(first, last, x) { - return Math.max(first, Math.min(last, x)); - } - - function dispatchKeyboardNavigating(element, oldEntity, newEntity) { - var navigationEvent = document.createEvent("CustomEvent"); - navigationEvent.initCustomEvent("keyboardnavigating", true, true, { - oldFocus: oldEntity.index, - oldFocusType: oldEntity.type, - newFocus: newEntity.index, - newFocusType: newEntity.type - }); - return element.dispatchEvent(navigationEvent); - } - - var _SelectionMode = function (modeSite) { - this.inboundFocusHandled = false; - this._pressedContainer = null; - this._pressedItemBox = null; - this._pressedHeader = null; - this._pressedEntity = { type: WinJS.UI.ObjectType.item, index: WinJS.UI._INVALID_INDEX }; - this._pressedPosition = null; - - this.initialize(modeSite); - }; - _SelectionMode.prototype = { - _dispose: function () { - if (this._itemEventsHandler) { - this._itemEventsHandler.dispose(); - } - if (this._setNewFocusItemOffsetPromise) { - this._setNewFocusItemOffsetPromise.cancel(); - } - }, - - initialize: function (modeSite) { - this.site = modeSite; - - this._keyboardNavigationHandlers = {}; - this._keyboardAcceleratorHandlers = {}; - - var site = this.site, - that = this; - this._itemEventsHandler = new WinJS.UI._ItemEventsHandler(Object.create({ - containerFromElement: function (element) { - return site._view.items.containerFrom(element); - }, - indexForItemElement: function (element) { - return site._view.items.index(element); - }, - indexForHeaderElement: function (element) { - return site._groups.index(element); - }, - itemBoxAtIndex: function (index) { - return site._view.items.itemBoxAt(index); - }, - itemAtIndex: function (index) { - return site._view.items.itemAt(index); - }, - headerAtIndex: function (index) { - return site._groups.group(index).header; - }, - containerAtIndex: function (index) { - return site._view.items.containerAt(index); - }, - isZombie: function () { - return site._isZombie(); - }, - getItemPosition: function (entity) { - return site._getItemPosition(entity); - }, - rtl: function () { - return site._rtl(); - }, - fireInvokeEvent: function (entity, itemElement) { - return that._fireInvokeEvent(entity, itemElement); - }, - verifySelectionAllowed: function (index) { - return that._verifySelectionAllowed(index); - }, - changeFocus: function (newFocus, skipSelection, ctrlKeyDown, skipEnsureVisible, keyboardFocused) { - return site._changeFocus(newFocus, skipSelection, ctrlKeyDown, skipEnsureVisible, keyboardFocused); - }, - selectRange: function (firstIndex, lastIndex, additive) { - return that._selectRange(firstIndex, lastIndex, additive); - } - }, { - pressedEntity: { - enumerable: true, - get: function () { - return that._pressedEntity; - }, - set: function (value) { - that._pressedEntity = value; - } - }, - pressedContainerScaleTransform: { - enumerable: true, - get: function () { - return that._pressedContainerScaleTransform; - }, - set: function (value) { - that._pressedContainerScaleTransform = value; - } - }, - pressedContainer: { - enumerable: true, - get: function () { - return that._pressedContainer; - }, - set: function (value) { - that._pressedContainer = value; - } - }, - - pressedItemBox: { - enumerable: true, - get: function () { - return that._pressedItemBox; - }, - set: function (value) { - that._pressedItemBox = value; - } - }, - - pressedHeader: { - enumerable: true, - get: function () { - return that._pressedHeader; - }, - set: function (value) { - return that._pressedHeader = value; - } - }, - - pressedPosition: { - enumerable: true, - get: function () { - return that._pressedPosition; - }, - set: function (value) { - that._pressedPosition = value; - } - }, - - pressedElement: { - enumerable: true, - set: function (value) { - that._pressedElement = value; - } - }, - - swipeBehavior: { - enumerable: true, - get: function () { - return site._swipeBehavior; - } - }, - eventHandlerRoot: { - enumerable: true, - get: function () { - return site._viewport; - } - }, - selectionMode: { - enumerable: true, - get: function () { - return site._selectionMode; - } - }, - accessibleItemClass: { - enumerable: true, - get: function () { - // CSS class of the element with the aria role - return WinJS.UI._itemClass; - } - }, - canvasProxy: { - enumerable: true, - get: function () { - return site._canvasProxy; - } - }, - tapBehavior: { - enumerable: true, - get: function () { - return site._tap; - } - }, - draggable: { - enumerable: true, - get: function () { - return site.itemsDraggable || site.itemsReorderable; - } - }, - selection: { - enumerable: true, - get: function () { - return site._selection; - } - }, - horizontal: { - enumerable: true, - get: function () { - return site._horizontal(); - } - }, - customFootprintParent: { - enumerable: true, - get: function () { - return null; - } - } - })); - - function createArrowHandler(direction, clampToBounds) { - var handler = function (oldFocus) { - return modeSite._view.getAdjacent(oldFocus, direction); - }; - handler.clampToBounds = clampToBounds; - return handler; - } - - var Key = utilities.Key; - this._keyboardNavigationHandlers[Key.upArrow] = createArrowHandler(Key.upArrow); - this._keyboardNavigationHandlers[Key.downArrow] = createArrowHandler(Key.downArrow); - this._keyboardNavigationHandlers[Key.leftArrow] = createArrowHandler(Key.leftArrow); - this._keyboardNavigationHandlers[Key.rightArrow] = createArrowHandler(Key.rightArrow); - this._keyboardNavigationHandlers[Key.pageUp] = createArrowHandler(Key.pageUp, true); - this._keyboardNavigationHandlers[Key.pageDown] = createArrowHandler(Key.pageDown, true); - this._keyboardNavigationHandlers[Key.home] = function (oldFocus) { - return WinJS.Promise.wrap({ type: oldFocus.type, index: 0 }); - }; - this._keyboardNavigationHandlers[Key.end] = function (oldFocus) { - if (oldFocus.type === WinJS.UI.ObjectType.groupHeader) { - return WinJS.Promise.wrap({ type: oldFocus.type, index: site._groups.length() - 1 }); - } else { - // Get the index of the last container - return that.site._view.finalItem().then(function (index) { - return { type: oldFocus.type, index: index }; - }, function (error) { - return WinJS.Promise.wrapError(error); - }); - } - }; - - this._keyboardAcceleratorHandlers[Key.a] = function () { - if (that.site._multiSelection()) { - that._selectAll(); - } - }; - }, - - staticMode: function SelectionMode_staticMode() { - return this.site._tap === WinJS.UI.TapBehavior.none && this.site._selectionMode === WinJS.UI.SelectionMode.none; - }, - - itemUnrealized: function SelectionMode_itemUnrealized(index, itemBox) { - if (this._pressedEntity.type === WinJS.UI.ObjectType.groupHeader) { - return; - } - - if (this._pressedEntity.index === index) { - this._resetPointerDownState(); - } - - if (this._itemBeingDragged(index)) { - for (var i = this._draggedItemBoxes.length - 1; i >= 0; i--) { - if (this._draggedItemBoxes[i] === itemBox) { - utilities.removeClass(itemBox, WinJS.UI._dragSourceClass); - this._draggedItemBoxes.splice(i, 1); - } - } - } - }, - - _fireInvokeEvent: function SelectionMode_fireInvokeEvent(entity, itemElement) { - if (!itemElement) { - return; - } - - var that = this; - function fireInvokeEventImpl(dataSource, isHeader) { - var listBinding = dataSource.createListBinding(), - promise = listBinding.fromIndex(entity.index), - eventName = isHeader ? "groupheaderinvoked" : "iteminvoked"; - - promise.done(function (item) { - listBinding.release(); - }); - - var eventObject = document.createEvent("CustomEvent"); - eventObject.initCustomEvent(eventName, true, true, isHeader ? { - groupHeaderPromise: promise, - groupHeaderIndex: entity.index - } : { - itemPromise: promise, - itemIndex: entity.index - }); - - // If preventDefault was not called, call the default action on the site - if (itemElement.dispatchEvent(eventObject)) { - that.site._defaultInvoke(entity); - } - } - - if (entity.type === WinJS.UI.ObjectType.groupHeader) { - if (this.site._groupHeaderTap === WinJS.UI.GroupHeaderTapBehavior.invoke && - entity.index !== WinJS.UI._INVALID_INDEX) { - fireInvokeEventImpl(this.site.groupDataSource, true); - } - } - else { - if (this.site._tap !== WinJS.UI.TapBehavior.none && entity.index !== WinJS.UI._INVALID_INDEX) { - fireInvokeEventImpl(this.site.itemDataSource, false); - } - } - }, - - _verifySelectionAllowed: function SelectionMode_verifySelectionAllowed(entity) { - if (entity.type === WinJS.UI.ObjectType.groupHeader) { - return { - canSelect: false, - canTapSelect: false - }; - } - - var itemIndex = entity.index; - var site = this.site; - var item = this.site._view.items.itemAt(itemIndex); - if (site._selectionAllowed() && (site._selectOnTap() || site._swipeBehavior === WinJS.UI.SwipeBehavior.select) && !(item && utilities.hasClass(item, WinJS.UI._nonSelectableClass))) { - var selected = site._selection._isIncluded(itemIndex), - single = !site._multiSelection(), - newSelection = site._selection._cloneSelection(); - - if (selected) { - if (single) { - newSelection.clear(); - } else { - newSelection.remove(itemIndex); - } - } else { - if (single) { - newSelection.set(itemIndex); - } else { - newSelection.add(itemIndex); - } - } - - var eventObject = document.createEvent("CustomEvent"), - newSelectionUpdated = Promise.wrap(), - completed = false, - preventTap = false, - included; - - eventObject.initCustomEvent("selectionchanging", true, true, { - newSelection: newSelection, - preventTapBehavior: function () { - preventTap = true; - }, - setPromise: function (promise) { - /// - /// - /// Used to inform the ListView that asynchronous work is being performed, and that this - /// event handler should not be considered complete until the promise completes. - /// - /// - /// The promise to wait for. - /// - /// - - newSelectionUpdated = promise; - } - }); - - var defaultBehavior = site._element.dispatchEvent(eventObject); - - newSelectionUpdated.then(function () { - completed = true; - included = newSelection._isIncluded(itemIndex); - newSelection.clear(); - }); - - var canSelect = defaultBehavior && completed && (selected || included); - - return { - canSelect: canSelect, - canTapSelect: canSelect && !preventTap - }; - } else { - return { - canSelect: false, - canTapSelect: false - }; - } - }, - - _containedInElementWithClass: function SelectionMode_containedInElementWithClass(element, className) { - if (element.parentNode) { - var matches = element.parentNode.querySelectorAll("." + className + ", ." + className + " *"); - for (var i = 0, len = matches.length; i < len; i++) { - if (matches[i] === element) { - return true; - } - } - } - return false; - }, - - _isDraggable: function SelectionMode_isDraggable(element) { - return (!this._containedInElementWithClass(element, WinJS.UI._nonDraggableClass)); - }, - - _isInteractive: function SelectionMode_isInteractive(element) { - return this._containedInElementWithClass(element, "win-interactive"); - }, - - _resetPointerDownState: function SelectionMode_resetPointerDownState() { - this._itemEventsHandler.resetPointerDownState(); - }, - - onMSManipulationStateChanged: function (eventObject) { - this._itemEventsHandler.onMSManipulationStateChanged(eventObject); - }, - - onPointerDown: function SelectionMode_onPointerDown(eventObject) { - this._itemEventsHandler.onPointerDown(eventObject); - }, - - onclick: function SelectionMode_onclick(eventObject) { - this._itemEventsHandler.onClick(eventObject); - }, - - onPointerUp: function SelectionMode_onPointerUp(eventObject) { - this._itemEventsHandler.onPointerUp(eventObject); - }, - - onPointerCancel: function SelectionMode_onPointerCancel(eventObject) { - this._itemEventsHandler.onPointerCancel(eventObject); - }, - - onLostPointerCapture: function SelectionMode_onLostPointerCapture(eventObject) { - this._itemEventsHandler.onLostPointerCapture(eventObject); - }, - - onContextMenu: function SelectionMode_onContextMenu(eventObject) { - this._itemEventsHandler.onContextMenu(eventObject); - }, - - onMSHoldVisual: function SelectionMode_onMSHoldVisual(eventObject) { - this._itemEventsHandler.onMSHoldVisual(eventObject); - }, - - onDataChanged: function SelectionMode_onDataChanged(eventObject) { - this._itemEventsHandler.onDataChanged(eventObject); - }, - - _removeTransform: function SelectionMode_removeTransform(element, transform) { - if (transform && element.style.transform.indexOf(transform) !== -1) { - element.style.transform = element.style.transform.replace(transform, ""); - } - }, - - _selectAll: function SelectionMode_selectAll() { - var unselectableRealizedItems = []; - this.site._view.items.each(function (index, item, itemData) { - if (item && utilities.hasClass(item, WinJS.UI._nonSelectableClass)) { - unselectableRealizedItems.push(index); - } - }); - - this.site._selection.selectAll(); - if (unselectableRealizedItems.length > 0) { - this.site._selection.remove(unselectableRealizedItems); - } - }, - - _selectRange: function SelectionMode_selectRange(firstIndex, lastIndex, additive) { - var ranges = []; - var currentStartRange = -1; - for (var i = firstIndex; i <= lastIndex; i++) { - var item = this.site._view.items.itemAt(i); - if (item && utilities.hasClass(item, WinJS.UI._nonSelectableClass)) { - if (currentStartRange !== -1) { - ranges.push({ - firstIndex: currentStartRange, - lastIndex: i - 1 - }); - currentStartRange = -1; - } - } else if (currentStartRange === -1) { - currentStartRange = i; - } - } - if (currentStartRange !== -1) { - ranges.push({ - firstIndex: currentStartRange, - lastIndex: lastIndex - }); - } - if (ranges.length > 0) { - this.site._selection[additive ? "add" : "set"](ranges); - } - }, - - onDragStart: function SelectionMode_onDragStart(eventObject) { - this._pressedEntity = { type: WinJS.UI.ObjectType.item, index: this.site._view.items.index(eventObject.srcElement) }; - this.site._selection._pivot = WinJS.UI._INVALID_INDEX; - // Drag shouldn't be initiated when the user holds down the mouse on a win-interactive element and moves. - // The problem is that the dragstart event's srcElement+target will both be an itembox (which has draggable=true), so we can't check for win-interactive in the dragstart event handler. - // The itemEventsHandler sets our _pressedElement field on MSPointerDown, so we use that instead when checking for interactive. - if (this._pressedEntity.index !== WinJS.UI._INVALID_INDEX && - (this.site.itemsDraggable || this.site.itemsReorderable) && - !this.site._view.animating && - this._isDraggable(eventObject.srcElement) && - (!this._pressedElement || !this._isInteractive(this._pressedElement))) { - this._dragging = true; - this._dragDataTransfer = eventObject.dataTransfer; - this._pressedPosition = WinJS.UI._getCursorPos(eventObject); - this._dragInfo = null; - this._lastEnteredElement = eventObject.srcElement; - - if (this.site._selection._isIncluded(this._pressedEntity.index)) { - this._dragInfo = this.site.selection; - } else { - this._draggingUnselectedItem = true; - this._dragInfo = new WinJS.UI._Selection(this.site, [{ firstIndex: this._pressedEntity.index, lastIndex: this._pressedEntity.index }]); - } - - var dropTarget = this.site.itemsReorderable; - var event = document.createEvent("CustomEvent"); - event.initCustomEvent("itemdragstart", true, false, { - dataTransfer: eventObject.dataTransfer, - dragInfo: this._dragInfo - }); - this.site.element.dispatchEvent(event); - if (this.site.itemsDraggable && !this.site.itemsReorderable) { - if (!this._firedDragEnter) { - if (this._fireDragEnterEvent(eventObject.dataTransfer)) { - dropTarget = true; - this._dragUnderstood = true; - } - } - } - - if (dropTarget) { - this._addedDragOverClass = true; - utilities.addClass(this.site._element, WinJS.UI._dragOverClass); - } - - this._draggedItemBoxes = []; - - var that = this; - // A dragged element can be removed from the DOM by a number of actions - datasource removes/changes, being scrolled outside of the realized range, etc. - // The dragend event is fired on the original source element of the drag. If that element isn't in the DOM, though, the dragend event will only be fired on the element - // itself and not bubble up through the ListView's tree to the _viewport element where all the other drag event handlers are. - // The dragend event handler has to be added to the event's srcElement so that we always receive the event, even when the source element is unrealized. - var sourceElement = eventObject.srcElement; - sourceElement.addEventListener("dragend", function itemDragEnd(eventObject) { - sourceElement.removeEventListener("dragend", itemDragEnd); - that.onDragEnd(eventObject); - }); - // We delay setting the opacity of the dragged items so that IE has time to create a thumbnail before me make them invisible - setImmediate(function () { - if (that._dragging) { - var indicesSelected = that._dragInfo.getIndices(); - for (var i = 0, len = indicesSelected.length; i < len; i++) { - var itemData = that.site._view.items.itemDataAt(indicesSelected[i]); - if (itemData && itemData.itemBox) { - that._addDragSourceClass(itemData.itemBox); - } - } - } - }); - } else { - eventObject.preventDefault(); - } - }, - - onDragEnter: function (eventObject) { - var eventHandled = this._dragUnderstood; - this._lastEnteredElement = eventObject.srcElement; - if (this._exitEventTimer) { - clearTimeout(this._exitEventTimer); - this._exitEventTimer = 0; - } - - if (!this._firedDragEnter) { - if (this._fireDragEnterEvent(eventObject.dataTransfer)) { - eventHandled = true; - } - } - - if (eventHandled || (this._dragging && this.site.itemsReorderable)) { - eventObject.preventDefault(); - this._dragUnderstood = true; - if (!this._addedDragOverClass) { - this._addedDragOverClass = true; - utilities.addClass(this.site._element, WinJS.UI._dragOverClass); - } - } - this._pointerLeftRegion = false; - }, - - onDragLeave: function (eventObject) { - if (eventObject.srcElement === this._lastEnteredElement) { - this._pointerLeftRegion = true; - this._handleExitEvent(); - } - }, - - fireDragUpdateEvent: function () { - var event = document.createEvent("CustomEvent"); - event.initCustomEvent("itemdragchanged", true, false, { - dataTransfer: this._dragDataTransfer, - dragInfo: this._dragInfo - }); - this.site.element.dispatchEvent(event); - }, - - _fireDragEnterEvent: function (dataTransfer) { - var event = document.createEvent("CustomEvent"); - event.initCustomEvent("itemdragenter", true, true, { - dataTransfer: dataTransfer - }); - // The end developer must tell a ListView when a drag can be understood by calling preventDefault() on the event we fire - var dropTarget = (!this.site.element.dispatchEvent(event)); - this._firedDragEnter = true; - return dropTarget; - }, - - _fireDragBetweenEvent: function (index, insertAfterIndex, dataTransfer) { - var event = document.createEvent("CustomEvent"); - event.initCustomEvent("itemdragbetween", true, true, { - index: index, - insertAfterIndex: insertAfterIndex, - dataTransfer: dataTransfer - }); - return this.site.element.dispatchEvent(event); - }, - - _fireDropEvent: function (index, insertAfterIndex, dataTransfer) { - var event = document.createEvent("CustomEvent"); - event.initCustomEvent("itemdragdrop", true, true, { - index: index, - insertAfterIndex: insertAfterIndex, - dataTransfer: dataTransfer - }); - return this.site.element.dispatchEvent(event); - }, - - _handleExitEvent: function () { - if (this._exitEventTimer) { - clearTimeout(this._exitEventTimer); - this._exitEventTimer = 0; - } - var that = this; - this._exitEventTimer = setTimeout(function () { - if (that._pointerLeftRegion) { - that.site._layout.dragLeave && that.site._layout.dragLeave(); - that._pointerLeftRegion = false; - that._dragUnderstood = false; - that._lastEnteredElement = null; - that._lastInsertPoint = null; - that._dragBetweenDisabled = false; - if (that._firedDragEnter) { - var event = document.createEvent("CustomEvent"); - event.initCustomEvent("itemdragleave", true, false, { - }); - that.site.element.dispatchEvent(event); - that._firedDragEnter = false; - } - if (that._addedDragOverClass) { - that._addedDragOverClass = false; - utilities.removeClass(that.site._element, WinJS.UI._dragOverClass); - } - that._exitEventTimer = 0; - that._stopAutoScroll(); - } - }, 40); - }, - - _getEventPositionInElementSpace: function (element, eventObject) { - var elementRect = { left: 0, top: 0 }; - try { - elementRect = element.getBoundingClientRect(); - } - catch (err) { } - - var computedStyle = window.getComputedStyle(element, null), - paddingLeft = parseInt(computedStyle["paddingLeft"]), - paddingTop = parseInt(computedStyle["paddingTop"]), - borderLeft = parseInt(computedStyle["borderLeftWidth"]), - borderTop = parseInt(computedStyle["borderTopWidth"]), - clientX = eventObject.clientX, - clientY = eventObject.clientY; - - var position = { - x: +clientX === clientX ? (clientX - elementRect.left - paddingLeft - borderLeft) : 0, - y: +clientY === clientY ? (clientY - elementRect.top - paddingTop - borderTop) : 0 - }; - - if (this.site._rtl()) { - position.x = (elementRect.right - elementRect.left) - position.x; - } - - return position; - }, - - _getPositionInCanvasSpace: function (eventObject) { - var scrollLeft = this.site._horizontal() ? this.site.scrollPosition : 0, - scrollTop = this.site._horizontal() ? 0 : this.site.scrollPosition, - position = this._getEventPositionInElementSpace(this.site.element, eventObject); - - return { - x: position.x + scrollLeft, - y: position.y + scrollTop - }; - }, - - _itemBeingDragged: function (itemIndex) { - if (!this._dragging) { - return false; - } - - return ((this._draggingUnselectedItem && this._dragInfo._isIncluded(itemIndex)) || (!this._draggingUnselectedItem && this.site._isSelected(itemIndex))); - }, - - _addDragSourceClass: function (itemBox) { - this._draggedItemBoxes.push(itemBox); - utilities.addClass(itemBox, WinJS.UI._dragSourceClass); - if (itemBox.parentNode) { - utilities.addClass(itemBox.parentNode, WinJS.UI._footprintClass); - } - }, - - renderDragSourceOnRealizedItem: function (itemIndex, itemBox) { - if (this._itemBeingDragged(itemIndex)) { - this._addDragSourceClass(itemBox); - } - }, - - onDragOver: function (eventObject) { - if (!this._dragUnderstood) { - return; - } - this._pointerLeftRegion = false; - eventObject.preventDefault(); - - var cursorPositionInCanvas = this._getPositionInCanvasSpace(eventObject), - cursorPositionInRoot = this._getEventPositionInElementSpace(this.site.element, eventObject); - this._checkAutoScroll(cursorPositionInRoot.x, cursorPositionInRoot.y); - if (this.site._layout.hitTest) { - if (this._autoScrollFrame) { - if (this._lastInsertPoint) { - this.site._layout.dragLeave(); - this._lastInsertPoint = null; - } - } else { - var insertPoint = this.site._view.hitTest(cursorPositionInCanvas.x, cursorPositionInCanvas.y); - insertPoint.insertAfterIndex = clampToRange(-1, this.site._cachedCount - 1, insertPoint.insertAfterIndex); - if (!this._lastInsertPoint || this._lastInsertPoint.insertAfterIndex !== insertPoint.insertAfterIndex || this._lastInsertPoint.index !== insertPoint.index) { - this._dragBetweenDisabled = !this._fireDragBetweenEvent(insertPoint.index, insertPoint.insertAfterIndex, eventObject.dataTransfer); - if (!this._dragBetweenDisabled) { - this.site._layout.dragOver(cursorPositionInCanvas.x, cursorPositionInCanvas.y, this._dragInfo); - } else { - this.site._layout.dragLeave(); - } - } - this._lastInsertPoint = insertPoint; - } - } - }, - - _clearDragProperties: function () { - if (this._addedDragOverClass) { - this._addedDragOverClass = false; - utilities.removeClass(this.site._element, WinJS.UI._dragOverClass); - } - if (this._draggedItemBoxes) { - for (var i = 0, len = this._draggedItemBoxes.length; i < len; i++) { - utilities.removeClass(this._draggedItemBoxes[i], WinJS.UI._dragSourceClass); - if (this._draggedItemBoxes[i].parentNode) { - utilities.removeClass(this._draggedItemBoxes[i].parentNode, WinJS.UI._footprintClass); - } - } - this._draggedItemBoxes = []; - } - this.site._layout.dragLeave(); - this._dragging = false; - this._dragInfo = null; - this._draggingUnselectedItem = false; - this._dragDataTransfer = null; - this._lastInsertPoint = null; - this._resetPointerDownState(); - this._lastEnteredElement = null; - this._dragBetweenDisabled = false; - this._firedDragEnter = false; - this._dragUnderstood = false; - this._stopAutoScroll(); - }, - - onDragEnd: function (eventObject) { - var event = document.createEvent("CustomEvent"); - event.initCustomEvent("itemdragend", true, false, {}); - this.site.element.dispatchEvent(event); - this._clearDragProperties(); - }, - - _findFirstAvailableInsertPoint: function (selectedItems, startIndex, searchForwards) { - var indicesSelected = selectedItems.getIndices(), - dropIndexInSelection = -1, - count = this.site._cachedCount, - selectionCount = indicesSelected.length, - startIndexInSelection = -1, - dropIndex = startIndex; - for (var i = 0; i < selectionCount; i++) { - if (indicesSelected[i] === dropIndex) { - dropIndexInSelection = i; - startIndexInSelection = i; - break; - } - } - - while (dropIndexInSelection >= 0 && dropIndex >= 0) { - if (searchForwards) { - dropIndex++; - if (dropIndexInSelection < selectionCount && indicesSelected[dropIndexInSelection + 1] === dropIndex && dropIndex < count) { - dropIndexInSelection++; - } else if (dropIndex >= count) { - // If we hit the end of the list when looking for a new location ahead of our start index, it means everything from the starting point - // to the end is selected, so no valid index can be located to move the items. We need to start searching again, moving backwards - // from the starting location, to find the first available insert location to move the selected items. - searchForwards = false; - dropIndex = startIndex; - dropIndexInSelection = startIndexInSelection; - } else { - dropIndexInSelection = -1; - } - } else { - dropIndex--; - if (dropIndexInSelection > 0 && indicesSelected[dropIndexInSelection - 1] === dropIndex) { - dropIndexInSelection--; - } else { - dropIndexInSelection = -1; - } - } - } - - return dropIndex; - }, - - _reorderItems: function (dropIndex, reorderedItems, reorderingUnselectedItem, useMoveBefore, ensureVisibleAtEnd) { - var site = this.site; - var updateSelection = function updatedSelectionOnDrop(items) { - // Update selection if the items were selected. If there is a range with length > 0 a move operation - // on the first or last item removes the range. - if (!reorderingUnselectedItem) { - site._selection.set({ firstKey: items[0].key, lastKey: items[items.length - 1].key }); - } else { - site._selection.remove({ key: items[0].key }); - } - if (ensureVisibleAtEnd) { - site.ensureVisible(site._selection._getFocused()); - } - } - reorderedItems.getItems().then(function (items) { - var ds = site.itemDataSource; - if (dropIndex === -1) { - ds.beginEdits(); - for (var i = items.length - 1; i >= 0; i--) { - ds.moveToStart(items[i].key); - } - ds.endEdits(); - updateSelection(items); - } else { - var listBinding = ds.createListBinding(); - listBinding.fromIndex(dropIndex).then(function (item) { - listBinding.release(); - ds.beginEdits(); - if (useMoveBefore) { - for (var i = 0, len = items.length; i < len; i++) { - ds.moveBefore(items[i].key, item.key); - } - } else { - for (var i = items.length - 1; i >= 0; i--) { - ds.moveAfter(items[i].key, item.key); - } - } - ds.endEdits(); - updateSelection(items); - }); - } - }); - }, - - onDrop: function SelectionMode_onDrop(eventObject) { - // If the listview or the handler of the drop event we fire triggers a reorder, the dragged items can end up having different container nodes than what they started with. - // Because of that, we need to remove the footprint class from the item boxes' containers before we do any processing of the drop event. - if (this._draggedItemBoxes) { - for (var i = 0, len = this._draggedItemBoxes.length; i < len; i++) { - if (this._draggedItemBoxes[i].parentNode) { - utilities.removeClass(this._draggedItemBoxes[i].parentNode, WinJS.UI._footprintClass); - } - } - } - if (!this._dragBetweenDisabled) { - var cursorPosition = this._getPositionInCanvasSpace(eventObject); - var dropLocation = this.site._view.hitTest(cursorPosition.x, cursorPosition.y), - dropIndex = clampToRange(-1, this.site._cachedCount - 1, dropLocation.insertAfterIndex), - allowDrop = true; - // We don't fire dragBetween events during autoscroll, so if a user drops during autoscroll, we need to get up to date information - // on the drop location, and fire dragBetween before the insert so that the developer can prevent the drop if they choose. - if (!this._lastInsertPoint || this._lastInsertPoint.insertAfterIndex !== dropIndex || this._lastInsertPoint.index !== dropLocation.index) { - allowDrop = this._fireDragBetweenEvent(dropLocation.index, dropIndex, eventObject.dataTransfer); - } - if (allowDrop) { - this._lastInsertPoint = null; - this.site._layout.dragLeave(); - if (this._fireDropEvent(dropLocation.index, dropIndex, eventObject.dataTransfer) && this._dragging && this.site.itemsReorderable) { - if (this._dragInfo.isEverything() || this.site._groupsEnabled()) { - return; - } - - dropIndex = this._findFirstAvailableInsertPoint(this._dragInfo, dropIndex, false); - this._reorderItems(dropIndex, this._dragInfo, this._draggingUnselectedItem); - } - } - } - this._clearDragProperties(); - }, - - _checkAutoScroll: function (x, y) { - var viewportSize = this.site._getViewportLength(), - horizontal = this.site._horizontal(), - cursorPositionInViewport = (horizontal ? x : y), - rtl = this.site._rtl(), - canvasMargins = this.site._getCanvasMargins(), - canvasSize = this.site._canvas[horizontal ? "offsetWidth" : "offsetHeight"] + canvasMargins[(horizontal ? (rtl ? "right" : "left") : "top")], - scrollPosition = Math.floor(this.site.scrollPosition), - travelRate = 0; - - if (cursorPositionInViewport < WinJS.UI._AUTOSCROLL_THRESHOLD) { - travelRate = cursorPositionInViewport - WinJS.UI._AUTOSCROLL_THRESHOLD; - } else if (cursorPositionInViewport > (viewportSize - WinJS.UI._AUTOSCROLL_THRESHOLD)) { - travelRate = (cursorPositionInViewport - (viewportSize - WinJS.UI._AUTOSCROLL_THRESHOLD)); - } - travelRate = Math.round((travelRate / WinJS.UI._AUTOSCROLL_THRESHOLD) * (WinJS.UI._MAX_AUTOSCROLL_RATE - WinJS.UI._MIN_AUTOSCROLL_RATE)); - - // If we're at the edge of the content, we don't need to keep scrolling. We'll set travelRate to 0 to stop the autoscroll timer. - if ((scrollPosition === 0 && travelRate < 0) || (scrollPosition >= (canvasSize - viewportSize) && travelRate > 0)) { - travelRate = 0; - } - if (travelRate === 0) { - if (this._autoScrollDelay) { - clearTimeout(this._autoScrollDelay); - this._autoScrollDelay = 0; - } - } else { - if (!this._autoScrollDelay && !this._autoScrollFrame) { - var that = this; - this._autoScrollDelay = setTimeout(function () { - if (that._autoScrollRate) { - that._lastDragTimeout = performance.now(); - var nextFrame = function () { - if ((!that._autoScrollRate && that._autoScrollFrame) || that.site._disposed) { - that._stopAutoScroll(); - } else { - // Timeout callbacks aren't reliably timed, so extra math is needed to figure out how far the scroll position should move since the last callback - var currentTime = performance.now(); - var delta = that._autoScrollRate * ((currentTime - that._lastDragTimeout) / 1000); - delta = (delta < 0 ? Math.min(-1, delta) : Math.max(1, delta)); - that.site._viewport[that.site._scrollProperty] += delta; - that._lastDragTimeout = currentTime; - that._autoScrollFrame = requestAnimationFrame(nextFrame); - } - }; - that._autoScrollFrame = requestAnimationFrame(nextFrame); - } - }, WinJS.UI._AUTOSCROLL_DELAY); - } - } - this._autoScrollRate = travelRate; - }, - - _stopAutoScroll: function () { - if (this._autoScrollDelay) { - clearTimeout(this._autoScrollDelay); - this._autoScrollDelay = 0; - } - this._autoScrollRate = 0; - this._autoScrollFrame = 0; - }, - - onKeyDown: function SelectionMode_onKeyDown(eventObject) { - var that = this, - site = this.site, - swipeEnabled = site._swipeBehavior === WinJS.UI.SwipeBehavior.select, - view = site._view, - oldEntity = site._selection._getFocused(), - handled = true, - handlerName, - ctrlKeyDown = eventObject.ctrlKey; - - function setNewFocus(newEntity, skipSelection, clampToBounds) { - function setNewFocusImpl(maxIndex) { - var moveView = true, - invalidIndex = false; - // Since getKeyboardNavigatedItem is purely geometry oriented, it can return us out of bounds numbers, so this check is necessary - if (clampToBounds) { - newEntity.index = Math.max(0, Math.min(maxIndex, newEntity.index)); - } else if (newEntity.index < 0 || newEntity.index > maxIndex) { - invalidIndex = true; - } - if (!invalidIndex && (oldEntity.index !== newEntity.index || oldEntity.type !== newEntity.type)) { - var changeFocus = dispatchKeyboardNavigating(site._element, oldEntity, newEntity); - if (changeFocus) { - moveView = false; - - // If the oldEntity is completely off-screen then we mimic the desktop - // behavior. This is consistent with navbar keyboarding. - if (that._setNewFocusItemOffsetPromise) { - that._setNewFocusItemOffsetPromise.cancel(); - } - site._batchViewUpdates(WinJS.UI._ViewChange.realize, WinJS.UI._ScrollToPriority.high, function () { - that._setNewFocusItemOffsetPromise = site._getItemOffset(oldEntity, true).then(function (range) { - range = site._convertFromCanvasCoordinates(range); - var oldItemOffscreen = range.end <= site.scrollPosition || range.begin >= site.scrollPosition + site._getViewportLength() - 1; - that._setNewFocusItemOffsetPromise = site._getItemOffset(newEntity).then(function (range) { - that._setNewFocusItemOffsetPromise = null; - var retVal = { - position: site.scrollPosition, - direction: "right" - }; - if (oldItemOffscreen) { - // oldEntity is completely off-screen - site._selection._setFocused(newEntity, true); - range = site._convertFromCanvasCoordinates(range); - if (newEntity.index > oldEntity.index) { - retVal.direction = "right"; - retVal.position = range.end - site._getViewportLength(); - } else { - retVal.direction = "left"; - retVal.position = range.begin; - } - } - site._changeFocus(newEntity, skipSelection, ctrlKeyDown, oldItemOffscreen, true); - if (!oldItemOffscreen) { - return Promise.cancel; - } else { - return retVal; - } - }, function (error) { - site._changeFocus(newEntity, skipSelection, ctrlKeyDown, true, true); - return Promise.wrapError(error); - }); - return that._setNewFocusItemOffsetPromise; - }, function (error) { - site._changeFocus(newEntity, skipSelection, ctrlKeyDown, true, true); - return Promise.wrapError(error); - }); - return that._setNewFocusItemOffsetPromise; - }, true); - } - } - // When a key is pressed, we want to make sure the current focus is in view. If the keypress is changing to a new valid index, - // _changeFocus will handle moving the viewport for us. If the focus isn't moving, though, we need to put the view back on - // the current item ourselves and call setFocused(oldFocus, true) to make sure that the listview knows the focused item was - // focused via keyboard and renders the rectangle appropriately. - if (moveView) { - site._selection._setFocused(oldEntity, true); - site.ensureVisible(oldEntity); - } - if (invalidIndex) { - return { type: WinJS.UI.ObjectType.item, index: WinJS.UI._INVALID_INDEX }; - } else { - return newEntity; - } - } - - // We need to get the final item in the view so that we don't try setting focus out of bounds. - if (newEntity.type !== WinJS.UI.ObjectType.groupHeader) { - return view.finalItem().then(setNewFocusImpl); - } else { - return Promise.wrap(site._groups.length() - 1).then(setNewFocusImpl); - } - } - - var Key = utilities.Key, - keyCode = eventObject.keyCode, - rtl = site._rtl(); - - if (!this._isInteractive(eventObject.srcElement)) { - if (eventObject.ctrlKey && !eventObject.altKey && !eventObject.shiftKey && this._keyboardAcceleratorHandlers[keyCode]) { - this._keyboardAcceleratorHandlers[keyCode](); - } - if (site.itemsReorderable && (!eventObject.ctrlKey && eventObject.altKey && eventObject.shiftKey && oldEntity.type === WinJS.UI.ObjectType.item) && - (keyCode === Key.leftArrow || keyCode === Key.rightArrow || keyCode === Key.upArrow || keyCode === Key.downArrow)) { - var selection = site._selection, - focusedIndex = oldEntity.index, - movingUnselectedItem = false, - processReorder = true; - if (!selection.isEverything()) { - if (!selection._isIncluded(focusedIndex)) { - var item = site._view.items.itemAt(focusedIndex); - // Selected items should never be marked as non draggable, so we only need to check for nonDraggableClass when trying to reorder an unselected item. - if (item && utilities.hasClass(item, WinJS.UI._nonDraggableClass)) { - processReorder = false; - } else { - movingUnselectedItem = true; - selection = new WinJS.UI._Selection(this.site, [{ firstIndex: focusedIndex, lastIndex: focusedIndex }]); - } - } - if (processReorder) { - var dropIndex = focusedIndex; - if (keyCode === Key.rightArrow) { - dropIndex += (rtl ? -1 : 1); - } else if (keyCode === Key.leftArrow) { - dropIndex += (rtl ? 1 : -1); - } else if (keyCode === Key.upArrow) { - dropIndex--; - } else { - dropIndex++; - } - // If the dropIndex is larger than the original index, we're trying to move items forward, so the search for the first unselected item to insert after should move forward. - var movingAhead = (dropIndex > focusedIndex), - searchForward = movingAhead; - if (movingAhead && dropIndex >= this.site._cachedCount) { - // If we're at the end of the list and trying to move items forward, dropIndex should be >= cachedCount. - // That doesn't mean we don't have to do any reordering, though. A selection could be broken down into - // a few blocks. We need to make the selection contiguous after this reorder, so we've got to search backwards - // to find the first unselected item, then move everything in the selection after it. - searchForward = false; - dropIndex = this.site._cachedCount - 1; - } - dropIndex = this._findFirstAvailableInsertPoint(selection, dropIndex, searchForward); - dropIndex = Math.min(Math.max(-1, dropIndex), this.site._cachedCount - 1); - var reportedInsertAfterIndex = dropIndex - (movingAhead || dropIndex === -1 ? 0 : 1), - reportedIndex = dropIndex, - groupsEnabled = this.site._groupsEnabled(); - - if (groupsEnabled) { - // The indices we picked for the index/insertAfterIndex to report in our events is always correct in an ungrouped list, - // and mostly correct in a grouped list. The only problem occurs when you move an item (or items) ahead into a new group, - // or back into a previous group, such that the items should be the first/last in the group. Take this list as an example: - // [Group A] [a] [b] [c] [Group B] [d] [e] - // When [d] is focused, right/down arrow reports index: 4, insertAfterIndex: 4, which is right -- it means move [d] after [e]. - // Similarily, when [c] is focused and left/up is pressed, we report index: 1, insertAfterIndex: 0 -- move [c] to after [a]. - // Take note that index does not tell us where focus is / what item is being moved. - // Like mouse/touch DnD, index tells us what the dragBetween slots would be were we to animate a dragBetween. - // The problem cases are moving backwards into a previous group, or forward into the next group. - // If [c] were focused and the user pressed right/down, we would report index: 3, insertAfterIndex: 3. In other words, move [c] after [d]. - // That's not right at all - [c] needs to become the first element of [Group B]. When we're moving ahead, then, and our dropIndex - // is the first index of a new group, we adjust insertAfterIndex to be dropIndex - 1. Now we'll report index:3, insertAfterIndex: 2, which means - // [c] is now the first element of [Group B], rather than the last element of [Group A]. This is exactly the same as what we would report when - // the user mouse/touch drags [c] right before [d]. - // Similarily, when [d] is focused and we press left/up, without the logic below we would report index: 2, insertAfterIndex: 1, so we'd try to move - // [d] ahead of [b]. Again, [d] first needs the opportunity to become the last element in [Group A], so we adjust the insertAfterIndex up by 1. - // We then will report index:2, insertAfterIndex:2, meaning insert [d] in [Group A] after [c], which again mimics the mouse/touch API. - var groups = this.site._groups, - groupIndex = (dropIndex > -1 ? groups.groupFromItem(dropIndex) : 0); - if (movingAhead) { - if (groups.group(groupIndex).startIndex === dropIndex) { - reportedInsertAfterIndex--; - } - } else if (groupIndex < (groups.length() - 1) && dropIndex === (groups.group(groupIndex + 1).startIndex - 1)) { - reportedInsertAfterIndex++; - } - } - - if (this._fireDragBetweenEvent(reportedIndex, reportedInsertAfterIndex, null) && this._fireDropEvent(reportedIndex, reportedInsertAfterIndex, null)) { - if (groupsEnabled) { - return; - } - - this._reorderItems(dropIndex, selection, movingUnselectedItem, !movingAhead, true); - } - } - } - } else if (!eventObject.altKey) { - - if (this._keyboardNavigationHandlers[keyCode]) { - this._keyboardNavigationHandlers[keyCode](oldEntity).then(function (newEntity) { - var clampToBounds = that._keyboardNavigationHandlers[keyCode].clampToBounds; - if (newEntity.type !== WinJS.UI.ObjectType.groupHeader && eventObject.shiftKey && site._selectionAllowed() && site._multiSelection()) { - // Shift selection should work when shift or shift+ctrl are depressed - if (site._selection._pivot === WinJS.UI._INVALID_INDEX) { - site._selection._pivot = oldEntity.index; - } - setNewFocus(newEntity, true, clampToBounds).then(function (newEntity) { - if (newEntity.index !== WinJS.UI._INVALID_INDEX) { - var firstIndex = Math.min(newEntity.index, site._selection._pivot), - lastIndex = Math.max(newEntity.index, site._selection._pivot), - additive = (eventObject.ctrlKey || site._tap === WinJS.UI.TapBehavior.toggleSelect); - that._selectRange(firstIndex, lastIndex, additive); - } - }); - } else { - site._selection._pivot = WinJS.UI._INVALID_INDEX; - setNewFocus(newEntity, false, clampToBounds); - } - }); - } else if (!eventObject.ctrlKey && keyCode === Key.enter) { - var element = oldEntity.type === WinJS.UI.ObjectType.groupHeader ? site._groups.group(oldEntity.index).header : site._view.items.itemBoxAt(oldEntity.index); - if (element) { - if (oldEntity.type === WinJS.UI.ObjectType.groupHeader) { - this._pressedHeader = element; - this._pressedItemBox = null; - this._pressedContainer = null; - } else { - this._pressedItemBox = element; - this._pressedContainer = site._view.items.containerAt(oldEntity.index); - this._pressedHeader = null; - } - - var allowed = this._verifySelectionAllowed(oldEntity); - if (allowed.canTapSelect) { - this._itemEventsHandler.handleTap(oldEntity); - } - this._fireInvokeEvent(oldEntity, element); - } - } else if (oldEntity.type !== WinJS.UI.ObjectType.groupHeader && - ((eventObject.ctrlKey && keyCode === Key.enter) || - (swipeEnabled && eventObject.shiftKey && keyCode === Key.F10) || - (swipeEnabled && keyCode === Key.menu) || - keyCode === Key.space)) { - // Swipe emulation - this._itemEventsHandler.handleSwipeBehavior(oldEntity.index); - site._changeFocus(oldEntity, true, ctrlKeyDown, false, true); - } else if (keyCode === Key.escape && site._selection.count() > 0) { - site._selection._pivot = WinJS.UI._INVALID_INDEX; - site._selection.clear(); - } else { - handled = false; - } - } else { - handled = false; - } - - this._keyDownHandled = handled; - if (handled) { - eventObject.stopPropagation(); - eventObject.preventDefault(); - } - } - - if (keyCode === Key.tab) { - this.site._keyboardFocusInbound = true; - } - }, - - onKeyUp: function (eventObject) { - if (this._keyDownHandled) { - eventObject.stopPropagation(); - eventObject.preventDefault(); - } - }, - - onTabEnter: function (eventObject) { - if (this.site._groups.length() == 0) { - return; - } - - var site = this.site, - focused = site._selection._getFocused(), - forward = eventObject.detail; - - // We establish whether focus is incoming on the ListView by checking keyboard focus and the srcElement. - // If the ListView did not have keyboard focus, then it is definitely incoming since keyboard focus is cleared - // on blur which works for 99% of all scenarios. When the ListView is the only tabbable element on the page, - // then tabbing out of the ListView will make focus wrap around and focus the ListView again. The blur event is - // handled after TabEnter, so the keyboard focus flag is not yet cleared. Therefore, we examine the srcElement and see - // if it is the canvas/surface since it is the first tabbable element in the ListView DOM tree. - var inboundFocus = !site._hasKeyboardFocus || eventObject.srcElement === site._canvas; - if (inboundFocus) { - this.inboundFocusHandled = true; - - // We tabbed into the ListView - focused.index = (focused.index === WinJS.UI._INVALID_INDEX ? 0 : focused.index); - - if (forward || !this.site._supportsGroupHeaderKeyboarding) { - // We tabbed into the ListView from before the ListView, so focus should go to items - var entity = { type: WinJS.UI.ObjectType.item }; - if (focused.type === WinJS.UI.ObjectType.groupHeader) { - entity.index = site._groupFocusCache.getIndexForGroup(focused.index); - if (dispatchKeyboardNavigating(site._element, focused, entity)) { - site._changeFocus(entity, true, false, false, true); - } else { - site._changeFocus(focused, true, false, false, true); - } - } else { - entity.index = focused.index; - site._changeFocus(entity, true, false, false, true); - } - - } else { - // We tabbed into the ListView from after the ListView, focus should go to headers - var entity = { type: WinJS.UI.ObjectType.groupHeader }; - if (focused.type !== WinJS.UI.ObjectType.groupHeader) { - entity.index = site._groups.groupFromItem(focused.index); - if (dispatchKeyboardNavigating(site._element, focused, entity)) { - site._changeFocus(entity, true, false, false, true); - } else { - site._changeFocus(focused, true, false, false, true); - } - } else { - entity.index = focused.index; - site._changeFocus(entity, true, false, false, true); - } - } - } - }, - - onTabExit: function (eventObject) { - if (!this.site._supportsGroupHeaderKeyboarding || this.site._groups.length() == 0) { - return; - } - - var site = this.site, - focused = site._selection._getFocused(), - forward = eventObject.detail; - - if (forward && focused.type !== WinJS.UI.ObjectType.groupHeader) { - // Tabbing and we were focusing an item, go to headers - var entity = { type: WinJS.UI.ObjectType.groupHeader, index: site._groups.groupFromItem(focused.index) }; - if (dispatchKeyboardNavigating(site._element, focused, entity)) { - site._changeFocus(entity, true, false, false, true); - } - } else if (!forward && focused.type === WinJS.UI.ObjectType.groupHeader) { - // Shift tabbing and we were focusing a header, go to items - var entity = { type: WinJS.UI.ObjectType.item, index: site._groupFocusCache.getIndexForGroup(focused.index) }; - if (dispatchKeyboardNavigating(site._element, focused, entity)) { - site._changeFocus(entity, true, false, false, true); - } - } - } - }; - return _SelectionMode; - }) - }); - -})(this, WinJS); -(function constantsInit(global, WinJS, undefined) { - "use strict"; - - var thisWinUI = WinJS.UI; - thisWinUI._listViewClass = "win-listview"; - thisWinUI._viewportClass = "win-viewport"; - thisWinUI._rtlListViewClass = "win-rtl"; - thisWinUI._horizontalClass = "win-horizontal"; - thisWinUI._verticalClass = "win-vertical"; - thisWinUI._scrollableClass = "win-surface"; - thisWinUI._itemsContainerClass = "win-itemscontainer"; - thisWinUI._padderClass = "win-itemscontainer-padder"; - thisWinUI._proxyClass = "_win-proxy"; - thisWinUI._itemClass = "win-item"; - thisWinUI._itemBoxClass = "win-itembox"; - thisWinUI._itemsBlockClass = "win-itemsblock"; - thisWinUI._containerClass = "win-container"; - thisWinUI._backdropClass = "win-backdrop"; - thisWinUI._footprintClass = "win-footprint"; - thisWinUI._groupsClass = "win-groups"; - thisWinUI._selectedClass = "win-selected"; - thisWinUI._swipeableClass = "win-swipeable"; - thisWinUI._swipeClass = "win-swipe"; - thisWinUI._selectionBorderClass = "win-selectionborder"; - thisWinUI._selectionBackgroundClass = "win-selectionbackground"; - thisWinUI._selectionCheckmarkClass = "win-selectioncheckmark"; - thisWinUI._selectionCheckmarkBackgroundClass = "win-selectioncheckmarkbackground"; - thisWinUI._selectionPartsSelector = ".win-selectionborder, .win-selectionbackground, .win-selectioncheckmark, .win-selectioncheckmarkbackground"; - thisWinUI._pressedClass = "win-pressed"; - thisWinUI._headerClass = "win-groupheader"; - thisWinUI._headerContainerClass = "win-groupheadercontainer"; - thisWinUI._groupLeaderClass = "win-groupleader"; - thisWinUI._progressClass = "win-progress"; - thisWinUI._selectionHintClass = "win-selectionhint"; - thisWinUI._revealedClass = "win-revealed"; - thisWinUI._itemFocusClass = "win-focused"; - thisWinUI._itemFocusOutlineClass = "win-focusedoutline"; - thisWinUI._zoomingXClass = "win-zooming-x"; - thisWinUI._zoomingYClass = "win-zooming-y"; - thisWinUI._listLayoutClass = "win-listlayout"; - thisWinUI._gridLayoutClass = "win-gridlayout"; - thisWinUI._headerPositionTopClass = "win-headerpositiontop"; - thisWinUI._headerPositionLeftClass = "win-headerpositionleft"; - thisWinUI._structuralNodesClass = "win-structuralnodes"; - thisWinUI._uniformGridLayoutClass = "win-uniformgridlayout"; - thisWinUI._uniformListLayoutClass = "win-uniformlistlayout"; - thisWinUI._cellSpanningGridLayoutClass = "win-cellspanninggridlayout"; - thisWinUI._laidOutClass = "win-laidout"; - thisWinUI._nonDraggableClass = "win-nondraggable"; - thisWinUI._nonSelectableClass = "win-nonselectable"; - thisWinUI._nonSwipeableClass = "win-nonswipeable"; - thisWinUI._dragOverClass = "win-dragover"; - thisWinUI._dragSourceClass = "win-dragsource"; - thisWinUI._clipClass = "win-clip"; - - thisWinUI._INVALID_INDEX = -1; - thisWinUI._UNINITIALIZED = -1; - - thisWinUI._LEFT_MSPOINTER_BUTTON = 0; - thisWinUI._RIGHT_MSPOINTER_BUTTON = 2; - - thisWinUI._TAP_END_THRESHOLD = 10; - - thisWinUI._DEFAULT_PAGES_TO_LOAD = 5; - thisWinUI._DEFAULT_PAGE_LOAD_THRESHOLD = 2; - - thisWinUI._MIN_AUTOSCROLL_RATE = 150; - thisWinUI._MAX_AUTOSCROLL_RATE = 1500; - thisWinUI._AUTOSCROLL_THRESHOLD = 100; - thisWinUI._AUTOSCROLL_DELAY = 50; - - thisWinUI._DEFERRED_ACTION = 250; - thisWinUI._DEFERRED_SCROLL_END = 250; - - // For horizontal layouts - thisWinUI._VERTICAL_SWIPE_SELECTION_THRESHOLD = 39; - thisWinUI._VERTICAL_SWIPE_SPEED_BUMP_START = 0; - thisWinUI._VERTICAL_SWIPE_SPEED_BUMP_END = 127; - thisWinUI._VERTICAL_SWIPE_SELF_REVEAL_GESTURE = 15; - - // For vertical layouts - thisWinUI._HORIZONTAL_SWIPE_SELECTION_THRESHOLD = 27; - thisWinUI._HORIZONTAL_SWIPE_SPEED_BUMP_START = 0; - thisWinUI._HORIZONTAL_SWIPE_SPEED_BUMP_END = 150; - thisWinUI._HORIZONTAL_SWIPE_SELF_REVEAL_GESTURE = 23; - - thisWinUI._SELECTION_CHECKMARK = "\uE081"; - - thisWinUI._LISTVIEW_PROGRESS_DELAY = 2000; -})(this, WinJS); - -(function errorMessagesInit(global, WinJS, undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI._strings", { - - modeIsInvalid: { - get: function () { return WinJS.Resources._getWinJSString("ui/modeIsInvalid").value; } - }, - - loadingBehaviorIsDeprecated: { - get: function () { return WinJS.Resources._getWinJSString("ui/loadingBehaviorIsDeprecated").value; } - }, - - pagesToLoadIsDeprecated: { - get: function () { return WinJS.Resources._getWinJSString("ui/pagesToLoadIsDeprecated").value; } - }, - - pagesToLoadThresholdIsDeprecated: { - get: function () { return WinJS.Resources._getWinJSString("ui/pagesToLoadThresholdIsDeprecated").value; } - }, - - automaticallyLoadPagesIsDeprecated: { - get: function () { return WinJS.Resources._getWinJSString("ui/automaticallyLoadPagesIsDeprecated").value; } - }, - - invalidTemplate: { - get: function () { return WinJS.Resources._getWinJSString("ui/invalidTemplate").value; } - }, - - loadMorePagesIsDeprecated: { - get: function () { return WinJS.Resources._getWinJSString("ui/loadMorePagesIsDeprecated").value; } - }, - - disableBackdropIsDeprecated: { - get: function () { return WinJS.Resources._getWinJSString("ui/disableBackdropIsDeprecated").value; } - }, - - backdropColorIsDeprecated: { - get: function () { return WinJS.Resources._getWinJSString("ui/backdropColorIsDeprecated").value; } - }, - - itemInfoIsDeprecated: { - get: function () { return WinJS.Resources._getWinJSString("ui/itemInfoIsDeprecated").value; } - }, - - groupInfoIsDeprecated: { - get: function () { return WinJS.Resources._getWinJSString("ui/groupInfoIsDeprecated").value; } - }, - - resetItemIsDeprecated: { - get: function () { return WinJS.Resources._getWinJSString("ui/resetItemIsDeprecated").value; } - }, - - resetGroupHeaderIsDeprecated: { - get: function () { return WinJS.Resources._getWinJSString("ui/resetGroupHeaderIsDeprecated").value; } - }, - - maxRowsIsDeprecated: { - get: function() { return WinJS.Resources._getWinJSString("ui/maxRowsIsDeprecated").value; } - } - }); - -})(this, WinJS); - -(function GroupFocusCacheInit() { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - _GroupFocusCache: WinJS.Namespace._lazy(function () { - return WinJS.Class.define(function GroupFocusCache_ctor(listView) { - this._listView = listView; - this.clear(); - }, { - // We store indices as strings in the cache so index=0 does not evaluate to false as - // when we check for the existance of an index in the cache. The index is converted - // back into a number when calling getIndexForGroup - - updateCache: function (groupKey, itemKey, itemIndex) { - itemIndex = "" + itemIndex; - this._itemToIndex[itemKey] = itemIndex; - this._groupToItem[groupKey] = itemKey; - }, - - deleteItem: function (itemKey) { - if (!this._itemToIndex[itemKey]) { - return; - } - - var that = this; - var keys = Object.keys(this._groupToItem); - for (var i = 0, len = keys.length; i < len; i++) { - var key = keys[i]; - if (that._groupToItem[key] === itemKey) { - that.deleteGroup(key); - break; - } - } - }, - - deleteGroup: function (groupKey) { - var itemKey = this._groupToItem[groupKey]; - if (itemKey) { - delete this._itemToIndex[itemKey]; - } - delete this._groupToItem[groupKey]; - }, - - updateItemIndex: function (itemKey, itemIndex) { - if (!this._itemToIndex[itemKey]) { - return; - } - this._itemToIndex[itemKey] = "" + itemIndex; - }, - - getIndexForGroup: function (groupIndex) { - var groupKey = this._listView._groups.group(groupIndex).key; - - var itemKey = this._groupToItem[groupKey]; - if (itemKey && this._itemToIndex[itemKey]) { - return +this._itemToIndex[itemKey]; - } else { - return this._listView._groups.fromKey(groupKey).group.startIndex; - } - }, - - clear: function () { - this._groupToItem = {}; - this._itemToIndex = {}; - } - }); - }), - - _UnsupportedGroupFocusCache: WinJS.Namespace._lazy(function () { - return WinJS.Class.define(null, { - updateCache: function (groupKey, itemKey, itemIndex) { - }, - - deleteItem: function (itemKey) { - }, - - deleteGroup: function (groupKey) { - }, - - updateItemIndex: function (itemKey, itemIndex) { - }, - - getIndexForGroup: function (groupIndex) { - return 0; - }, - - clear: function () { - } - }); - }) - }); - -})(); -(function groupsContainerInit(global, WinJS, undefined) { - "use strict"; - - var utilities = WinJS.Utilities, - Promise = WinJS.Promise; - - WinJS.Namespace.define("WinJS.UI", { - _GroupsContainerBase: WinJS.Namespace._lazy(function () { - return WinJS.Class.define(function () { - }, { - index: function (element) { - var header = this.headerFrom(element); - if (header) { - for (var i = 0, len = this.groups.length; i < len; i++) { - if (header === this.groups[i].header) { - return i; - } - } - } - return WinJS.UI._INVALID_INDEX; - }, - - headerFrom: function (element) { - while (element && !utilities.hasClass(element, WinJS.UI._headerClass)) { - element = element.parentNode; - } - return element; - }, - - requestHeader: function GroupsContainerBase_requestHeader(index) { - this._waitingHeaderRequests = this._waitingHeaderRequests || {}; - if (!this._waitingHeaderRequests[index]) { - this._waitingHeaderRequests[index] = []; - } - - var that = this; - return new Promise(function (complete, error) { - var group = that.groups[index]; - if (group && group.header) { - complete(group.header); - } else { - that._waitingHeaderRequests[index].push(complete); - } - }); - }, - - notify: function GroupsContainerBase_notify(index, header) { - if (this._waitingHeaderRequests && this._waitingHeaderRequests[index]) { - var requests = this._waitingHeaderRequests[index]; - for (var i = 0, len = requests.length; i < len; i++) { - requests[i](header); - } - - this._waitingHeaderRequests[index] = []; - } - }, - - groupFromImpl: function GroupsContainerBase_groupFromImpl(fromGroup, toGroup, comp) { - if (toGroup < fromGroup) { - return null; - } - - var center = fromGroup + Math.floor((toGroup - fromGroup) / 2), - centerGroup = this.groups[center]; - - if (comp(centerGroup, center)) { - return this.groupFromImpl(fromGroup, center - 1, comp); - } else if (center < toGroup && !comp(this.groups[center + 1], center + 1)) { - return this.groupFromImpl(center + 1, toGroup, comp); - } else { - return center; - } - }, - - groupFrom: function GroupsContainerBase_groupFrom(comp) { - //#DBG _ASSERT(this.assertValid()); - if (this.groups.length > 0) { - var lastGroupIndex = this.groups.length - 1, - lastGroup = this.groups[lastGroupIndex]; - - if (!comp(lastGroup, lastGroupIndex)) { - return lastGroupIndex; - } else { - return this.groupFromImpl(0, this.groups.length - 1, comp); - } - } else { - return null; - } - }, - - groupFromItem: function GroupsContainerBase_groupFromItem(itemIndex) { - return this.groupFrom(function (group) { - return itemIndex < group.startIndex; - }); - }, - - groupFromOffset: function GroupsContainerBase_groupFromOffset(offset) { - //#DBG _ASSERT(this.assertValid()); - return this.groupFrom(function (group, groupIndex) { - //#DBG _ASSERT(group.offset !== undefined); - return offset < group.offset; - }); - }, - - group: function GroupsContainerBase_getGroup(index) { - return this.groups[index]; - }, - - length: function GroupsContainerBase_length() { - return this.groups.length; - }, - - cleanUp: function GroupsContainerBase_cleanUp() { - if (this.listBinding) { - for (var i = 0, len = this.groups.length; i < len; i++) { - var group = this.groups[i]; - if (group.userData) { - this.listBinding.releaseItem(group.userData); - } - } - this.listBinding.release(); - } - }, - - _dispose: function GroupsContainerBase_dispose() { - this.cleanUp(); - }, - - /*#DBG - assertValid: function () { - if (WinJS.validation) { - if (this.groups.length) { - var prevIndex = this.groups[0].startIndex, - prevKey = this.groups[0].key, - keys = {}; - - //#DBG _ASSERT(prevIndex === 0); - keys[prevKey] = true; - - for (var i = 1, len = this.groups.length; i < len; i++) { - var group = this.groups[i]; - //#DBG _ASSERT(group.startIndex > prevIndex); - prevIndex = group.startIndex; - - //#DBG _ASSERT(!keys[group.key]); - keys[group.key] = true; - - prevKey = group.key; - } - } - } - return true; - }, - #DBG*/ - - synchronizeGroups: function GroupsContainerBase_synchronizeGroups() { - var that = this; - - this.pendingChanges = []; - this.ignoreChanges = true; - return this.groupDataSource.invalidateAll().then(function () { - return Promise.join(that.pendingChanges); - }).then(function () { - if (that._listView._ifZombieDispose()) { - return WinJS.Promise.cancel; - } - }).then( - function () { - that.ignoreChanges = false; - }, - function (error) { - that.ignoreChanges = false; - return WinJS.Promise.wrapError(error); - } - ); - }, - - fromKey: function GroupsContainerBase_fromKey(key) { - for (var i = 0, len = this.groups.length; i < len; i++) { - var group = this.groups[i]; - if (group.key === key) { - return { - group: group, - index: i - } - } - } - return null; - }, - - fromHandle: function GroupsContainerBase_fromHandle(handle) { - for (var i = 0, len = this.groups.length; i < len; i++) { - var group = this.groups[i]; - if (group.handle === handle) { - return { - group: group, - index: i - } - } - } - return null; - } - }); - }), - - _UnvirtualizedGroupsContainer: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(WinJS.UI._GroupsContainerBase, function (listView, groupDataSource) { - this._listView = listView; - this.groupDataSource = groupDataSource; - this.groups = []; - this.pendingChanges = []; - this.dirty = true; - - var that = this, - notificationHandler = { - beginNotifications: function GroupsContainer_beginNotifications() { - that._listView._versionManager.beginNotifications(); - }, - - endNotifications: function GroupsContainer_endNotifications() { - //#DBG _ASSERT(that.assertValid()); - that._listView._versionManager.endNotifications(); - - if (that._listView._ifZombieDispose()) { return; } - - if (!that.ignoreChanges && that._listView._groupsChanged) { - that._listView._scheduleUpdate(); - } - }, - - indexChanged: function GroupsContainer_indexChanged(item, newIndex, oldIndex) { - that._listView._versionManager.receivedNotification(); - - if (that._listView._ifZombieDispose()) { return; } - - this.scheduleUpdate(); - }, - - itemAvailable: function GroupsContainer_itemAvailable(item, placeholder) { - }, - - countChanged: function GroupsContainer_countChanged(newCount, oldCount) { - that._listView._versionManager.receivedNotification(); - - that._listView._writeProfilerMark("groupCountChanged(" + newCount + "),info"); - - if (that._listView._ifZombieDispose()) { return; } - - this.scheduleUpdate(); - }, - - changed: function GroupsContainer_changed(newItem, oldItem) { - that._listView._versionManager.receivedNotification(); - - if (that._listView._ifZombieDispose()) { return; } - - //#DBG _ASSERT(newItem.key == oldItem.key); - var groupEntry = that.fromKey(newItem.key); - if (groupEntry) { - that._listView._writeProfilerMark("groupChanged(" + groupEntry.index + "),info"); - - groupEntry.group.userData = newItem; - groupEntry.group.startIndex = newItem.firstItemIndexHint; - //#DBG _ASSERT(that.assertValid()); - this.markToRemove(groupEntry.group); - } - - this.scheduleUpdate(); - }, - - removed: function GroupsContainer_removed(itemHandle, mirage) { - that._listView._versionManager.receivedNotification(); - that._listView._groupRemoved(itemHandle); - - if (that._listView._ifZombieDispose()) { return; } - - var groupEntry = that.fromHandle(itemHandle); - if (groupEntry) { - that._listView._writeProfilerMark("groupRemoved(" + groupEntry.index + "),info"); - - that.groups.splice(groupEntry.index, 1); - var index = that.groups.indexOf(groupEntry.group, groupEntry.index); - - if (index > -1) { - that.groups.splice(index, 1); - } - - //#DBG _ASSERT(that.assertValid()); - this.markToRemove(groupEntry.group); - } - - this.scheduleUpdate(); - }, - - inserted: function GroupsContainer_inserted(itemPromise, previousHandle, nextHandle) { - that._listView._versionManager.receivedNotification(); - - if (that._listView._ifZombieDispose()) { return; } - - that._listView._writeProfilerMark("groupInserted,info"); - - var notificationHandler = this; - itemPromise.retain().then(function (item) { - //#DBG _ASSERT(!that.fromKey(item.key)) - - var index; - if (!previousHandle && !nextHandle && !that.groups.length) { - index = 0; - } else { - index = notificationHandler.findIndex(previousHandle, nextHandle); - } - if (index !== -1) { - var newGroup = { - key: item.key, - startIndex: item.firstItemIndexHint, - userData: item, - handle: itemPromise.handle - }; - - that.groups.splice(index, 0, newGroup); - } - notificationHandler.scheduleUpdate(); - }); - that.pendingChanges.push(itemPromise); - }, - - moved: function GroupsContainer_moved(itemPromise, previousHandle, nextHandle) { - that._listView._versionManager.receivedNotification(); - - if (that._listView._ifZombieDispose()) { return; } - - that._listView._writeProfilerMark("groupMoved,info"); - - var notificationHandler = this; - itemPromise.then(function (item) { - var newIndex = notificationHandler.findIndex(previousHandle, nextHandle), - groupEntry = that.fromKey(item.key); - - if (groupEntry) { - that.groups.splice(groupEntry.index, 1); - - if (newIndex !== -1) { - if (groupEntry.index < newIndex) { - newIndex--; - } - - groupEntry.group.key = item.key; - groupEntry.group.userData = item; - groupEntry.group.startIndex = item.firstItemIndexHint; - that.groups.splice(newIndex, 0, groupEntry.group); - } - - } else if (newIndex !== -1) { - var newGroup = { - key: item.key, - startIndex: item.firstItemIndexHint, - userData: item, - handle: itemPromise.handle - }; - that.groups.splice(newIndex, 0, newGroup); - itemPromise.retain(); - } - - //#DBG _ASSERT(that.assertValid()); - notificationHandler.scheduleUpdate(); - }); - that.pendingChanges.push(itemPromise); - }, - - reload: function GroupsContainer_reload() { - that._listView._versionManager.receivedNotification(); - - if (that._listView._ifZombieDispose()) { - return; - } - - that._listView._processReload(); - }, - - markToRemove: function GroupsContainer_markToRemove(group) { - if (group.header) { - var header = group.header; - group.header = null; - group.left = -1; - group.width = -1; - group.decorator = null; - group.tabIndex = -1; - header.tabIndex = -1; - - that._listView._groupsToRemove[header.uniqueID] = { group: group, header: header }; - } - }, - - scheduleUpdate: function GroupsContainer_scheduleUpdate() { - that.dirty = true; - if (!that.ignoreChanges) { - that._listView._groupsChanged = true; - } - }, - - findIndex: function GroupsContainer_findIndex(previousHandle, nextHandle) { - var index = -1, - groupEntry; - - if (previousHandle) { - groupEntry = that.fromHandle(previousHandle); - if (groupEntry) { - index = groupEntry.index + 1; - } - } - - if (index === -1 && nextHandle) { - groupEntry = that.fromHandle(nextHandle); - if (groupEntry) { - index = groupEntry.index; - } - } - - return index; - }, - - removeElements: function GroupsContainer_removeElements(group) { - if (group.header) { - var parentNode = group.header.parentNode; - if (parentNode) { - WinJS.Utilities.disposeSubTree(group.header); - parentNode.removeChild(group.header); - } - group.header = null; - group.left = -1; - group.width = -1; - } - } - }; - - this.listBinding = this.groupDataSource.createListBinding(notificationHandler); - }, { - initialize: function UnvirtualizedGroupsContainer_initialize() { - if (this.initializePromise) { - this.initializePromise.cancel(); - } - - this._listView._writeProfilerMark("GroupsContainer_initialize,StartTM"); - - var that = this; - this.initializePromise = this.groupDataSource.getCount().then(function (count) { - var promises = []; - for (var i = 0; i < count; i++) { - promises.push(that.listBinding.fromIndex(i).retain()); - } - return Promise.join(promises); - }).then( - function (groups) { - that.groups = []; - - for (var i = 0, len = groups.length; i < len; i++) { - var group = groups[i]; - - that.groups.push({ - key: group.key, - startIndex: group.firstItemIndexHint, - handle: group.handle, - userData: group, - }); - } - that._listView._writeProfilerMark("GroupsContainer_initialize groups(" + groups.length + "),info"); - that._listView._writeProfilerMark("GroupsContainer_initialize,StopTM"); - }, - function (error) { - that._listView._writeProfilerMark("GroupsContainer_initialize,StopTM"); - return WinJS.Promise.wrapError(error); - }); - return this.initializePromise; - }, - - renderGroup: function UnvirtualizedGroupsContainer_renderGroup(index) { - if (this._listView.groupHeaderTemplate) { - var group = this.groups[index]; - return Promise.wrap(this._listView._groupHeaderRenderer(Promise.wrap(group.userData))).then(WinJS.UI._normalizeRendererReturn); - } else { - return Promise.wrap(null); - } - }, - - setDomElement: function UnvirtualizedGroupsContainer_setDomElement(index, headerElement) { - this.groups[index].header = headerElement; - this.notify(index, headerElement); - }, - - removeElements: function UnvirtualizedGroupsContainer_removeElements() { - var elements = this._listView._groupsToRemove || {}, - keys = Object.keys(elements), - focusedItemPurged = false; - - var focused = this._listView._selection._getFocused(); - for (var i = 0, len = keys.length; i < len; i++) { - var group = elements[keys[i]], - header = group.header, - groupData = group.group; - - if (!focusedItemPurged && focused.type === WinJS.UI.ObjectType.groupHeader && groupData.userData.index === focused.index) { - this._listView._unsetFocusOnItem(); - focusedItemPurged = true; - } - - if (header) { - var parentNode = header.parentNode; - if (parentNode) { - WinJS.Utilities._disposeElement(header); - parentNode.removeChild(header); - } - } - } - - if (focusedItemPurged) { - this._listView._setFocusOnItem(focused); - } - - this._listView._groupsToRemove = {}; - }, - - resetGroups: function UnvirtualizedGroupsContainer_resetGroups() { - var groups = this.groups.slice(0); - - for (var i = 0, len = groups.length; i < len; i++) { - var group = groups[i]; - - if (this.listBinding && group.userData) { - this.listBinding.releaseItem(group.userData); - } - } - - // Set the lengths to zero to clear the arrays, rather than setting = [], which re-instantiates - this.groups.length = 0; - this.dirty = true; - } - }); - }), - - _NoGroups: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(WinJS.UI._GroupsContainerBase, function (listView) { - this._listView = listView; - this.groups = [{ startIndex: 0 }]; - this.dirty = true; - }, { - synchronizeGroups: function () { - return WinJS.Promise.wrap(); - }, - - addItem: function (itemIndex, itemPromise) { - return WinJS.Promise.wrap(this.groups[0]); - }, - - resetGroups: function () { - this.groups = [{ startIndex: 0 }]; - delete this.pinnedItem; - delete this.pinnedOffset; - this.dirty = true; - }, - - renderGroup: function () { - return WinJS.Promise.wrap(null); - }, - - ensureFirstGroup: function () { - return WinJS.Promise.wrap(this.groups[0]); - }, - - groupOf: function (item) { - return WinJS.Promise.wrap(this.groups[0]); - }, - - removeElements: function () { - } - }); - }) - }); - -})(this, WinJS); - -(function itemEventsHandlerInit(global, WinJS) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - _ItemEventsHandler: WinJS.Namespace._lazy(function () { - var utilities = WinJS.Utilities, - Promise = WinJS.Promise, - Animation = WinJS.UI.Animation; - - var PT_TOUCH = MSPointerEvent.MSPOINTER_TYPE_TOUCH || "touch"; - - function getElementWithClass(parent, className) { - return parent.querySelector("." + className); - } - - function createNodeWithClass(className, skipAriaHidden) { - var element = document.createElement("div"); - element.className = className; - if (!skipAriaHidden) { - element.setAttribute("aria-hidden", true); - } - return element; - } - - return WinJS.Class.define(function ItemEventsHandler_ctor(site) { - this._site = site; - - this._work = []; - this._animations = {}; - this._selectionHintTracker = {}; - this._swipeClassTracker = {}; - - if (this._selectionAllowed()) { - var that = this; - setTimeout(function () { - if (!that._gestureRecognizer && !site.isZombie()) { - that._gestureRecognizer = that._createGestureRecognizer(); - } - }, 500); - } - }, { - dispose: function () { - if (this._disposed) { - return; - } - this._disposed = true; - this._gestureRecognizer = null; - window.removeEventListener("pointerup", this._resetPointerDownStateBound); - window.removeEventListener("pointercancel", this._resetPointerDownStateBound); - }, - - onMSManipulationStateChanged: function ItemEventsHandler_onMSManipulationStateChanged(eventObject) { - var state = eventObject.currentState; - // We're not necessarily guaranteed to get onMSPointerDown before we get a selection event from cross slide, - // so if we hit a select state with no pressed item box recorded, we need to set up the pressed info before - // processing the selection. - if (state === MSManipulationEvent.MS_MANIPULATION_STATE_PRESELECT && !this._site.pressedItemBox) { - var currentPressedIndex = this._site.indexForItemElement(eventObject.srcElement); - - this._site.pressedEntity = { type: WinJS.UI.ObjectType.item, index: currentPressedIndex }; - if (this._site.pressedEntity.index !== WinJS.UI._INVALID_INDEX) { - this._site.pressedItemBox = this._site.itemBoxAtIndex(this._site.pressedEntity.index); - this._site.pressedContainer = this._site.containerAtIndex(this._site.pressedEntity.index); - this._site.pressedHeader = null; - var allowed = this._site.verifySelectionAllowed(this._site.pressedEntity); - this._canSelect = allowed.canSelect; - this._canTapSelect = allowed.canTapSelect; - this._swipeBehaviorSelectionChanged = false; - this._selectionHint = null; - if (this._canSelect) { - this._addSelectionHint(); - } - } - } - if (this._canSelect && (state === MSManipulationEvent.MS_MANIPULATION_STATE_PRESELECT || - state === MSManipulationEvent.MS_MANIPULATION_STATE_COMMITTED || - state === MSManipulationEvent.MS_MANIPULATION_STATE_CANCELLED || - state === MSManipulationEvent.MS_MANIPULATION_STATE_SELECTING || - state === MSManipulationEvent.MS_MANIPULATION_STATE_DRAGGING)) { - this._dispatchSwipeBehavior(state); - } - - if (state === MSManipulationEvent.MS_MANIPULATION_STATE_COMMITTED || - state === MSManipulationEvent.MS_MANIPULATION_STATE_CANCELLED || - state === MSManipulationEvent.MS_MANIPULATION_STATE_STOPPED) { - this.resetPointerDownState(); - } - }, - - onPointerDown: function ItemEventsHandler_onPointerDown(eventObject) { - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:MSPointerDown,StartTM"); - var site = this._site, - touchInput = (eventObject.pointerType === PT_TOUCH), - leftButton, - rightButton; - site.pressedElement = eventObject.target; - if (utilities.hasWinRT) { - // xButton is true when you've x-clicked with a mouse or pen. Otherwise it is false. - var currentPoint = this._getCurrentPoint(eventObject); - var pointProps = currentPoint.properties; - if (!(touchInput || pointProps.isInverted || pointProps.isEraser || pointProps.isMiddleButtonPressed)) { - rightButton = pointProps.isRightButtonPressed; - leftButton = !rightButton && pointProps.isLeftButtonPressed; - } else { - leftButton = rightButton = false; - } - } else { - // xButton is true when you've x-clicked with a mouse. Otherwise it is false. - leftButton = (eventObject.button === WinJS.UI._LEFT_MSPOINTER_BUTTON); - rightButton = (eventObject.button === WinJS.UI._RIGHT_MSPOINTER_BUTTON); - } - - this._DragStartBound = this._DragStartBound || this.onDragStart.bind(this); - this._PointerOverBound = this._PointerOverBound || this.onPointerOver.bind(this); - this._PointerOutBound = this._PointerOutBound || this.onPointerOut.bind(this); - - this._swipeBehaviorState = MSManipulationEvent.MS_MANIPULATION_STATE_STOPPED; - var swipeEnabled = site.swipeBehavior === WinJS.UI.SwipeBehavior.select, - swipeBehavior = touchInput && swipeEnabled, - isInteractive = this._isInteractive(eventObject.srcElement), - currentPressedIndex = site.indexForItemElement(eventObject.srcElement), - currentPressedHeaderIndex = site.indexForHeaderElement(eventObject.srcElement), - mustSetCapture = !isInteractive && currentPressedIndex !== WinJS.UI._INVALID_INDEX; - - if ((touchInput || leftButton || (this._selectionAllowed() && swipeEnabled && rightButton)) && this._site.pressedEntity.index === WinJS.UI._INVALID_INDEX && !isInteractive) { - if (currentPressedHeaderIndex === WinJS.UI._INVALID_INDEX) { - this._site.pressedEntity = { type: WinJS.UI.ObjectType.item, index: currentPressedIndex }; - } else { - this._site.pressedEntity = { type: WinJS.UI.ObjectType.groupHeader, index: currentPressedHeaderIndex }; - } - - if (this._site.pressedEntity.index !== WinJS.UI._INVALID_INDEX) { - this._site.pressedPosition = WinJS.UI._getCursorPos(eventObject); - - var allowed = site.verifySelectionAllowed(this._site.pressedEntity); - this._canSelect = allowed.canSelect; - this._canTapSelect = allowed.canTapSelect; - - this._swipeBehaviorSelectionChanged = false; - this._selectionHint = null; - - if (this._site.pressedEntity.type !== WinJS.UI.ObjectType.groupHeader) { - this._site.pressedItemBox = site.itemBoxAtIndex(this._site.pressedEntity.index); - this._site.pressedContainer = site.containerAtIndex(this._site.pressedEntity.index); - this._site.pressedHeader = null; - this._togglePressed(true); - this._site.pressedContainer.addEventListener('dragstart', this._DragStartBound); - if (!touchInput) { - // This only works for non touch input because on touch input we set capture which immediately fires the MSPointerOut. - this._site.pressedContainer.addEventListener('pointerover', this._PointerOverBound); - this._site.pressedContainer.addEventListener('pointerout', this._PointerOutBound); - } - } else { - this._site.pressedHeader = eventObject.srcElement; - this._site.pressedItemBox = null; - this._site.pressedContainer = null; - } - - if (!this._resetPointerDownStateBound) { - this._resetPointerDownStateBound = this._resetPointerDownStateForPointerId.bind(this); - } - - if (!touchInput) { - window.addEventListener("pointerup", this._resetPointerDownStateBound); - window.addEventListener("pointercancel", this._resetPointerDownStateBound); - } - - if (this._canSelect) { - if (!this._gestureRecognizer) { - this._gestureRecognizer = this._createGestureRecognizer(); - } - this._addSelectionHint(); - } - this._pointerId = eventObject.pointerId; - this._pointerRightButton = rightButton; - this._pointerTriggeredSRG = false; - - if (this._gestureRecognizer && touchInput) { - try { - this._gestureRecognizer.addPointer(this._pointerId); - } catch (e) { - this._gestureRecognizer.stop(); - } - } - } - } - - if (mustSetCapture) { - if (touchInput) { - try { - // Move pointer capture to avoid hover visual on second finger - site.canvasProxy.setPointerCapture(eventObject.pointerId); - } catch (e) { - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:MSPointerDown,StopTM"); - return; - } - } - } - - // Once the shift selection pivot is set, it remains the same until the user - // performs a left- or right-click without holding the shift key down. - if (this._site.pressedEntity.type !== WinJS.UI.ObjectType.groupHeader && - this._selectionAllowed() && this._multiSelection() && // Multi selection enabled - this._site.pressedEntity.index !== WinJS.UI._INVALID_INDEX && // A valid item was clicked - site.selection._getFocused().index !== WinJS.UI._INVALID_INDEX && site.selection._pivot === WinJS.UI._INVALID_INDEX) { - site.selection._pivot = site.selection._getFocused().index; - } - - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:MSPointerDown,StopTM"); - }, - - onPointerOver: function ItemEventsHandler_onPointerOver(eventObject) { - if (this._site.pressedContainer && this._pointerId === eventObject.pointerId) { - this._togglePressed(true); - } - }, - - onPointerOut: function ItemEventsHandler_onPointerOut(eventObject) { - if (this._site.pressedContainer && this._pointerId === eventObject.pointerId) { - this._togglePressed(false, true /* synchronous */); - } - }, - - onDragStart: function ItemEventsHandler_onDragStart() { - this._resetPressedContainer(); - }, - - _resetPressedContainer: function ItemEventsHandler_resetPressedContainer() { - if (this._site.pressedContainer) { - this._togglePressed(false); - this._site.pressedContainer.removeEventListener('dragstart', this._DragStartBound); - this._site.pressedContainer.removeEventListener('pointerover', this._PointerOverBound); - this._site.pressedContainer.removeEventListener('pointerout', this._PointerOutBound); - } - }, - - onClick: function ItemEventsHandler_onClick(eventObject) { - if (!this._skipClick) { - // Handle the UIA invoke action on an item. this._skipClick is false which tells us that we received a click - // event without an associated MSPointerUp event. This means that the click event was triggered thru UIA - // rather than thru the GUI. - var entity = { type: WinJS.UI.ObjectType.item, index: this._site.indexForItemElement(eventObject.srcElement) }; - if (entity.index === WinJS.UI._INVALID_INDEX) { - entity.index = this._site.indexForHeaderElement(eventObject.srcElement); - if (entity.index !== WinJS.UI._INVALID_INDEX) { - entity.type = WinJS.UI.ObjectType.groupHeader; - } - } - - if (entity.index !== WinJS.UI._INVALID_INDEX && - (utilities.hasClass(eventObject.srcElement, this._site.accessibleItemClass) || utilities.hasClass(eventObject.srcElement, WinJS.UI._headerClass))) { - var allowed = this._site.verifySelectionAllowed(entity); - if (allowed.canTapSelect) { - this.handleTap(entity); - } - this._site.fireInvokeEvent(entity, eventObject.srcElement); - } - } - }, - - onPointerUp: function ItemEventsHandler_onPointerUp(eventObject) { - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:MSPointerUp,StartTM"); - - var site = this._site; - this._skipClick = true; - var that = this; - var swipeEnabled = this._site.swipeBehavior === WinJS.UI.SwipeBehavior.select; - setImmediate(function () { - that._skipClick = false; - }); - - try { - // Release the pointer capture to allow in air touch pointers to be reused for multiple interactions - site.canvasProxy.releasePointerCapture(eventObject.pointerId); - } catch (e) { - // This can throw if SeZo had capture or if the pointer was not already captured - } - - var touchInput = (eventObject.pointerType === PT_TOUCH), - releasedElement = this._releasedElement(eventObject), - releasedIndex = site.indexForItemElement(releasedElement), - releasedHeaderIndex = site.indexForHeaderElement(releasedElement); - - if (this._pointerId === eventObject.pointerId) { - var releasedEntity; - if (releasedHeaderIndex === WinJS.UI._INVALID_INDEX) { - releasedEntity = { type: WinJS.UI.ObjectType.item, index: releasedIndex }; - } else { - releasedEntity = { type: WinJS.UI.ObjectType.groupHeader, index: releasedHeaderIndex }; - } - - this._resetPressedContainer(); - - if (this._site.pressedEntity.type !== WinJS.UI.ObjectType.groupHeader && releasedEntity.type !== WinJS.UI.ObjectType.groupHeader && - this._site.pressedContainer && this._site.pressedEntity.index === releasedEntity.index) { - - if (!eventObject.shiftKey) { - // Reset the shift selection pivot when the user clicks w/o pressing shift - site.selection._pivot = WinJS.UI._INVALID_INDEX; - } - - if (eventObject.shiftKey) { - // Shift selection should work when shift or shift+ctrl are depressed for both left- and right-click - if (this._selectionAllowed() && this._multiSelection() && site.selection._pivot !== WinJS.UI._INVALID_INDEX) { - var firstIndex = Math.min(this._site.pressedEntity.index, site.selection._pivot), - lastIndex = Math.max(this._site.pressedEntity.index, site.selection._pivot), - additive = (this._pointerRightButton || eventObject.ctrlKey || site.tapBehavior === WinJS.UI.TapBehavior.toggleSelect); - site.selectRange(firstIndex, lastIndex, additive); - } - } else if (eventObject.ctrlKey || (this._selectionAllowed() && swipeEnabled && this._pointerRightButton)) { - // Swipe emulation - this.handleSwipeBehavior(this._site.pressedEntity.index); - } - } - - if ((this._site.pressedHeader || this._site.pressedContainer) && this._swipeBehaviorState !== MSManipulationEvent.MS_MANIPULATION_STATE_COMMITTED) { - var upPosition = WinJS.UI._getCursorPos(eventObject); - var isTap = Math.abs(upPosition.left - this._site.pressedPosition.left) <= WinJS.UI._TAP_END_THRESHOLD && - Math.abs(upPosition.top - this._site.pressedPosition.top) <= WinJS.UI._TAP_END_THRESHOLD; - - this._endSelfRevealGesture(); - this._clearItem(this._site.pressedEntity, this._isSelected(this._site.pressedEntity.index)); - - // We do not care whether or not the pressed and released indices are equivalent when the user is using touch. The only time they won't be is if the user - // tapped the edge of an item and the pressed animation shrank the item such that the user's finger was no longer over it. In this case, the item should - // be considered tapped. - // However, if the user is using touch then we must perform an extra check. Sometimes we receive MSPointerUp events when the user intended to pan or swipe. - // This extra check ensures that these intended pans/swipes aren't treated as taps. - if (!this._pointerRightButton && !this._pointerTriggeredSRG && !eventObject.ctrlKey && !eventObject.shiftKey && - ((touchInput && isTap) || - (!touchInput && this._site.pressedEntity.index === releasedEntity.index && this._site.pressedEntity.type === releasedEntity.type))) { - if (releasedEntity.type === WinJS.UI.ObjectType.groupHeader) { - this._site.pressedHeader = site.headerAtIndex(releasedEntity.index); - this._site.pressedItemBox = null; - this._site.pressedContainer = null; - } else { - this._site.pressedItemBox = site.itemBoxAtIndex(releasedEntity.index); - this._site.pressedContainer = site.containerAtIndex(releasedEntity.index); - this._site.pressedHeader = null; - } - - if (this._canTapSelect) { - this.handleTap(this._site.pressedEntity); - } - this._site.fireInvokeEvent(this._site.pressedEntity, this._site.pressedItemBox || this._site.pressedHeader); - } - } - - if (this._site.pressedEntity.index !== WinJS.UI._INVALID_INDEX) { - site.changeFocus(this._site.pressedEntity, true, false, true); - } - - this.resetPointerDownState(); - } - - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:MSPointerUp,StopTM"); - }, - - onPointerCancel: function ItemEventsHandler_onPointerCancel(eventObject) { - if (this._pointerId === eventObject.pointerId && this._swipeBehaviorState !== MSManipulationEvent.MS_MANIPULATION_STATE_PRESELECT) { - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:MSPointerCancel,info"); - this.resetPointerDownState(); - } - }, - - onLostPointerCapture: function ItemEventsHandler_onLostPointerCapture(eventObject) { - if (this._pointerId === eventObject.pointerId && this._swipeBehaviorState !== MSManipulationEvent.MS_MANIPULATION_STATE_PRESELECT) { - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:MSLostPointerCapture,info"); - this.resetPointerDownState(); - } - }, - - // In order for the control to play nicely with other UI controls such as the app bar, it calls preventDefault on - // contextmenu events. It does this only when selection is enabled, the event occurred on or within an item, and - // the event did not occur on an interactive element. - onContextMenu: function ItemEventsHandler_onContextMenu(eventObject) { - var containerElement = this._site.containerFromElement(eventObject.srcElement); - - if (this._selectionAllowed() && containerElement && !this._isInteractive(eventObject.srcElement)) { - eventObject.preventDefault(); - } - }, - - onMSHoldVisual: function ItemEventsHandler_onMSHoldVisual(eventObject) { - if (!this._isInteractive(eventObject.srcElement)) { - eventObject.preventDefault(); - } - }, - - onDataChanged: function ItemEventsHandler_onDataChanged() { - this.resetPointerDownState(); - }, - - handleSwipeBehavior: function ItemEventsHandler_handleSwipeBehavior(itemIndex) { - if (this._selectionAllowed(itemIndex)) { - this._toggleItemSelection(itemIndex); - } - }, - - handleTap: function ItemEventsHandler_handleTap(entity) { - if (entity.type === WinJS.UI.ObjectType.groupHeader) { - return; - } - - var site = this._site, - selection = site.selection; - - if (this._selectionAllowed(entity.index) && this._selectOnTap()) { - if (site.tapBehavior === WinJS.UI.TapBehavior.toggleSelect) { - this._toggleItemSelection(entity.index); - } else { - // site.tapBehavior === WinJS.UI.TapBehavior.directSelect so ensure only itemIndex is selected - if (site.selectionMode === WinJS.UI.SelectionMode.multi || !selection._isIncluded(entity.index)) { - selection.set(entity.index); - } - } - } - }, - - // In single selection mode, in addition to itemIndex's selection state being toggled, - // all other items will become deselected - _toggleItemSelection: function ItemEventsHandler_toggleItemSelection(itemIndex) { - var site = this._site, - selection = site.selection, - selected = selection._isIncluded(itemIndex); - - if (site.selectionMode === WinJS.UI.SelectionMode.single) { - if (!selected) { - selection.set(itemIndex); - } else { - selection.clear(); - } - } else { - if (!selected) { - selection.add(itemIndex); - } else { - selection.remove(itemIndex); - } - } - }, - - _getCurrentPoint: function ItemEventsHandler_getCurrentPoint(eventObject) { - return Windows.UI.Input.PointerPoint.getCurrentPoint(eventObject.pointerId); - }, - - _containedInElementWithClass: function ItemEventsHandler_containedInElementWithClass(element, className) { - if (element.parentNode) { - var matches = element.parentNode.querySelectorAll("." + className + ", ." + className + " *"); - for (var i = 0, len = matches.length; i < len; i++) { - if (matches[i] === element) { - return true; - } - } - } - return false; - }, - - _isSelected: function ItemEventsHandler_isSelected(index) { - return (!this._swipeBehaviorSelectionChanged && this._site.selection._isIncluded(index)) || (this._swipeBehaviorSelectionChanged && this.swipeBehaviorSelected); - }, - - _isInteractive: function ItemEventsHandler_isInteractive(element) { - return this._containedInElementWithClass(element, "win-interactive"); - }, - - _togglePressed: function ItemEventsHandler_togglePressed(add, synchronous) { - var that = this; - - if (!this._staticMode()) { - if (add) { - if (!utilities.hasClass(this._site.pressedContainer, WinJS.UI._pressedClass)) { - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:applyPressedUI,info"); - utilities.addClass(this._site.pressedContainer, WinJS.UI._pressedClass); - - // Shrink by 97.5% unless that is larger than 7px in either direction. In that case we cap the - // scale so that it is no larger than 7px in either direction. We keep the scale uniform in both x - // and y directions. Note that this scale cap only works if getItemPosition returns synchronously - // which it does for the built in layouts. - var scale = 0.975; - var maxPixelsToShrink = 7; - this._site.getItemPosition(this._site.pressedEntity).then(function (pos) { - if (pos.contentWidth > 0) { - scale = Math.max(scale, (1 - (maxPixelsToShrink / pos.contentWidth))); - } - if (pos.contentHeight > 0) { - scale = Math.max(scale, (1 - (maxPixelsToShrink / pos.contentHeight))); - } - }, function () { - // Swallow errors in case data source changes - }); - - if (this._site.pressedContainer.style.transform === "") { - this._site.pressedContainer.style.transform = "scale(" + scale + "," + scale + ")"; - this._site.pressedContainerScaleTransform = this._site.pressedContainer.style.transform; - } else { - this._site.pressedContainerScaleTransform = ""; - } - } - } else { - if (utilities.hasClass(this._site.pressedContainer, WinJS.UI._pressedClass)) { - var element = this._site.pressedContainer; - var expectingStyle = this._site.pressedContainerScaleTransform; - if (synchronous) { - togglePressedImpl(element, expectingStyle); - } else { - // Force removal of the _pressedClass to be asynchronous so that users will see at - // least one frame of the shrunken item when doing a quick tap. - // - // setImmediate is used rather than requestAnimationFrame to ensure that the item - // doesn't get stuck down for too long -- apps are told to put long running invoke - // code behind a setImmediate and togglePressed's async code needs to run first. - setImmediate(function () { - if (utilities.hasClass(element, WinJS.UI._pressedClass)) { - togglePressedImpl(element, expectingStyle); - } - }); - } - } - } - } - - function togglePressedImpl(element, expectingStyle) { - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:removePressedUI,info"); - utilities.removeClass(element, WinJS.UI._pressedClass); - that._removeTransform(element, expectingStyle); - } - }, - - _removeTransform: function ItemEventsHandler_removeTransform(element, transform) { - if (transform && element.style.transform.indexOf(transform) !== -1) { - element.style.transform = element.style.transform.replace(transform, ""); - } - }, - - _endSwipeBehavior: function ItemEventsHandler_endSwipeBehavior() { - if (!(this._swipeBehaviorState === MSManipulationEvent.MS_MANIPULATION_STATE_PRESELECT || - this._swipeBehaviorState === MSManipulationEvent.MS_MANIPULATION_STATE_SELECTING || - this._swipeBehaviorState === MSManipulationEvent.MS_MANIPULATION_STATE_DRAGGING || - this._swipeBehaviorState === MSManipulationEvent.MS_MANIPULATION_STATE_COMMITTED || - this._swipeBehaviorState === MSManipulationEvent.MS_MANIPULATION_STATE_CANCELLED)) { - return; - } - - if (this._site.pressedEntity.type === WinJS.UI.ObjectType.groupHeader) { - return; - } - - this._flushUIBatches(); - var selectionHint = this._selectionHint; - this._selectionHint = null; - - if (this._site.pressedItemBox) { - var pressedIndex = this._site.pressedEntity.index, - selected = this._site.selection._isIncluded(pressedIndex); - if (selected) { - var elementsToShowHide = WinJS.UI._getElementsByClasses(this._site.pressedItemBox, [WinJS.UI._selectionCheckmarkClass, WinJS.UI._selectionCheckmarkBackgroundClass]); - for (var i = 0; i < elementsToShowHide.length; i++) { - elementsToShowHide[i].style.opacity = 1; - } - } - this._clearItem(this._site.pressedEntity, selected); - if (selectionHint) { - this._removeSelectionHint(selectionHint); - } - delete this._animations[pressedIndex]; - } - }, - - _createGestureRecognizer: function ItemEventsHandler_createGestureRecognizer() { - var rootElement = this._site.eventHandlerRoot; - var recognizer = new MSGesture(); - recognizer.target = rootElement; - var that = this; - rootElement.addEventListener("MSGestureHold", function (eventObject) { - if (that._site.pressedEntity.index !== -1 && eventObject.detail === MSGestureEvent.MSGESTURE_FLAG_BEGIN) { - that._startSelfRevealGesture(); - } - }); - return recognizer; - }, - - _dispatchSwipeBehavior: function ItemEventsHandler_dispatchSwipeBehavior(manipulationState) { - if (this._site.pressedEntity.type === WinJS.UI.ObjectType.groupHeader) { - return; - } - this._site.selection._pivot = WinJS.UI._INVALID_INDEX; - if (this._site.pressedItemBox) { - var pressedIndex = this._site.pressedEntity.index; - if (this._swipeBehaviorState !== manipulationState) { - if (manipulationState === MSManipulationEvent.MS_MANIPULATION_STATE_DRAGGING && this._canSelect) { - this._animateSelectionChange(this._site.selection._isIncluded(pressedIndex)); - this._removeSelectionHint(this._selectionHint); - } else if (manipulationState === MSManipulationEvent.MS_MANIPULATION_STATE_PRESELECT) { - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:crossSlidingStarted,info"); - var site = this._site, - pressedElement = site.itemAtIndex(pressedIndex), - selected = site.selection._isIncluded(pressedIndex); - - if (this._selfRevealGesture) { - this._selfRevealGesture.finishAnimation(); - this._selfRevealGesture = null; - } else if (this._canSelect) { - this._prepareItem(this._site.pressedEntity, pressedElement, selected); - } - - if (this._swipeBehaviorState !== MSManipulationEvent.MS_MANIPULATION_STATE_SELECTING) { - if (this._site.pressedContainer && utilities.hasClass(this._site.pressedContainer, WinJS.UI._pressedClass)) { - utilities.removeClass(this._site.pressedContainer, WinJS.UI._pressedClass); - this._removeTransform(this._site.pressedContainer, this._site.pressedContainerScaleTransform); - } - - this._showSelectionHintCheckmark(); - } else { - this._animateSelectionChange(this._site.selection._isIncluded(pressedIndex)); - } - } else if (manipulationState === MSManipulationEvent.MS_MANIPULATION_STATE_COMMITTED) { - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:crossSlidingCompleted,info"); - var that = this, - site = this._site, - selection = site.selection, - swipeBehaviorSelectionChanged = this._swipeBehaviorSelectionChanged, - swipeBehaviorSelected = this.swipeBehaviorSelected; - - if (this._swipeBehaviorState === MSManipulationEvent.MS_MANIPULATION_STATE_SELECTING && swipeBehaviorSelectionChanged) { - if (this._selectionAllowed() && site.swipeBehavior === WinJS.UI.SwipeBehavior.select) { - if (site.selectionMode === WinJS.UI.SelectionMode.single) { - if (swipeBehaviorSelected) { - selection.set(pressedIndex); - } else if (selection._isIncluded(pressedIndex)) { - selection.remove(pressedIndex); - } - } else { - if (swipeBehaviorSelected) { - selection.add(pressedIndex); - } else if (selection._isIncluded(pressedIndex)) { - selection.remove(pressedIndex); - } - } - } - } - - // snap back and remove addional elements - this._endSwipeBehavior(); - } else if (manipulationState === MSManipulationEvent.MS_MANIPULATION_STATE_SELECTING && this._canSelect) { - this._animateSelectionChange(!this._site.selection._isIncluded(pressedIndex)); - } else if (this._swipeBehaviorState === MSManipulationEvent.MS_MANIPULATION_STATE_SELECTING && this._canSelect) { - this._animateSelectionChange(this._site.selection._isIncluded(pressedIndex), (manipulationState === MSManipulationEvent.MS_MANIPULATION_STATE_CANCELLED)); - } - } - } - - this._swipeBehaviorState = manipulationState; - }, - - - _resetPointerDownStateForPointerId: function ItemEventsHandler_resetPointerDownState(eventObject) { - if (this._pointerId === eventObject.pointerId) { - this.resetPointerDownState(); - } - }, - - resetPointerDownState: function ItemEventsHandler_resetPointerDownState() { - if (this._gestureRecognizer) { - this._endSelfRevealGesture(); - this._endSwipeBehavior(); - } - this._site.pressedElement = null; - window.removeEventListener("pointerup", this._resetPointerDownStateBound); - window.removeEventListener("pointercancel", this._resetPointerDownStateBound); - - this._resetPressedContainer(); - - this._site.pressedContainer = null; - this._site.pressedHeader = null; - this._site.pressedItemBox = null; - - this._removeSelectionHint(this._selectionHint); - this._selectionHint = null; - - this._site.pressedEntity = { type: WinJS.UI.ObjectType.item, index: WinJS.UI._INVALID_INDEX }; - this._pointerId = null; - }, - - // Play the self-reveal gesture (SRG) animation which jiggles the item to reveal the selection hint behind it. - // This function is overridden by internal teams to add a tooltip on SRG start - treat this function as a public API for the sake of function name/parameter changes. - _startSelfRevealGesture: function ItemEventsHandler_startSelfRevealGesture() { - if (this._canSelect && this._site.swipeBehavior === WinJS.UI.SwipeBehavior.select) { - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:playSelfRevealGesture,info"); - - var that = this; - var site = this._site, - Animation = WinJS.UI.Animation, - index = this._site.pressedEntity.index, - itemBox = site.itemBoxAtIndex(index), - selected = site.selection._isIncluded(index), - finished = false; - - var swipeReveal = function () { - var top, - left; - - if (site.horizontal) { - top = WinJS.UI._VERTICAL_SWIPE_SELF_REVEAL_GESTURE + "px"; - left = "0px"; - } else { - top = "0px"; - left = (site.rtl() ? "" : "-") + WinJS.UI._HORIZONTAL_SWIPE_SELF_REVEAL_GESTURE + "px"; - } - - return Animation.swipeReveal(itemBox, { top: top, left: left }); - } - - var swipeHide = function () { - return finished ? WinJS.Promise.wrap() : Animation.swipeReveal(itemBox, { top: "0px", left: "0px" }); - } - - var cleanUp = function (selectionHint) { - if (!site.isZombie()) { - if (selectionHint) { - that._removeSelectionHint(selectionHint); - } - that._clearItem(site.pressedEntity, site.selection._isIncluded(index)); - } - } - - // Immediately begins the last phase of the SRG animation which animates the item back to its original location - var finishAnimation = function () { - that._selfRevealGesture._promise.cancel(); - finished = true; - var selectionHint = that._selectionHint; - that._selectionHint = null; - return swipeHide().then(function () { - itemBox.style.transform = ""; - cleanUp(selectionHint); - }); - } - - this._prepareItem(this._site.pressedEntity, itemBox, selected); - this._showSelectionHintCheckmark(); - - this._pointerTriggeredSRG = true; - this._selfRevealGesture = { - finishAnimation: finishAnimation, - _promise: swipeReveal(). - then(swipeHide). - then(function () { - if (!finished) { - that._hideSelectionHintCheckmark(); - cleanUp(); - that._selfRevealGesture = null; - } - }) - }; - } - }, - - // This function is overridden by internal teams to remove a tooltip on SRG completion - treat this function as a public API for the sake of function name/parameter changes - _endSelfRevealGesture: function ItemEventsHandler_endSelfRevealGesture() { - if (this._selfRevealGesture) { - this._selfRevealGesture.finishAnimation(); - this._selfRevealGesture = null; - } - }, - - _prepareItem: function ItemEventsHandler_prepareItem(pressedEntity, pressedElement, selected) { - if (pressedEntity.type === WinJS.UI.ObjectType.groupHeader) { - return; - } - - var that = this, - site = this._site, - pressedIndex = pressedEntity.index; - - function addSwipeClass(container) { - if (!that._swipeClassTracker[container.uniqueID]) { - utilities.addClass(container, WinJS.UI._swipeClass); - that._swipeClassTracker[container.uniqueID] = 1; - } else { - that._swipeClassTracker[container.uniqueID]++; - } - } - - if (!selected) { - (this._animations[pressedIndex] || Promise.wrap()).then(function () { - if (!site.isZombie() && pressedEntity.type !== WinJS.UI.ObjectType.groupHeader && site.pressedEntity.index !== -1) { - pressedIndex = site.pressedEntity.index; - - var pressedElement = site.itemAtIndex(pressedIndex), - itemBox = site.itemBoxAtIndex(pressedIndex), - container = site.containerAtIndex(pressedIndex); - - addSwipeClass(container); - - if (!WinJS.UI._isSelectionRendered(itemBox)) { - WinJS.UI._ItemEventsHandler.renderSelection(itemBox, pressedElement, true, container); - - utilities.removeClass(itemBox, WinJS.UI._selectedClass); - utilities.removeClass(container, WinJS.UI._selectedClass); - - var nodes = itemBox.querySelectorAll(WinJS.UI._selectionPartsSelector); - for (var i = 0, len = nodes.length; i < len; i++) { - nodes[i].style.opacity = 0; - } - } - } - }); - } else { - var container = site.containerAtIndex(pressedIndex); - addSwipeClass(container); - } - }, - - _clearItem: function ItemEventsHandler_clearItem(pressedEntity, selected) { - if (pressedEntity.type !== WinJS.UI.ObjectType.item) { - return; - } - - var that = this, - site = this._site, - container = site.containerAtIndex(pressedEntity.index), - itemBox = site.itemBoxAtIndex(pressedEntity.index), - element = site.itemAtIndex(pressedEntity.index); - - function removeSwipeClass(container) { - var refCount = --that._swipeClassTracker[container.uniqueID]; - if (!refCount) { - delete that._swipeClassTracker[container.uniqueID]; - utilities.removeClass(container, WinJS.UI._swipeClass); - return true; - } - return false; - } - - function removeSwipeFromItemsBlock(container) { - var itemsBlock = container.parentNode; - if (itemsBlock && WinJS.Utilities.hasClass(itemsBlock, WinJS.UI._itemsBlockClass)) { - removeSwipeClass(itemsBlock); - } - } - - if (container && itemBox && element) { - var doneSwiping = removeSwipeClass(container); - removeSwipeFromItemsBlock(container); - if (doneSwiping) { - WinJS.UI._ItemEventsHandler.renderSelection(itemBox, element, selected, true, container); - } - } - }, - - _animateSelectionChange: function ItemEventsHandler_animateSelectionChange(select, includeCheckmark) { - var that = this, - pressedContainer = this._site.pressedContainer, - pressedItemBox = this._site.pressedItemBox; - - function toggleClasses() { - var classOperation = select ? "addClass" : "removeClass"; - utilities[classOperation](pressedItemBox, WinJS.UI._selectedClass); - utilities[classOperation](pressedContainer, WinJS.UI._selectedClass); - if (that._selectionHint) { - var hintCheckMark = getElementWithClass(that._selectionHint, WinJS.UI._selectionHintClass); - if (hintCheckMark) { - utilities[classOperation](hintCheckMark, WinJS.UI._revealedClass); - } - } - } - - this._swipeBehaviorSelectionChanged = true; - this.swipeBehaviorSelected = select; - - var elementsToShowHide = WinJS.UI._getElementsByClasses(this._site.pressedItemBox, [WinJS.UI._selectionBorderClass, WinJS.UI._selectionBackgroundClass]); - - if (!select || includeCheckmark) { - elementsToShowHide = elementsToShowHide.concat(WinJS.UI._getElementsByClasses(this._site.pressedItemBox, [WinJS.UI._selectionCheckmarkBackgroundClass, WinJS.UI._selectionCheckmarkClass])); - } - - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:" + (select ? "hitSelectThreshold" : "hitUnselectThreshold") + ",info"); - - this._applyUIInBatches(function () { - msWriteProfilerMark("WinJS.UI._ItemEventsHandler:" + (select ? "apply" : "remove") + "SelectionVisual,info"); - var opacity = (select ? 1 : 0); - for (var i = 0; i < elementsToShowHide.length; i++) { - elementsToShowHide[i].style.opacity = opacity; - } - - toggleClasses(); - }); - }, - - _showSelectionHintCheckmark: function ItemEventsHandler_showSelectionHintCheckmark() { - if (this._selectionHint) { - var hintCheckMark = getElementWithClass(this._selectionHint, WinJS.UI._selectionHintClass); - if (hintCheckMark) { - hintCheckMark.style.display = 'block'; - } - } - }, - - _hideSelectionHintCheckmark: function ItemEventsHandler_hideSelectionHintCheckmark() { - if (this._selectionHint) { - var hintCheckMark = getElementWithClass(this._selectionHint, WinJS.UI._selectionHintClass); - if (hintCheckMark) { - hintCheckMark.style.display = 'none'; - } - } - }, - - _addSelectionHint: function ItemEventsHandler_addSelectionHint() { - if (this._site.pressedEntity.type === WinJS.UI.ObjectType.groupHeader) { - return; - } - - var selectionHint, - site = this._site; - - if (site.customFootprintParent) { - selectionHint = this._selectionHint = document.createElement("div"); - selectionHint.className = WinJS.UI._containerClass; - - var that = this; - site.getItemPosition(this._site.pressedEntity).then(function (pos) { - if (!site.isZombie() && that._selectionHint && that._selectionHint === selectionHint) { - var style = selectionHint.style; - var cssText = ";position:absolute;" + - (site.rtl() ? "right:" : "left:") + pos.left + "px;top:" + - pos.top + "px;width:" + pos.contentWidth + "px;height:" + pos.contentHeight + "px"; - style.cssText += cssText; - site.customFootprintParent.insertBefore(that._selectionHint, that._site.pressedItemBox); - } - }, function () { - // Swallow errors in case data source changes - }); - } else { - selectionHint = this._selectionHint = this._site.pressedContainer; - } - - if (!this._selectionHintTracker[selectionHint.uniqueID]) { - utilities.addClass(selectionHint, WinJS.UI._footprintClass); - - if (!site.selection._isIncluded(this._site.pressedEntity.index)) { - var element = document.createElement("div"); - element.className = WinJS.UI._selectionHintClass; - element.innerText = WinJS.UI._SELECTION_CHECKMARK; - element.style.display = 'none'; - this._selectionHint.insertBefore(element, this._selectionHint.firstElementChild); - } - - this._selectionHintTracker[selectionHint.uniqueID] = 1; - } else { - this._selectionHintTracker[selectionHint.uniqueID]++; - } - }, - - _removeSelectionHint: function ItemEventsHandler_removeSelectionHint(selectionHint) { - if (selectionHint) { - var refCount = --this._selectionHintTracker[selectionHint.uniqueID]; - if (!refCount) { - delete this._selectionHintTracker[selectionHint.uniqueID]; - - if (!this._site.customFootprintParent) { - utilities.removeClass(selectionHint, WinJS.UI._footprintClass); - var hintCheckMark = getElementWithClass(selectionHint, WinJS.UI._selectionHintClass); - if (hintCheckMark) { - hintCheckMark.parentNode.removeChild(hintCheckMark); - } - } else if (selectionHint.parentNode) { - selectionHint.parentNode.removeChild(selectionHint); - } - } - } - }, - - _releasedElement: function ItemEventsHandler_releasedElement(eventObject) { - return document.elementFromPoint(eventObject.clientX, eventObject.clientY); - }, - - _applyUIInBatches: function ItemEventsHandler_applyUIInBatches(work) { - var that = this; - this._work.push(work); - - if (!this._paintedThisFrame) { - applyUI(); - } - - function applyUI() { - if (that._work.length > 0) { - that._flushUIBatches(); - that._paintedThisFrame = requestAnimationFrame(applyUI.bind(that)); - } else { - that._paintedThisFrame = null; - } - } - }, - - _flushUIBatches: function ItemEventsHandler_flushUIBatches() { - if (this._work.length > 0) { - var workItems = this._work; - this._work = []; - - for (var i = 0; i < workItems.length; i++) { - workItems[i](); - } - } - }, - - _selectionAllowed: function ItemEventsHandler_selectionAllowed(itemIndex) { - var item = (itemIndex !== undefined ? this._site.itemAtIndex(itemIndex) : null), - itemSelectable = !(item && utilities.hasClass(item, WinJS.UI._nonSelectableClass)); - return itemSelectable && this._site.selectionMode !== WinJS.UI.SelectionMode.none; - }, - - _multiSelection: function ItemEventsHandler_multiSelection() { - return this._site.selectionMode === WinJS.UI.SelectionMode.multi; - }, - - _selectOnTap: function ItemEventsHandler_selectOnTap() { - return this._site.tapBehavior === WinJS.UI.TapBehavior.toggleSelect || this._site.tapBehavior === WinJS.UI.TapBehavior.directSelect; - }, - - _staticMode: function ItemEventsHandler_staticMode() { - return this._site.tapBehavior === WinJS.UI.TapBehavior.none && this._site.selectionMode === WinJS.UI.SelectionMode.none; - }, - }, { - // Avoids unnecessary UIA selection events by only updating aria-selected if it has changed - setAriaSelected: function ItemEventsHandler_setAriaSelected(itemElement, isSelected) { - var ariaSelected = (itemElement.getAttribute("aria-selected") === "true"); - - if (isSelected !== ariaSelected) { - itemElement.setAttribute("aria-selected", isSelected); - } - }, - - renderSelection: function ItemEventsHandler_renderSelection(itemBox, element, selected, aria, container) { - if (!WinJS.UI._ItemEventsHandler._selectionTemplate) { - WinJS.UI._ItemEventsHandler._selectionTemplate = []; - WinJS.UI._ItemEventsHandler._selectionTemplate.push(createNodeWithClass(WinJS.UI._selectionBackgroundClass)); - WinJS.UI._ItemEventsHandler._selectionTemplate.push(createNodeWithClass(WinJS.UI._selectionBorderClass)); - WinJS.UI._ItemEventsHandler._selectionTemplate.push(createNodeWithClass(WinJS.UI._selectionCheckmarkBackgroundClass)); - var checkmark = createNodeWithClass(WinJS.UI._selectionCheckmarkClass); - checkmark.innerText = WinJS.UI._SELECTION_CHECKMARK; - WinJS.UI._ItemEventsHandler._selectionTemplate.push(checkmark); - } - - // Update the selection rendering if necessary - if (selected !== WinJS.UI._isSelectionRendered(itemBox)) { - if (selected) { - itemBox.insertBefore(WinJS.UI._ItemEventsHandler._selectionTemplate[0].cloneNode(true), itemBox.firstElementChild); - - for (var i = 1, len = WinJS.UI._ItemEventsHandler._selectionTemplate.length; i < len; i++) { - itemBox.appendChild(WinJS.UI._ItemEventsHandler._selectionTemplate[i].cloneNode(true)); - } - } else { - var nodes = itemBox.querySelectorAll(WinJS.UI._selectionPartsSelector); - for (var i = 0, len = nodes.length; i < len; i++) { - itemBox.removeChild(nodes[i]); - } - } - - utilities[selected ? "addClass" : "removeClass"](itemBox, WinJS.UI._selectedClass); - if (container) { - utilities[selected ? "addClass" : "removeClass"](container, WinJS.UI._selectedClass); - } - } - - // To allow itemPropertyChange to work properly, aria needs to be updated after the selection visuals are added to the itemBox - if (aria) { - WinJS.UI._ItemEventsHandler.setAriaSelected(element, selected); - } - }, - }); - }) - - }); - -})(this, WinJS); - -(function itemsContainerInit(global, WinJS, undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - _ItemsContainer: WinJS.Namespace._lazy(function () { - var utilities = WinJS.Utilities, - Promise = WinJS.Promise; - - var _ItemsContainer = function (site) { - this.site = site; - this._itemData = {}; - this.waitingItemRequests = {}; - }; - _ItemsContainer.prototype = { - requestItem: function ItemsContainer_requestItem(itemIndex) { - if (!this.waitingItemRequests[itemIndex]) { - this.waitingItemRequests[itemIndex] = []; - } - - var that = this; - var promise = new Promise(function (complete, error) { - var itemData = that._itemData[itemIndex]; - if (itemData && !itemData.detached && itemData.element) { - complete(itemData.element); - } else { - that.waitingItemRequests[itemIndex].push(complete); - } - }); - - return promise; - }, - - removeItem: function (index) { - /*#DBG - delete WinJS.Utilities.data(this._itemData[index].element).itemData; - delete WinJS.Utilities.data(this._itemData[index].element).itemsContainer; - #DBG*/ - delete this._itemData[index]; - }, - - removeItems: function ItemsContainer_removeItems() { - /*#DBG - var that = this; - Object.keys(this._itemData).forEach(function (k) { - delete WinJS.Utilities.data(that._itemData[k].element).itemData; - delete WinJS.Utilities.data(that._itemData[k].element).itemsContainer; - }); - #DBG*/ - this._itemData = {}; - this.waitingItemRequests = {}; - }, - - setItemAt: function ItemsContainer_setItemAt(itemIndex, itemData) { - /*#DBG - if (itemData.itemsManagerRecord.released) { - throw "ACK! Attempt to use a released itemsManagerRecord"; - } - var oldItemData = WinJS.Utilities.data(itemData.element).itemData; - if (oldItemData || WinJS.Utilities.data(itemData.element).itemsContainer) { - if (oldItemData.itemsManagerRecord.item.index !== itemIndex) { - throw "ACK! Attempted use of already in-use element"; - } - } - WinJS.Utilities.data(itemData.element).itemData = itemData; - WinJS.Utilities.data(itemData.element).itemsContainer = this; - #DBG*/ - //#DBG _ASSERT(itemData.element && (itemData.element instanceof HTMLElement)); - //#DBG _ASSERT(!this._itemData[itemIndex]); - this._itemData[itemIndex] = itemData; - if (!itemData.detached) { - this.notify(itemIndex, itemData); - } - }, - - notify: function ItemsContainer_notify(itemIndex, itemData) { - if (this.waitingItemRequests[itemIndex]) { - var requests = this.waitingItemRequests[itemIndex]; - for (var i = 0; i < requests.length; i++) { - requests[i](itemData.element); - } - - this.waitingItemRequests[itemIndex] = []; - } - }, - - elementAvailable: function ItemsContainer_elementAvailable(itemIndex) { - var itemData = this._itemData[itemIndex]; - itemData.detached = false; - this.notify(itemIndex, itemData); - }, - - itemAt: function ItemsContainer_itemAt(itemIndex) { - var itemData = this._itemData[itemIndex]; - return itemData ? itemData.element : null; - }, - - itemDataAt: function ItemsContainer_itemDataAt(itemIndex) { - return this._itemData[itemIndex]; - }, - - containerAt: function ItemsContainer_containerAt(itemIndex) { - var itemData = this._itemData[itemIndex]; - return itemData ? itemData.container : null; - }, - - itemBoxAt: function ItemsContainer_itemBoxAt(itemIndex) { - var itemData = this._itemData[itemIndex]; - return itemData ? itemData.itemBox : null; - }, - - itemBoxFrom: function ItemsContainer_containerFrom(element) { - while (element && !utilities.hasClass(element, WinJS.UI._itemBoxClass)) { - element = element.parentNode; - } - - return element; - }, - - containerFrom: function ItemsContainer_containerFrom(element) { - while (element && !utilities.hasClass(element, WinJS.UI._containerClass)) { - element = element.parentNode; - } - - return element; - }, - - index: function ItemsContainer_index(element) { - var item = this.containerFrom(element); - if (item) { - for (var index in this._itemData) { - if (this._itemData[index].container === item) { - return parseInt(index, 10); - } - } - } - - return WinJS.UI._INVALID_INDEX; - }, - - each: function ItemsContainer_each(callback) { - for (var index in this._itemData) { - if (this._itemData.hasOwnProperty(index)) { - var itemData = this._itemData[index]; - //#DBG _ASSERT(itemData); - callback(parseInt(index, 10), itemData.element, itemData); - } - } - }, - - eachIndex: function ItemsContainer_each(callback) { - for (var index in this._itemData) { - if (callback(parseInt(index, 10))) { - break; - } - } - }, - - count: function ItemsContainer_count() { - return Object.keys(this._itemData).length; - } - }; - return _ItemsContainer; - }) - }); - -})(this, WinJS); - -(function layouts2Init(global, WinJS, undefined) { - "use strict"; - - var Utilities = WinJS.Utilities, - Key = Utilities.Key, - Scheduler = Utilities.Scheduler; - - var strings = { - get itemInfoIsInvalid() { return WinJS.Resources._getWinJSString("ui/itemInfoIsInvalid").value; }, - get groupInfoResultIsInvalid() { return WinJS.Resources._getWinJSString("ui/groupInfoResultIsInvalid").value; } - }; - - // - // Helpers for dynamic CSS rules - // - // Rule deletions are delayed until the next rule insertion. This helps the - // scenario where a ListView changes layouts. By doing the rule manipulations - // in a single synchronous block, IE will do 1 layout pass instead of 2. - // - - // Dynamic CSS rules will be added to this style element - var layoutStyleElem = document.createElement("style"); - document.head.appendChild(layoutStyleElem); - - var nextCssClassId = 0, - staleClassNames = []; - - // The prefix for the class name should not contain dashes - function uniqueCssClassName(prefix) { - return "_win-dynamic-" + prefix + "-" + (nextCssClassId++); - } - - var dragBetweenTransition = "transform cubic-bezier(0.1, 0.9, 0.2, 1) 167ms"; - var dragBetweenDistance = 12; - - // Removes the dynamic CSS rules corresponding to the classes in staleClassNames - // from the DOM. - function flushDynamicCssRules() { - var rules = layoutStyleElem.sheet.cssRules, - classCount = staleClassNames.length, - i, - ruleCount, - j, - ruleSuffix; - - for (i = 0; i < classCount; i++) { - ruleSuffix = "." + staleClassNames[i] + " "; - for (j = rules.length - 1; j >= 0; j--) { - if (rules[j].selectorText.indexOf(ruleSuffix) !== -1) { - layoutStyleElem.sheet.deleteRule(j); - } - } - } - staleClassNames = []; - } - - // Creates a dynamic CSS rule and adds it to the DOM. uniqueToken is a class name - // which uniquely identifies a set of related rules. These rules may be removed - // using deleteDynamicCssRule. uniqueToken should be created using uniqueCssClassName. - function addDynamicCssRule(uniqueToken, site, selector, body) { - flushDynamicCssRules(); - var rule = "." + WinJS.UI._listViewClass + " ." + uniqueToken + " " + selector + " { " + - body + - "}"; - var perfId = "_addDynamicCssRule:" + uniqueToken + ",info"; - if (site) { - site._writeProfilerMark(perfId); - } else { - msWriteProfilerMark("WinJS.UI.ListView:Layout" + perfId); - } - layoutStyleElem.sheet.insertRule(rule, 0); - } - - // Marks the CSS rules corresponding to uniqueToken for deletion. The rules - // should have been added by addDynamicCssRule. - function deleteDynamicCssRule(uniqueToken) { - staleClassNames.push(uniqueToken); - } - - // - // Helpers shared by all layouts - // - - // Clamps x to the range first <= x <= last - function clampToRange(first, last, x) { - return Math.max(first, Math.min(last, x)); - } - - function getDimension(element, property) { - return WinJS.Utilities.convertToPixels(element, window.getComputedStyle(element, null)[property]); - } - - // Returns the sum of the margin, border, and padding for the side of the - // element specified by side. side can be "Left", "Right", "Top", or "Bottom". - function getOuter(side, element) { - return getDimension(element, "margin" + side) + - getDimension(element, "border" + side + "Width") + - getDimension(element, "padding" + side); - } - - // Returns the total height of element excluding its content height - function getOuterHeight(element) { - return getOuter("Top", element) + getOuter("Bottom", element); - } - - // Returns the total width of element excluding its content width - function getOuterWidth(element) { - return getOuter("Left", element) + getOuter("Right", element); - } - - function forEachContainer(itemsContainer, callback) { - if (itemsContainer.items) { - for (var i = 0, len = itemsContainer.items.length; i < len; i++) { - callback(itemsContainer.items[i], i); - } - } else { - for (var b = 0, index = 0; b < itemsContainer.itemsBlocks.length; b++) { - var block = itemsContainer.itemsBlocks[b]; - for (var i = 0, len = block.items.length; i < len; i++) { - callback(block.items[i], index++); - } - } - } - } - - function containerFromIndex(itemsContainer, index) { - if (index < 0) { - return null; - } - if (itemsContainer.items) { - return (index < itemsContainer.items.length ? itemsContainer.items[index] : null); - } else { - var blockSize = itemsContainer.itemsBlocks[0].items.length, - blockIndex = Math.floor(index / blockSize), - offset = index % blockSize; - return (blockIndex < itemsContainer.itemsBlocks.length && offset < itemsContainer.itemsBlocks[blockIndex].items.length ? itemsContainer.itemsBlocks[blockIndex].items[offset] : null); - } - } - - function getItemsContainerTree(itemsContainer, tree) { - var itemsContainerTree; - for (var i = 0, treeLength = tree.length; i < treeLength; i++) { - if (tree[i].itemsContainer.element === itemsContainer) { - itemsContainerTree = tree[i].itemsContainer; - break; - } - } - return itemsContainerTree; - } - - function getItemsContainerLength(itemsContainer) { - var blocksCount, - itemsCount; - if (itemsContainer.itemsBlocks) { - blocksCount = itemsContainer.itemsBlocks.length; - if (blocksCount > 0) { - itemsCount = (itemsContainer.itemsBlocks[0].items.length * (blocksCount - 1)) + itemsContainer.itemsBlocks[blocksCount - 1].items.length; - } else { - itemsCount = 0; - } - } else { - itemsCount = itemsContainer.items.length; - } - return itemsCount; - } - - WinJS.Namespace.define("WinJS.UI", { - Layout: WinJS.Class.define(function Layout_ctor(options) { - /// - /// - /// Creates a new Layout object. - /// - /// - /// The set of options to be applied initially to the new Layout object. - /// - /// - /// The new Layout object. - /// - /// - }), - - _LayoutCommon: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(WinJS.UI.Layout, null, { - /// - /// Gets or sets the position of group headers relative to their items. - /// The default value is "top". - /// - groupHeaderPosition: { - enumerable: true, - get: function () { - return this._groupHeaderPosition; - }, - set: function (position) { - this._groupHeaderPosition = position; - this._invalidateLayout(); - } - }, - - // Implementation of part of ILayout interface - - initialize: function _LayoutCommon_initialize(site, groupsEnabled) { - site._writeProfilerMark("Layout:initialize,info"); - if (!this._inListMode) { - Utilities.addClass(site.surface, WinJS.UI._gridLayoutClass); - } - if (this._backdropColorClassName) { - Utilities.addClass(site.surface, this._backdropColorClassName); - } - if (this._disableBackdropClassName) { - Utilities.addClass(site.surface, this._disableBackdropClassName); - } - this._groups = []; - this._groupMap = {}; - this._oldGroupHeaderPosition = null; - this._usingStructuralNodes = false; - - this._site = site; - this._groupsEnabled = groupsEnabled; - this._resetAnimationCaches(true); - }, - - /// - /// Gets or sets the orientation for the layout. - /// The default value is "horizontal". - /// - orientation: { - enumerable: true, - get: function () { - return this._orientation; - }, - set: function (orientation) { - this._orientation = orientation; - this._horizontal = (orientation === "horizontal"); - this._invalidateLayout(); - } - }, - - uninitialize: function _LayoutCommon_uninitialize() { - var that = this; - var perfId = "Layout:uninitialize,info"; - function cleanGroups(groups) { - var len = groups.length, - i; - for (i = 0; i < len; i++) { - groups[i].cleanUp(true); - } - } - - this._elementsToMeasure = {}; - - if (this._site) { - this._site._writeProfilerMark(perfId); - Utilities.removeClass(this._site.surface, WinJS.UI._gridLayoutClass); - Utilities.removeClass(this._site.surface, WinJS.UI._headerPositionTopClass); - Utilities.removeClass(this._site.surface, WinJS.UI._headerPositionLeftClass); - WinJS.Utilities.removeClass(this._site.surface, WinJS.UI._structuralNodesClass); - this._site.surface.style.cssText = ""; - if (this._groups) { - cleanGroups(this._groups); - this._groups = null; - this._groupMap = null; - } - if (this._layoutPromise) { - this._layoutPromise.cancel(); - this._layoutPromise = null; - } - this._resetMeasurements(); - this._oldGroupHeaderPosition = null; - this._usingStructuralNodes = null; - // The properties given to us by the app (_groupInfo, _itemInfo, - // _groupHeaderPosition) are not cleaned up so that the values are - // remembered if the layout is reused. - - if (this._backdropColorClassName) { - Utilities.removeClass(this._site.surface, this._backdropColorClassName); - deleteDynamicCssRule(this._backdropColorClassName); - this._backdropColorClassName = null; - } - if (this._disableBackdropClassName) { - Utilities.removeClass(this._site.surface, this._disableBackdropClassName); - deleteDynamicCssRule(this._disableBackdropClassName); - this._disableBackdropClassName = null; - } - - this._site = null; - this._groupsEnabled = null; - if (this._animationsRunning) { - this._animationsRunning.cancel(); - } - this._animatingItemsBlocks = {}; - } else { - msWriteProfilerMark("WinJS.UI.ListView:" + perfId); - } - }, - - numberOfItemsPerItemsBlock: { - get: function _LayoutCommon_getNumberOfItemsPerItemsBlock() { - function allGroupsAreUniform() { - var groupCount = that._site.groupCount, - i; - - for (i = 0; i < groupCount; i++) { - if (that._isCellSpanning(i)) { - return false; - } - } - - return true; - } - - var that = this; - return that._measureItem(0).then(function () { - if (that._sizes.viewportContentSize !== that._getViewportCrossSize()) { - that._viewportSizeChanged(that._getViewportCrossSize()); - } - - if (allGroupsAreUniform()) { - that._usingStructuralNodes = WinJS.UI._LayoutCommon._barsPerItemsBlock > 0; - return WinJS.UI._LayoutCommon._barsPerItemsBlock * that._itemsPerBar; - } else { - that._usingStructuralNodes = false; - return null; - } - }); - } - }, - - layout: function _LayoutCommon_layout(tree, changedRange, modifiedItems, modifiedGroups) { - // changedRange implies that the minimum amount of work the layout needs to do is as follows: - // - It needs to lay out group shells (header containers and items containers) from - // firstChangedGroup thru lastGroup. - // - It needs to ask firstChangedGroup thru lastChangedGroup to lay out their - // contents (i.e. win-containers). - // - For each group included in the changedRange, it needs to lay out its - // contents (i.e. win-containers) from firstChangedItem thru lastItem. - - var that = this; - var site = that._site, - layoutPerfId = "Layout.layout", - realizedRangePerfId = layoutPerfId + ":realizedRange", - realizedRangePromise; - - that._site._writeProfilerMark(layoutPerfId + ",StartTM"); - that._site._writeProfilerMark(realizedRangePerfId + ",StartTM"); - - // Receives an items container's tree and returns a normalized copy. - // This allows us to hold on to a snapshot of the tree without - // worrying that items may have been unexpectedly inserted/ - // removed/moved. The returned tree always appears as though - // structural nodes are disabled. - function copyItemsContainerTree(itemsContainer) { - function copyItems(itemsContainer) { - if (that._usingStructuralNodes) { - var items = []; - itemsContainer.itemsBlocks.forEach(function (itemsBlock) { - items = items.concat(itemsBlock.items.slice(0)); - }); - return items; - } else { - return itemsContainer.items.slice(0); - } - } - - return { - element: itemsContainer.element, - items: copyItems(itemsContainer) - }; - } - - // Updates the GridLayout's internal state to reflect the current tree. - // Similarly tells each group to update its internal state via prepareLayout. - // After this function runs, the ILayout functions will return results that - // are appropriate for the current tree. - function updateGroups() { - function createGroup(groupInfo, itemsContainer) { - var GroupType = (groupInfo.enableCellSpanning ? - Groups.CellSpanningGroup : - Groups.UniformGroup); - return new GroupType(that, itemsContainer); - } - - var oldRealizedItemRange = (that._groups.length > 0 ? - that._getRealizationRange() : - null), - newGroups = [], - prepared = [], - cleanUpDom = {}, - newGroupMap = {}, - currentIndex = 0, - len = tree.length, - i; - - for (i = 0; i < len; i++) { - var oldChangedRealizedRangeInGroup = null, - groupInfo = that._getGroupInfo(i), - groupKey = that._site.groupFromIndex(i).key, - oldGroup = that._groupMap[groupKey], - wasCellSpanning = oldGroup instanceof Groups.CellSpanningGroup, - isCellSpanning = groupInfo.enableCellSpanning; - - if (oldGroup) { - if (wasCellSpanning !== isCellSpanning) { - // The group has changed types so DOM needs to be cleaned up - cleanUpDom[groupKey] = true; - } else { - // Compute the range of changed items that is within the group's realized range - var firstChangedIndexInGroup = Math.max(0, changedRange.firstIndex - oldGroup.startIndex), - oldRealizedItemRangeInGroup = that._rangeForGroup(oldGroup, oldRealizedItemRange); - if (oldRealizedItemRangeInGroup && firstChangedIndexInGroup <= oldRealizedItemRangeInGroup.lastIndex) { - // The old changed realized range is non-empty - oldChangedRealizedRangeInGroup = { - firstIndex: Math.max(firstChangedIndexInGroup, oldRealizedItemRangeInGroup.firstIndex), - lastIndex: oldRealizedItemRangeInGroup.lastIndex - }; - } - } - } - var group = createGroup(groupInfo, tree[i].itemsContainer.element); - var prepareLayoutPromise; - if (group.prepareLayoutWithCopyOfTree) { - prepareLayoutPromise = group.prepareLayoutWithCopyOfTree(copyItemsContainerTree(tree[i].itemsContainer), oldChangedRealizedRangeInGroup, oldGroup, { - groupInfo: groupInfo, - startIndex: currentIndex, - }); - } else { - prepareLayoutPromise = group.prepareLayout(getItemsContainerLength(tree[i].itemsContainer), oldChangedRealizedRangeInGroup, oldGroup, { - groupInfo: groupInfo, - startIndex: currentIndex, - }); - } - prepared.push(prepareLayoutPromise); - - currentIndex += group.count; - - newGroups.push(group); - newGroupMap[groupKey] = group; - } - - return WinJS.Promise.join(prepared).then(function () { - var currentOffset = 0; - for (var i = 0, len = newGroups.length; i < len; i++) { - var group = newGroups[i]; - group.offset = currentOffset; - currentOffset += that._getGroupSize(group); - } - - // Clean up deleted groups - Object.keys(that._groupMap).forEach(function (deletedKey) { - var skipDomCleanUp = !cleanUpDom[deletedKey]; - that._groupMap[deletedKey].cleanUp(skipDomCleanUp); - }); - - that._groups = newGroups; - that._groupMap = newGroupMap; - }); - } - - // When doRealizedRange is true, this function is synchronous and has no return value. - // When doRealizedRange is false, this function is asynchronous and returns a promise. - function layoutGroupContent(groupIndex, realizedItemRange, doRealizedRange) { - var group = that._groups[groupIndex], - firstChangedIndexInGroup = Math.max(0, changedRange.firstIndex - group.startIndex), - realizedItemRangeInGroup = that._rangeForGroup(group, realizedItemRange), - beforeRealizedRange; - - if (doRealizedRange) { - group.layoutRealizedRange(firstChangedIndexInGroup, realizedItemRangeInGroup); - } else { - if (!realizedItemRangeInGroup) { - beforeRealizedRange = (group.startIndex + group.count - 1 < realizedItemRange.firstIndex); - } - - return group.layoutUnrealizedRange(firstChangedIndexInGroup, realizedItemRangeInGroup, beforeRealizedRange); - } - } - - // Synchronously lays out: - // - Realized and unrealized group shells (header containers and items containers). - // This is needed so that each realized group will be positioned at the correct offset. - // - Realized items. - function layoutRealizedRange() { - if (that._groups.length === 0) { - return; - } - - var realizedItemRange = that._getRealizationRange(), - len = tree.length, - i, - firstChangedGroup = site.groupIndexFromItemIndex(changedRange.firstIndex); - - for (i = firstChangedGroup; i < len; i++) { - layoutGroupContent(i, realizedItemRange, true); - that._layoutGroup(i); - } - } - - // Asynchronously lays out the unrealized items - function layoutUnrealizedRange() { - if (that._groups.length === 0) { - return WinJS.Promise.wrap(); - } - - var realizedItemRange = that._getRealizationRange(), - // Last group before the realized range which contains 1 or more unrealized items - lastGroupBefore = site.groupIndexFromItemIndex(realizedItemRange.firstIndex - 1), - // First group after the realized range which contains 1 or more unrealized items - firstGroupAfter = site.groupIndexFromItemIndex(realizedItemRange.lastIndex + 1), - firstChangedGroup = site.groupIndexFromItemIndex(changedRange.firstIndex), - layoutPromises = [], - groupCount = that._groups.length; - - var stop = false; - var before = lastGroupBefore; - var after = Math.max(firstChangedGroup, firstGroupAfter); - after = Math.max(before + 1, after); - while (!stop) { - stop = true; - if (before >= firstChangedGroup) { - layoutPromises.push(layoutGroupContent(before, realizedItemRange, false)); - stop = false; - before--; - } - if (after < groupCount) { - layoutPromises.push(layoutGroupContent(after, realizedItemRange, false)); - stop = false; - after++; - } - } - - return WinJS.Promise.join(layoutPromises); - } - - realizedRangePromise = that._measureItem(0).then(function () { - WinJS.Utilities[that._usingStructuralNodes ? "addClass" : "removeClass"](that._site.surface, WinJS.UI._structuralNodesClass); - - if (that._sizes.viewportContentSize !== that._getViewportCrossSize()) { - that._viewportSizeChanged(that._getViewportCrossSize()); - } - - // Move deleted elements to their original positions before calling updateGroups can be slow. - that._cacheRemovedElements(modifiedItems, that._cachedItemRecords, that._cachedInsertedItemRecords, that._cachedRemovedItems, false); - that._cacheRemovedElements(modifiedGroups, that._cachedHeaderRecords, that._cachedInsertedHeaderRecords, that._cachedRemovedHeaders, true); - - return updateGroups(); - }).then(function () { - that._syncDomWithGroupHeaderPosition(tree); - - // Explicitly set the surface width/height. This maintains backwards - // compatibility with the original layouts by allowing the items - // to be shifted through surface margins. - if (that._horizontal) { - if (that._groupsEnabled && that._groupHeaderPosition === WinJS.UI.HeaderPosition.left) { - site.surface.style.cssText += - ";height:" + that._sizes.surfaceContentSize + - "px;-ms-grid-columns: (" + that._sizes.headerContainerWidth + "px auto)[" + tree.length + "]"; - } else { - site.surface.style.height = that._sizes.surfaceContentSize + "px"; - } - } else { - if (that._groupsEnabled && that._groupHeaderPosition === WinJS.UI.HeaderPosition.top) { - site.surface.style.cssText += - ";width:" + that._sizes.surfaceContentSize + - "px;-ms-grid-rows: (" + that._sizes.headerContainerHeight + "px auto)[" + tree.length + "]"; - } else { - site.surface.style.width = that._sizes.surfaceContentSize + "px"; - } - } - - layoutRealizedRange(); - - that._layoutAnimations(modifiedItems, modifiedGroups); - - that._site._writeProfilerMark(realizedRangePerfId + ":complete,info"); - that._site._writeProfilerMark(realizedRangePerfId + ",StopTM"); - }, function (error) { - that._site._writeProfilerMark(realizedRangePerfId + ":canceled,info"); - that._site._writeProfilerMark(realizedRangePerfId + ",StopTM"); - return WinJS.Promise.wrapError(error); - }); - - that._layoutPromise = realizedRangePromise.then(function () { - return layoutUnrealizedRange().then(function () { - that._site._writeProfilerMark(layoutPerfId + ":complete,info"); - that._site._writeProfilerMark(layoutPerfId + ",StopTM"); - }, function (error) { - that._site._writeProfilerMark(layoutPerfId + ":canceled,info"); - that._site._writeProfilerMark(layoutPerfId + ",StopTM"); - return WinJS.Promise.wrapError(error); - }); - }); - - return { - realizedRangeComplete: realizedRangePromise, - layoutComplete: that._layoutPromise - }; - }, - - itemsFromRange: function _LayoutCommon_itemsFromRange(firstPixel, lastPixel) { - if (this._rangeContainsItems(firstPixel, lastPixel)) { - return { - firstIndex: this._firstItemFromRange(firstPixel), - lastIndex: this._lastItemFromRange(lastPixel) - }; - } else { - return { - firstIndex: 0, - lastIndex: -1 - }; - } - - }, - - getAdjacent: function _LayoutCommon_getAdjacent(currentItem, pressedKey) { - var that = this, - groupIndex = that._site.groupIndexFromItemIndex(currentItem.index), - group = that._groups[groupIndex], - adjustedKey = that._adjustedKeyForOrientationAndBars(that._adjustedKeyForRTL(pressedKey), group instanceof Groups.CellSpanningGroup); - - if (currentItem.type === WinJS.UI.ObjectType.groupHeader) { - if (pressedKey === Key.pageUp || pressedKey === Key.pageDown) { - // We treat page up and page down keys as if an item had focus - currentItem = { type: WinJS.UI.ObjectType.item, index: this._groups[currentItem.index].startIndex }; - } else { - switch (adjustedKey) { - case Key.leftArrow: - return { type: WinJS.UI.ObjectType.groupHeader, index: Math.max(0, currentItem.index - 1) }; - case Key.rightArrow: - return { type: WinJS.UI.ObjectType.groupHeader, index: Math.min(that._groups.length - 1, currentItem.index + 1) }; - } - return currentItem; - } - } - - function handleArrowKeys() { - var currentItemInGroup = { - type: currentItem.type, - index: currentItem.index - group.startIndex - }, - newItem = group.getAdjacent(currentItemInGroup, adjustedKey); - - if (newItem === "boundary") { - var prevGroup = that._groups[groupIndex - 1], - nextGroup = that._groups[groupIndex + 1], - lastGroupIndex = that._groups.length - 1; - - if (adjustedKey === Key.leftArrow) { - if (groupIndex === 0) { - // We're at the beginning of the first group so stay put - return currentItem; - } else if (prevGroup instanceof Groups.UniformGroup && group instanceof Groups.UniformGroup) { - // Moving between uniform groups so maintain the row/column if possible - var coordinates = that._indexToCoordinate(currentItemInGroup.index); - var currentSlot = (that._horizontal ? coordinates.row : coordinates.column), - indexOfLastBar = Math.floor((prevGroup.count - 1) / that._itemsPerBar), - startOfLastBar = indexOfLastBar * that._itemsPerBar; // first cell of last bar - return { - type: WinJS.UI.ObjectType.item, - index: prevGroup.startIndex + Math.min(prevGroup.count - 1, startOfLastBar + currentSlot) - }; - } else { - // Moving to or from a cell spanning group so go to the last item - return { type: WinJS.UI.ObjectType.item, index: group.startIndex - 1 }; - } - } else if (adjustedKey === Key.rightArrow) { - if (groupIndex === lastGroupIndex) { - // We're at the end of the last group so stay put - return currentItem; - } else if (group instanceof Groups.UniformGroup && nextGroup instanceof Groups.UniformGroup) { - // Moving between uniform groups so maintain the row/column if possible - var coordinates = that._indexToCoordinate(currentItemInGroup.index), - currentSlot = (that._horizontal ? coordinates.row : coordinates.column); - return { - type: WinJS.UI.ObjectType.item, - index: nextGroup.startIndex + Math.min(nextGroup.count - 1, currentSlot) - }; - } else { - // Moving to or from a cell spanning group so go to the first item - return { type: WinJS.UI.ObjectType.item, index: nextGroup.startIndex }; - } - } else { - //#DBG _ASSERT(adjustedKey === Key.downArrow || adjustedKey === Key.upArrow); - return currentItem; - } - } else { - newItem.index += group.startIndex; - return newItem; - } - } - - switch (that._adjustedKeyForRTL(pressedKey)) { - case Key.upArrow: - case Key.leftArrow: - case Key.downArrow: - case Key.rightArrow: - return handleArrowKeys(); - default: - return WinJS.UI._LayoutCommon.prototype._getAdjacentForPageKeys.call(that, currentItem, pressedKey); - } - }, - - hitTest: function _LayoutCommon_hitTest(x, y) { - var sizes = this._sizes, - result; - - // Make the coordinates relative to grid layout's content box - x -= sizes.layoutOriginX; - y -= sizes.layoutOriginY; - - var groupIndex = this._groupFromOffset(this._horizontal ? x : y), - group = this._groups[groupIndex]; - - // Make the coordinates relative to the margin box of the group's items container - if (this._horizontal) { - x -= group.offset; - } else { - y -= group.offset; - } - if (this._groupsEnabled) { - if (this._groupHeaderPosition === WinJS.UI.HeaderPosition.left) { - x -= sizes.headerContainerWidth; - } else { - // Headers above - y -= sizes.headerContainerHeight; - } - } - - result = group.hitTest(x, y); - result.index += group.startIndex; - result.insertAfterIndex += group.startIndex; - return result; - }, - - // Animation cycle: - // - // Edits - // --- UpdateTree Realize - // | | --- /\/\ - // | | | | | | - // ------------------------------------------------------- Time - // | | | | | | | | - // --- | | --- ---/\/\/\/\/\/\/\/\/ - // setupAni | | layoutAni endAni (animations) - // ---/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ - // layout (outside realized range) - // - // - // When there is a modification to the DataSource, the first thing that happens is setupAnimations is - // called with the current tree. This allows us to cache the locations of the existing items. - // - // The next 3 steps have to be completely synchronous otherwise users will see intermediate states and - // items will blink or jump between locations. - // - // ListView modifies the DOM tree. A container is added/removed from the group's itemsContainer for each - // item added/removed to the group. The existing itemBoxes are shuffled between the different containers. - // The itemBoxes for the removed items will be removed from the containers completely. Since the DOM tree - // has been modified we have to apply a transform to position the itemBoxes at their original location. We - // compare the new locations with the cached locations to figure out how far to translate the itemBoxes. - // Also the removed items need to be placed back in the DOM without affecting layout (by using position - // absolute) so that they also do not jump or blink. - // - // We only tranform and add back removed items for items which were on screen or are now on screen. - // - // Now the ListView can realize other items asynchronously. The items to realize are items which have been - // inserted into the DataSource or items which are in the realization range because a removal has occurred - // or the user has scroll slightly. - // - // During the realization pass the user may scroll. If they scroll to a range outside of the realization - // range the items will just appear in the correct location without any animations. If they scroll to a - // location within the old realization range we still have the items and they will animate correctly. - // - // During the realization pass another data source edit can occur. A realization pass is unable to run when - // the tree and layout are out of sync. Otherwise it may try to request item at index X and get item at - // index X + 1. This means that if another data source edit occurs before endAnimations is called we - // restart the whole animation cycle. To group the animations between the two edits we do not reset the - // caches of item box locations. We could add to it if there were items outside of the range however they - // will only play half of the animation and will probably look just as ugly as not playing the animation at - // all. This means setupAnimations will just be a no op in this scenario. - // - // This also shows that batching data source edits and only changing the data source when in loadingstate - // "complete" is still a large performance win. - // - // Once the realization pass has finished ListView calls executeAnimations. This is where the layout - // effectively fades out the removed items (and then removes them from the dom), moves the itemBoxes back - // to translate(0,0), and fades in the inserted itemBoxes. ListView waits for the executeAnimations promise - // to complete before allowing more data source edits to trigger another animation cycle. - // - // If a resize occurs during the animation cycle the animations will be canceled and items will jump to - // their final positions. - - setupAnimations: function _LayoutCommon_setupAnimations() { - // This function is called after a data source change so that we can cache the locations - // of the realized items. - - if (this._groups.length === 0) { - // No animations if we haven't measured before - this._resetAnimationCaches(); - return; - } - - if (Object.keys(this._cachedItemRecords).length) { - // Ignore the second call. - return; - } - - this._site._writeProfilerMark("Animation:setupAnimations,StartTM"); - - var realizationRange = this._getRealizationRange(); - - var tree = this._site.tree; - var itemIndex = 0; - var horizontal = (this.orientation === "horizontal"); - for (var i = 0, treeLength = tree.length; i < treeLength; i++) { - var groupBundle = tree[i]; - var groupHasAtleastOneItemRealized = false; - var group = this._groups[i]; - var groupIsCellSpanning = group instanceof Groups.CellSpanningGroup; - var groupOffset = (group ? group.offset : 0); - - forEachContainer(groupBundle.itemsContainer, function (container, j) { - // Don't try to cache something outside of the realization range. - if (realizationRange.firstIndex <= itemIndex && realizationRange.lastIndex >= itemIndex) { - groupHasAtleastOneItemRealized = true; - - if (!this._cachedItemRecords[itemIndex]) { - var itemPosition = this._getItemPositionForAnimations(itemIndex, i, j); - var row = itemPosition.row; - var column = itemPosition.column; - var left = itemPosition.left; - var top = itemPosition.top; - - // Setting both old and new variables now in case layoutAnimations is called multiple times. - this._cachedItemRecords[itemIndex] = { - oldRow: row, - oldColumn: column, - oldLeft: left, - oldTop: top, - width: itemPosition.width, - height: itemPosition.height, - element: container, - inCellSpanningGroup: groupIsCellSpanning - }; - } - } - itemIndex++; - }.bind(this)); - - if (groupHasAtleastOneItemRealized) { - var groupIndex = i; - if (!this._cachedHeaderRecords[groupIndex]) { - var headerPosition = this._getHeaderPositionForAnimations(groupIndex); - this._cachedHeaderRecords[groupIndex] = { - oldLeft: headerPosition.left, - oldTop: headerPosition.top, - width: headerPosition.width, - height: headerPosition.height, - element: groupBundle.header, - }; - } - if (!this._cachedGroupRecords[groupBundle.itemsContainer.element.uniqueID]) { - this._cachedGroupRecords[groupBundle.itemsContainer.element.uniqueID] = { - oldLeft: horizontal ? groupOffset : 0, - left: horizontal ? groupOffset : 0, - oldTop: horizontal ? 0 : groupOffset, - top: horizontal ? 0 : groupOffset, - element: groupBundle.itemsContainer.element, - }; - } - } - } - - this._site._writeProfilerMark("Animation:setupAnimations,StopTM"); - }, - - _layoutAnimations: function _LayoutCommon_layoutAnimations(modifiedItems, modifiedGroups) { - // This function is called after the DOM tree has been modified to match the data source. - // In this function we update the cached records and apply transforms to hide the modifications - // from the user. We will remove the transforms via animations in execute animation. - - //#DBG _ASSERT(!this._animationsRunning); - - if (!Object.keys(this._cachedItemRecords).length && - !Object.keys(this._cachedGroupRecords).length && - !Object.keys(this._cachedHeaderRecords).length) { - return; - } - - this._site._writeProfilerMark("Animation:layoutAnimation,StartTM"); - - this._updateAnimationCache(modifiedItems, modifiedGroups); - - var realizationRange = this._getRealizationRange(); - - var tree = this._site.tree; - var itemIndex = 0; - var horizontal = (this.orientation === "horizontal"); - for (var i = 0, treeLength = tree.length; i < treeLength; i++) { - var groupBundle = tree[i]; - var group = this._groups[i]; - var groupIsCellSpanning = group instanceof Groups.CellSpanningGroup; - var groupOffset = (group ? group.offset : 0); - var groupMovementX = 0; - var groupMovementY = 0; - - var cachedGroupRecord = this._cachedGroupRecords[groupBundle.itemsContainer.element.uniqueID]; - if (cachedGroupRecord) { - if (horizontal) { - groupMovementX = cachedGroupRecord.oldLeft - groupOffset; - } else { - groupMovementY = cachedGroupRecord.oldTop - groupOffset; - } - } - - - forEachContainer(groupBundle.itemsContainer, function (container, j) { - // Don't try to cache something outside of the realization range. - if (realizationRange.firstIndex <= itemIndex && realizationRange.lastIndex >= itemIndex) { - var cachedItemRecord = this._cachedItemRecords[itemIndex]; - if (cachedItemRecord) { - var itemPosition = this._getItemPositionForAnimations(itemIndex, i, j); - var row = itemPosition.row; - var column = itemPosition.column; - var left = itemPosition.left; - var top = itemPosition.top; - - cachedItemRecord.inCellSpanningGroup = cachedItemRecord.inCellSpanningGroup || groupIsCellSpanning; - - // If the item has moved we need to update the cache and apply a transform to make it - // appear like it has not moved yet. - if (cachedItemRecord.oldRow !== row || - cachedItemRecord.oldColumn !== column || - cachedItemRecord.oldTop !== top || - cachedItemRecord.oldLeft !== left) { - - cachedItemRecord.row = row; - cachedItemRecord.column = column; - cachedItemRecord.left = left; - cachedItemRecord.top = top; - - var xOffset = cachedItemRecord.oldLeft - cachedItemRecord.left - groupMovementX; - var yOffset = cachedItemRecord.oldTop - cachedItemRecord.top - groupMovementY; - xOffset = (this._site.rtl ? -1 : 1) * xOffset; - - cachedItemRecord.xOffset = xOffset; - cachedItemRecord.yOffset = yOffset; - if (xOffset !== 0 || yOffset !== 0) { - var element = cachedItemRecord.element; - cachedItemRecord.needsToResetTransform = true; - element.style.transition = ""; - element.style.transform = "translate(" + xOffset + "px," + yOffset + "px)"; - } - - var itemsBlock = container.parentNode; - if (WinJS.Utilities.hasClass(itemsBlock, WinJS.UI._itemsBlockClass)) { - this._animatingItemsBlocks[itemsBlock.uniqueID] = itemsBlock; - } - } - - } else { - // Treat items that came from outside of the realization range into the realization range - // as a "Move" which means fade it in. - this._cachedInsertedItemRecords[itemIndex] = container; - container.style.transition = ""; - container.style.opacity = 0; - } - } - - itemIndex++; - }.bind(this)); - - var groupIndex = i; - var cachedHeader = this._cachedHeaderRecords[groupIndex]; - if (cachedHeader) { - var headerPosition = this._getHeaderPositionForAnimations(groupIndex); - // Note: If a group changes width we allow the header to immediately grow/shrink instead of - // animating it. However if the header is removed we stick the header to the last known size. - cachedHeader.height = headerPosition.height; - cachedHeader.width = headerPosition.width; - if (cachedHeader.oldLeft !== headerPosition.left || - cachedHeader.oldTop !== headerPosition.top) { - - cachedHeader.left = headerPosition.left; - cachedHeader.top = headerPosition.top; - - var xOffset = cachedHeader.oldLeft - cachedHeader.left; - var yOffset = cachedHeader.oldTop - cachedHeader.top; - xOffset = (this._site.rtl ? -1 : 1) * xOffset; - if (xOffset !== 0 || yOffset !== 0) { - cachedHeader.needsToResetTransform = true; - var headerContainer = cachedHeader.element; - headerContainer.style.transition = ""; - headerContainer.style.transform = "translate(" + xOffset + "px," + yOffset + "px)"; - } - } - } - - if (cachedGroupRecord) { - if ((horizontal && cachedGroupRecord.left !== groupOffset) || - (!horizontal && cachedGroupRecord.top !== groupOffset)) { - var element = cachedGroupRecord.element; - if (groupMovementX === 0 && groupMovementY === 0) { - if (cachedGroupRecord.needsToResetTransform) { - cachedGroupRecord.needsToResetTransform = false; - element.style.transform = ""; - } - } else { - var groupOffsetX = (this._site.rtl ? -1 : 1) * groupMovementX, - groupOffsetY = groupMovementY; - cachedGroupRecord.needsToResetTransform = true; - element.style.transition = ""; - element.style.transform = "translate(" + groupOffsetX + "px, " + groupOffsetY + "px)"; - } - } - } - } - - if (this._inListMode || this._itemsPerBar === 1) { - var itemsBlockKeys = Object.keys(this._animatingItemsBlocks); - for (var b = 0, blockKeys = itemsBlockKeys.length; b < blockKeys; b++) { - this._animatingItemsBlocks[itemsBlockKeys[b]].style.overflow = 'visible'; - } - } - - this._site._writeProfilerMark("Animation:layoutAnimation,StopTM"); - }, - - executeAnimations: function _LayoutCommon_executeAnimations() { - // This function is called when we should perform an animation to reveal the true location of the items. - // We fade out removed items, fade in added items, and move items which need to be shifted. If they moved - // across columns we do a reflow animation. - - //#DBG _ASSERT(!this._animationsRunning); - - var animationSignal = new WinJS._Signal(); - - // Only animate the items on screen. - this._filterInsertedElements(); - this._filterMovedElements(); - this._filterRemovedElements(); - - if (this._insertedElements.length === 0 && this._removedElements.length === 0 && this._itemMoveRecords.length === 0 && this._moveRecords.length === 0) { - // Nothing to animate. - this._resetAnimationCaches(true); - animationSignal.complete(); - return animationSignal.promise; - } - this._animationsRunning = animationSignal.promise; - - var slowAnimations = WinJS.UI.Layout._debugAnimations || WinJS.UI.Layout._slowAnimations; - var site = this._site; - var insertedElements = this._insertedElements; - var removedElements = this._removedElements; - var itemMoveRecords = this._itemMoveRecords; - var moveRecords = this._moveRecords; - - var removeDelay = 0; - var moveDelay = 0; - var addDelay = 0; - - var currentAnimationPromise = null; - var pendingTransitionPromises = []; - var listenerElement = this._site.surface; - - var hasMultisizeMove = false; - var hasReflow = false; - var minOffset = 0; - var maxOffset = 0; - var itemContainersToExpand = {}; - var upOutDist = 0; - var downOutDist = 0; - var upInDist = 0; - var downInDist = 0; - var reflowItemRecords = []; - var horizontal = (this.orientation === "horizontal"); - var oldReflowLayoutProperty = horizontal ? "oldColumn" : "oldRow", - reflowLayoutProperty = horizontal ? "column" : "row", - oldReflowLayoutPosition = horizontal ? "oldTop" : "oldLeft", - reflowLayoutPosition = horizontal ? "top" : "left"; - - var animatingItemsBlocks = this._animatingItemsBlocks; - - for (var i = 0, len = itemMoveRecords.length; i < len; i++) { - var cachedItemRecord = itemMoveRecords[i]; - if (cachedItemRecord.inCellSpanningGroup) { - hasMultisizeMove = true; - break; - } - } - - var that = this; - - function startAnimations() { - removePhase(); - if (hasMultisizeMove) { - cellSpanningFadeOutMove(); - } else { - if (that._itemsPerBar > 1) { - var maxDistance = that._itemsPerBar * that._sizes.containerCrossSize + that._getHeaderSizeContentAdjustment() + - that._sizes.containerMargins[horizontal ? "top" : (site.rtl ? "right" : "left")] + - (horizontal ? that._sizes.layoutOriginY : that._sizes.layoutOriginX) - for (var i = 0, len = itemMoveRecords.length; i < len; i++) { - var cachedItemRecord = itemMoveRecords[i]; - if (cachedItemRecord[oldReflowLayoutProperty] > cachedItemRecord[reflowLayoutProperty]) { - upOutDist = Math.max(upOutDist, cachedItemRecord[oldReflowLayoutPosition] + cachedItemRecord[horizontal ? "height" : "width"]); - upInDist = Math.max(upInDist, maxDistance - cachedItemRecord[reflowLayoutPosition]); - hasReflow = true; - reflowItemRecords.push(cachedItemRecord); - } else if (cachedItemRecord[oldReflowLayoutProperty] < cachedItemRecord[reflowLayoutProperty]) { - downOutDist = Math.max(downOutDist, maxDistance - cachedItemRecord[oldReflowLayoutPosition]); - downInDist = Math.max(downInDist, cachedItemRecord[reflowLayoutPosition] + cachedItemRecord[horizontal ? "height" : "width"]); - reflowItemRecords.push(cachedItemRecord); - hasReflow = true; - } - } - } - - if (site.rtl && !horizontal) { - upOutDist *= -1; - upInDist *= -1; - downOutDist *= -1; - downInDist *= -1; - } - - if (hasReflow) { - reflowPhase(that._itemsPerBar); - } else { - directMovePhase(); - } - } - } - - if (WinJS.UI.Layout._debugAnimations) { - requestAnimationFrame(function () { - startAnimations() - }); - } else { - startAnimations(); - } - - function waitForNextPhase(nextPhaseCallback) { - currentAnimationPromise = WinJS.Promise.join(pendingTransitionPromises); - currentAnimationPromise.done(function () { - pendingTransitionPromises = []; - // The success is called even if the animations are canceled due to the WinJS.UI.executeTransition - // API. To deal with that we check the animationSignal variable. If it is null the animations were - // canceled so we shouldn't continue. - if (animationSignal) { - if (WinJS.UI.Layout._debugAnimations) { - requestAnimationFrame(function () { - nextPhaseCallback(); - }) - } else { - nextPhaseCallback(); - } - } - }); - } - - function removePhase() { - if (removedElements.length) { - site._writeProfilerMark("Animation:setupRemoveAnimation,StartTM"); - - moveDelay += 60; - addDelay += 60; - - var removeDuration = 120; - if (slowAnimations) { - removeDuration *= 10; - } - - pendingTransitionPromises.push(WinJS.UI.executeTransition(removedElements, - [{ - property: "opacity", - delay: removeDelay, - duration: removeDuration, - timing: "linear", - to: 0, - skipStylesReset: true - }])); - - site._writeProfilerMark("Animation:setupRemoveAnimation,StopTM"); - } - } - - function cellSpanningFadeOutMove() { - site._writeProfilerMark("Animation:cellSpanningFadeOutMove,StartTM"); - - // For multisize items which move we fade out and then fade in (opacity 1->0->1) - var moveElements = []; - for (var i = 0, len = itemMoveRecords.length; i < len; i++) { - var cachedItemRecord = itemMoveRecords[i]; - var container = cachedItemRecord.element; - moveElements.push(container); - } - // Including groups and headers. - for (var i = 0, len = moveRecords.length; i < len; i++) { - var cachedItemRecord = moveRecords[i]; - var container = cachedItemRecord.element; - moveElements.push(container); - } - - var fadeOutDuration = 120; - if (slowAnimations) { - fadeOutDuration *= 10; - } - - pendingTransitionPromises.push(WinJS.UI.executeTransition(moveElements, - { - property: "opacity", - delay: removeDelay, - duration: fadeOutDuration, - timing: "linear", - to: 0 - })); - - waitForNextPhase(cellSpanningFadeInMove); - site._writeProfilerMark("Animation:cellSpanningFadeOutMove,StopTM"); - } - - function cellSpanningFadeInMove() { - site._writeProfilerMark("Animation:cellSpanningFadeInMove,StartTM"); - - addDelay = 0; - - var moveElements = []; - // Move them to their final location. - for (var i = 0, len = itemMoveRecords.length; i < len; i++) { - var cachedItemRecord = itemMoveRecords[i]; - var container = cachedItemRecord.element; - container.style.transform = ""; - moveElements.push(container); - } - // Including groups and headers. - for (var i = 0, len = moveRecords.length; i < len; i++) { - var cachedItemRecord = moveRecords[i]; - var container = cachedItemRecord.element; - container.style.transform = ""; - moveElements.push(container); - } - - var fadeInDuration = 120; - if (slowAnimations) { - fadeInDuration *= 10; - } - - // For multisize items which move we fade out and then fade in (opacity 1->0->1) - pendingTransitionPromises.push(WinJS.UI.executeTransition(moveElements, - { - property: "opacity", - delay: addDelay, - duration: fadeInDuration, - timing: "linear", - to: 1 - })); - - site._writeProfilerMark("Animation:cellSpanningFadeInMove,StopTM"); - - addPhase(); - } - - function reflowPhase(itemsPerBar) { - site._writeProfilerMark("Animation:setupReflowAnimation,StartTM"); - - var itemContainersLastBarIndices = {} - for (var i = 0, len = reflowItemRecords.length; i < len; i++) { - var reflowItemRecord = reflowItemRecords[i]; - var xOffset = reflowItemRecord.xOffset; - var yOffset = reflowItemRecord.yOffset; - if (reflowItemRecord[oldReflowLayoutProperty] > reflowItemRecord[reflowLayoutProperty]) { - if (horizontal) { - yOffset -= upOutDist; - } else { - xOffset -= upOutDist; - } - } else if (reflowItemRecord[oldReflowLayoutProperty] < reflowItemRecord[reflowLayoutProperty]) { - if (horizontal) { - yOffset += downOutDist; - } else { - xOffset += downOutDist; - } - } - - var container = reflowItemRecord.element; - - minOffset = Math.min(minOffset, horizontal ? xOffset : yOffset); - maxOffset = Math.max(maxOffset, horizontal ? xOffset : yOffset); - var itemsContainer = container.parentNode; - if (!WinJS.Utilities.hasClass(itemsContainer, "win-itemscontainer")) { - itemsContainer = itemsContainer.parentNode - } - - // The itemscontainer element is always overflow:hidden for two reasons: - // 1) Better panning performance - // 2) When there is margin betweeen the itemscontainer and the surface elements, items that - // reflow should not be visible while they travel long distances or overlap with headers. - // This introduces an issue when updateTree makes the itemscontainer smaller, but we need its size - // to remain the same size during the execution of the animation to avoid having some of the animated - // items being clipped. This is only an issue when items from the last column (in horizontal mode) or row - // (in vertical mode) of the group will reflow. Therefore, we change the padding so that the contents are larger, - // and then use margin to reverse the size change. We don't do this expansion when it is unnecessary because the - // layout/formatting caused by these style changes has significant cost when the group has thousands of items. - var lastBarIndex = itemContainersLastBarIndices[itemsContainer.uniqueID]; - if (!lastBarIndex) { - var count = getItemsContainerLength(getItemsContainerTree(itemsContainer, site.tree)); - itemContainersLastBarIndices[itemsContainer.uniqueID] = lastBarIndex = Math.ceil(count / itemsPerBar) - 1; - } - if (reflowItemRecords[i][horizontal ? "column" : "row"] === lastBarIndex) { - itemContainersToExpand[itemsContainer.uniqueID] = itemsContainer; - } - - var reflowDuration = 80; - if (slowAnimations) { - reflowDuration *= 10; - } - - pendingTransitionPromises.push(WinJS.UI.executeTransition(container, - { - property: "transform", - delay: moveDelay, - duration: reflowDuration, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "translate(" + xOffset + "px," + yOffset + "px)" - })); - } - - var itemContainerKeys = Object.keys(itemContainersToExpand); - for (var i = 0, len = itemContainerKeys.length; i < len; i++) { - var itemContainer = itemContainersToExpand[itemContainerKeys[i]]; - if (site.rtl && horizontal) { - itemContainer.style.paddingLeft = (-1 * minOffset) + 'px'; - itemContainer.style.marginLeft = minOffset + 'px'; - } else { - itemContainer.style[horizontal ? "paddingRight" : "paddingBottom"] = maxOffset + 'px'; - itemContainer.style[horizontal ? "marginRight" : "marginBottom"] = '-' + maxOffset + 'px'; - } - } - var itemsBlockKeys = Object.keys(animatingItemsBlocks); - for (var i = 0, len = itemsBlockKeys.length; i < len; i++) { - animatingItemsBlocks[itemsBlockKeys[i]].classList.add(WinJS.UI._clipClass); - } - - waitForNextPhase(afterReflowPhase); - - site._writeProfilerMark("Animation:setupReflowAnimation,StopTM"); - } - - function cleanupItemsContainers() { - // Reset the styles used to obtain overflow-y: hidden overflow-x: visible. - var itemContainerKeys = Object.keys(itemContainersToExpand); - for (var i = 0, len = itemContainerKeys.length; i < len; i++) { - var itemContainer = itemContainersToExpand[itemContainerKeys[i]]; - if (site.rtl && horizontal) { - itemContainer.style.paddingLeft = ''; - itemContainer.style.marginLeft = ''; - } else { - itemContainer.style[horizontal ? "paddingRight" : "paddingBottom"] = ''; - itemContainer.style[horizontal ? "marginRight" : "marginBottom"] = ''; - } - } - itemContainersToExpand = {}; - - var itemsBlockKeys = Object.keys(animatingItemsBlocks); - for (var i = 0, len = itemsBlockKeys.length; i < len; i++) { - var itemsBlock = animatingItemsBlocks[itemsBlockKeys[i]]; - itemsBlock.style.overflow = ''; - itemsBlock.classList.remove(WinJS.UI._clipClass); - } - } - - function afterReflowPhase() { - site._writeProfilerMark("Animation:prepareReflowedItems,StartTM"); - - // Position the items at the edge ready to slide in. - for (var i = 0, len = reflowItemRecords.length; i < len; i++) { - var reflowItemRecord = reflowItemRecords[i]; - var xOffset = 0, - yOffset = 0; - if (reflowItemRecord[oldReflowLayoutProperty] > reflowItemRecord[reflowLayoutProperty]) { - if (horizontal) { - yOffset = upInDist; - } else { - xOffset = upInDist; - } - } else if (reflowItemRecord[oldReflowLayoutProperty] < reflowItemRecord[reflowLayoutProperty]) { - if (horizontal) { - yOffset = -1 * downInDist; - } else { - xOffset = -1 * downInDist; - } - } - reflowItemRecord.element.style.transition = ""; - reflowItemRecord.element.style.transform = "translate(" + xOffset + "px," + yOffset + "px)"; - } - - site._writeProfilerMark("Animation:prepareReflowedItems,StopTM"); - - if (WinJS.UI.Layout._debugAnimations) { - requestAnimationFrame(function () { - directMovePhase(true); - }); - } else { - directMovePhase(true); - } - } - - function directMovePhase(fastMode) { - // For groups and items which move we transition them from transform: translate(Xpx,Ypx) to translate(0px,0px). - var duration = 200; - if (fastMode) { - duration = 150; - moveDelay = 0; - addDelay = 0; - } - - if (slowAnimations) { - duration *= 10; - } - - if (itemMoveRecords.length > 0 || moveRecords.length > 0) { - site._writeProfilerMark("Animation:setupMoveAnimation,StartTM"); - - var moveElements = []; - for (var i = 0, len = moveRecords.length; i < len; i++) { - var container = moveRecords[i].element; - moveElements.push(container); - } - for (var i = 0, len = itemMoveRecords.length; i < len; i++) { - var container = itemMoveRecords[i].element; - moveElements.push(container); - } - pendingTransitionPromises.push(WinJS.UI.executeTransition(moveElements, - { - property: "transform", - delay: moveDelay, - duration: duration, - timing: "cubic-bezier(0.1, 0.9, 0.2, 1)", - to: "" - })); - - addDelay += 80; - - site._writeProfilerMark("Animation:setupMoveAnimation,StopTM"); - } - - addPhase(); - } - - function addPhase() { - if (insertedElements.length > 0) { - site._writeProfilerMark("Animation:setupInsertAnimation,StartTM"); - - var addDuration = 120; - if (slowAnimations) { - addDuration *= 10; - } - - pendingTransitionPromises.push(WinJS.UI.executeTransition(insertedElements, - [{ - property: "opacity", - delay: addDelay, - duration: addDuration, - timing: "linear", - to: 1 - }])); - - site._writeProfilerMark("Animation:setupInsertAnimation,StopTM"); - } - - waitForNextPhase(completePhase); - } - function completePhase() { - site._writeProfilerMark("Animation:cleanupAnimations,StartTM"); - - cleanupItemsContainers(); - - for (var i = 0, len = removedElements.length; i < len; i++) { - var container = removedElements[i]; - if (container.parentNode) { - WinJS.Utilities._disposeElement(container); - container.parentNode.removeChild(container); - } - } - - site._writeProfilerMark("Animation:cleanupAnimations,StopTM"); - - that._animationsRunning = null; - animationSignal.complete(); - } - this._resetAnimationCaches(true); - - // The PVL animation library completes sucessfully even if you cancel an animation. - // If the animation promise passed to layout is canceled we should cancel the PVL animations and - // set a marker for them to be ignored. - animationSignal.promise.then(null, function () { - // Since it was canceled make sure we still clean up the styles. - cleanupItemsContainers(); - for (var i = 0, len = moveRecords.length; i < len; i++) { - var container = moveRecords[i].element; - container.style.transform = ''; - container.style.opacity = 1; - } - for (var i = 0, len = itemMoveRecords.length; i < len; i++) { - var container = itemMoveRecords[i].element; - container.style.transform = ''; - container.style.opacity = 1; - } - for (var i = 0, len = insertedElements.length; i < len; i++) { - insertedElements[i].style.opacity = 1; - } - for (var i = 0, len = removedElements.length; i < len; i++) { - var container = removedElements[i]; - if (container.parentNode) { - WinJS.Utilities._disposeElement(container); - container.parentNode.removeChild(container); - } - } - - this._animationsRunning = null; - animationSignal = null; - currentAnimationPromise && currentAnimationPromise.cancel(); - - }.bind(this)); - - return animationSignal.promise; - }, - - dragOver: function _LayoutCommon_dragOver(x, y, dragInfo) { - // The coordinates passed to dragOver should be in ListView's viewport space. 0,0 should be the top left corner of the viewport's padding. - var indicesAffected = this.hitTest(x, y), - groupAffected = (this._groups ? this._site.groupIndexFromItemIndex(indicesAffected.index) : 0), - itemsContainer = this._site.tree[groupAffected].itemsContainer, - itemsCount = getItemsContainerLength(itemsContainer), - indexOffset = (this._groups ? this._groups[groupAffected].startIndex : 0), - visibleRange = this._getVisibleRange(); - - indicesAffected.index -= indexOffset; - indicesAffected.insertAfterIndex -= indexOffset; - visibleRange.firstIndex = Math.max(visibleRange.firstIndex - indexOffset - 1, 0); - visibleRange.lastIndex = Math.min(visibleRange.lastIndex - indexOffset + 1, itemsCount); - var indexAfter = Math.max(Math.min(itemsCount - 1, indicesAffected.insertAfterIndex), -1), - indexBefore = Math.min(indexAfter + 1, itemsCount); - - if (dragInfo) { - for (var i = indexAfter; i >= visibleRange.firstIndex; i--) { - if (!dragInfo._isIncluded(i + indexOffset)) { - indexAfter = i; - break; - } else if (i === visibleRange.firstIndex) { - indexAfter = -1; - } - } - - for (var i = indexBefore; i < visibleRange.lastIndex; i++) { - if (!dragInfo._isIncluded(i + indexOffset)) { - indexBefore = i; - break; - } else if (i === (visibleRange.lastIndex - 1)) { - indexBefore = itemsCount; - } - } - } - - var elementBefore = containerFromIndex(itemsContainer, indexBefore), - elementAfter = containerFromIndex(itemsContainer, indexAfter); - - if (this._animatedDragItems) { - for (var i = 0, len = this._animatedDragItems.length; i < len; i++) { - var item = this._animatedDragItems[i]; - if (item) { - item.style.transition = this._site.animationsDisabled ? "" : dragBetweenTransition; - item.style.transform = ""; - } - } - } - this._animatedDragItems = []; - var horizontal = this.orientation === "horizontal", - inListMode = this._inListMode || this._itemsPerBar === 1; - if (this._groups && this._groups[groupAffected] instanceof Groups.CellSpanningGroup) { - inListMode = this._groups[groupAffected]._slotsPerColumn === 1; - } - var horizontalTransform = 0, - verticalTransform = 0; - // In general, items should slide in the direction perpendicular to the layout's orientation. - // In a horizontal layout, items are laid out top to bottom, left to right. For any two neighboring items in this layout, we want to move the first item up and the second down - // to denote that any inserted item would go between those two. - // Similarily, vertical layout should have the first item move left and the second move right. - // List layout is a special case. A horizontal list layout can only lay things out left to right, so it should slide the two items left and right like a vertical grid. - // A vertical list can only lay things out top to bottom, so it should slide items up and down like a horizontal grid. - // In other words: Apply horizontal transformations if we're a vertical grid or horizontal list, otherwise use vertical transformations. - if ((!horizontal && !inListMode) || (horizontal && inListMode)) { - horizontalTransform = this._site.rtl ? -dragBetweenDistance : dragBetweenDistance; - } else { - verticalTransform = dragBetweenDistance; - } - if (elementBefore) { - elementBefore.style.transition = this._site.animationsDisabled ? "" : dragBetweenTransition; - elementBefore.style.transform = "translate(" + horizontalTransform + "px, " + verticalTransform + "px)"; - this._animatedDragItems.push(elementBefore); - } - if (elementAfter) { - elementAfter.style.transition = this._site.animationsDisabled ? "" : dragBetweenTransition; - elementAfter.style.transform = "translate(" + (-horizontalTransform) + "px, -" + verticalTransform + "px)"; - this._animatedDragItems.push(elementAfter); - } - }, - - dragLeave: function _LayoutCommon_dragLeave() { - if (this._animatedDragItems) { - for (var i = 0, len = this._animatedDragItems.length; i < len; i++) { - this._animatedDragItems[i].style.transition = this._site.animationsDisabled ? "" : dragBetweenTransition; - this._animatedDragItems[i].style.transform = ""; - } - } - this._animatedDragItems = []; - }, - - // Private methods - - _setMaxRowsOrColumns: function _LayoutCommon_setMaxRowsOrColumns(value) { - if (value === this._maxRowsOrColumns || this._inListMode) { - return; - } - - // If container size is unavailable then we do not need to compute itemsPerBar - // as it will be computed along with the container size. - if (this._sizes && this._sizes.containerSizeLoaded) { - this._itemsPerBar = Math.floor(this._sizes.maxItemsContainerContentSize / this._sizes.containerCrossSize); - if (value) { - this._itemsPerBar = Math.min(this._itemsPerBar, value); - } - this._itemsPerBar = Math.max(1, this._itemsPerBar); - } - this._maxRowsOrColumns = value; - - this._invalidateLayout(); - }, - - _getItemPosition: function _LayoutCommon_getItemPosition(itemIndex) { - if (this._groupsEnabled) { - var groupIndex = Math.min(this._groups.length - 1, this._site.groupIndexFromItemIndex(itemIndex)), - group = this._groups[groupIndex], - itemOfGroupIndex = itemIndex - group.startIndex; - return this._getItemPositionForAnimations(itemIndex, groupIndex, itemOfGroupIndex); - } else { - return this._getItemPositionForAnimations(itemIndex, 0, itemIndex); - } - }, - - _getRealizationRange: function _LayoutCommon_getRealizationRange() { - var realizedRange = this._site.realizedRange; - return { - firstIndex: this._firstItemFromRange(realizedRange.firstPixel), - lastIndex: this._lastItemFromRange(realizedRange.lastPixel) - }; - }, - - _getVisibleRange: function _LayoutCommon_getVisibleRange() { - var visibleRange = this._site.visibleRange; - return { - firstIndex: this._firstItemFromRange(visibleRange.firstPixel), - lastIndex: this._lastItemFromRange(visibleRange.lastPixel) - }; - }, - - _resetAnimationCaches: function _LayoutCommon_resetAnimationCaches(skipReset) { - if (!skipReset) { - // Caches with move transforms: - this._resetStylesForRecords(this._cachedGroupRecords); - this._resetStylesForRecords(this._cachedItemRecords); - this._resetStylesForRecords(this._cachedHeaderRecords); - - // Caches with insert transforms: - this._resetStylesForInsertedRecords(this._cachedInsertedItemRecords); - this._resetStylesForInsertedRecords(this._cachedInsertedHeaderRecords); - - // Caches with insert transforms: - this._resetStylesForRemovedRecords(this._cachedRemovedItems); - this._resetStylesForRemovedRecords(this._cachedRemovedHeaders); - - var itemsBlockKeys = Object.keys(this._animatingItemsBlocks); - for (var i = 0, len = itemsBlockKeys.length; i < len; i++) { - var itemsBlock = this._animatingItemsBlocks[itemsBlockKeys[i]]; - itemsBlock.style.overflow = ''; - itemsBlock.classList.remove(WinJS.UI._clipClass); - } - } - - this._cachedGroupRecords = {}; - this._cachedItemRecords = {}; - this._cachedHeaderRecords = {}; - - this._cachedInsertedItemRecords = {}; - this._cachedInsertedHeaderRecords = {}; - - this._cachedRemovedItems = []; - this._cachedRemovedHeaders = []; - - this._animatingItemsBlocks = {}; - }, - - _cacheRemovedElements: function _LayoutCommon_cacheRemovedElements(modifiedElements, cachedRecords, cachedInsertedRecords, removedElements, areHeaders) { - var containerMargins = this._sizes.containerMargins; - var leftStr = "left"; - if (this._site.rtl) { - leftStr = "right"; - } - // Offset between the container's content box and its margin box - var outerX, outerY; - if (areHeaders) { - outerX = this._sizes.headerContainerOuterX; - outerY = this._sizes.headerContainerOuterY; - } else { - outerX = this._sizes.containerMargins[leftStr]; - outerY = this._sizes.containerMargins.top; - } - - // Cache the removed boxes and place them back in the DOM with position absolute - // so that they do not appear like they have moved. - for (var i = 0, len = modifiedElements.length; i < len; i++) { - var modifiedElementLookup = modifiedElements[i]; - if (modifiedElementLookup.newIndex === -1) { - var container = modifiedElementLookup.element; - var cachedItemRecord = cachedRecords[modifiedElementLookup.oldIndex]; - if (cachedItemRecord) { - cachedItemRecord.element = container; - // This item can no longer be a moved item. - delete cachedRecords[modifiedElementLookup.oldIndex]; - container.style.position = "absolute"; - container.style.transition = ""; - container.style.top = cachedItemRecord.oldTop - outerY + "px"; - container.style[leftStr] = cachedItemRecord.oldLeft - outerX + "px"; - container.style.width = cachedItemRecord.width + "px"; - container.style.height = cachedItemRecord.height + "px"; - container.style.transform = ""; - this._site.surface.appendChild(container); - removedElements.push(cachedItemRecord); - } - if (cachedInsertedRecords[modifiedElementLookup.oldIndex]) { - delete cachedInsertedRecords[modifiedElementLookup.oldIndex]; - } - } - } - }, - _cacheInsertedElements: function _LayoutCommon_cacheInsertedItems(modifiedElements, cachedInsertedRecords, cachedRecords) { - var newCachedInsertedRecords = {}; - - for (var i = 0, len = modifiedElements.length; i < len; i++) { - var modifiedElementLookup = modifiedElements[i]; - var wasInserted = cachedInsertedRecords[modifiedElementLookup.oldIndex]; - if (wasInserted) { - delete cachedInsertedRecords[modifiedElementLookup.oldIndex]; - } - - if (wasInserted || modifiedElementLookup.oldIndex === -1 || modifiedElementLookup.moved) { - var cachedRecord = cachedRecords[modifiedElementLookup.newIndex]; - if (cachedRecord) { - delete cachedRecords[modifiedElementLookup.newIndex]; - } - - var modifiedElement = modifiedElementLookup.element; - newCachedInsertedRecords[modifiedElementLookup.newIndex] = modifiedElement; - modifiedElement.style.transition = ""; - modifiedElement.style.transform = ""; - modifiedElement.style.opacity = 0; - } - } - - var keys = Object.keys(cachedInsertedRecords); - for (var i = 0, len = keys.length; i < len; i++) { - newCachedInsertedRecords[keys[i]] = cachedInsertedRecords[keys[i]]; - } - - return newCachedInsertedRecords; - }, - _resetStylesForRecords: function _LayoutCommon_resetStylesForRecords(recordsHash) { - var recordKeys = Object.keys(recordsHash); - for (var i = 0, len = recordKeys.length; i < len; i++) { - var record = recordsHash[recordKeys[i]]; - if (record.needsToResetTransform) { - record.element.style.transform = ""; - record.needsToResetTransform = false; - } - } - }, - _resetStylesForInsertedRecords: function _LayoutCommon_resetStylesForInsertedRecords(insertedRecords) { - var insertedRecordKeys = Object.keys(insertedRecords); - for (var i = 0, len = insertedRecordKeys.length; i < len; i++) { - var insertedElement = insertedRecords[insertedRecordKeys[i]] - insertedElement.style.opacity = 1; - } - }, - _resetStylesForRemovedRecords: function _LayoutCommon_resetStylesForRemovedRecords(removedElements) { - for (var i = 0, len = removedElements.length; i < len; i++) { - var container = removedElements[i].element; - if (container.parentNode) { - WinJS.Utilities._disposeElement(container); - container.parentNode.removeChild(container); - } - } - }, - _updateAnimationCache: function _LayoutCommon_updateAnimationCache(modifiedItems, modifiedGroups) { - // ItemBoxes can change containers so we have to start them back without transforms - // and then update them again. ItemsContainers don't need to do this. - this._resetStylesForRecords(this._cachedItemRecords); - this._resetStylesForRecords(this._cachedHeaderRecords); - // Go through all the inserted records and reset their insert transforms. - this._resetStylesForInsertedRecords(this._cachedInsertedItemRecords); - this._resetStylesForInsertedRecords(this._cachedInsertedHeaderRecords); - - var existingContainers = {}; - var realizationRange = this._getRealizationRange(); - var tree = this._site.tree; - for (var i = 0, itemIndex = 0, treeLength = tree.length; i < treeLength; i++) { - forEachContainer(tree[i].itemsContainer, function (container, j) { - if (realizationRange.firstIndex <= itemIndex && realizationRange.lastIndex >= itemIndex) { - existingContainers[container.uniqueID] = true; - } - itemIndex++; - }); - } - - // Update the indicies before the insert since insert needs the new containers. - function updateIndicies(modifiedElements, cachedRecords) { - var updatedCachedRecords = {}; - - for (var i = 0, len = modifiedElements.length; i < len; i++) { - var modifiedElementLookup = modifiedElements[i]; - var cachedRecord = cachedRecords[modifiedElementLookup.oldIndex]; - if (cachedRecord) { - updatedCachedRecords[modifiedElementLookup.newIndex] = cachedRecord; - cachedRecord.element = modifiedElementLookup.element; - delete cachedRecords[modifiedElementLookup.oldIndex]; - } - } - var cachedRecordKeys = Object.keys(cachedRecords); - for (var i = 0, len = cachedRecordKeys.length; i < len; i++) { - var key = cachedRecordKeys[i], - record = cachedRecords[key]; - // We need to filter out containers which were removed from the DOM. If container's item - // wasn't realized container can be removed without adding record to modifiedItems. - if (!record.element || existingContainers[record.element.uniqueID]) { - updatedCachedRecords[key] = record; - } - } - return updatedCachedRecords; - } - - this._cachedItemRecords = updateIndicies(modifiedItems, this._cachedItemRecords); - this._cachedHeaderRecords = updateIndicies(modifiedGroups, this._cachedHeaderRecords); - - this._cachedInsertedItemRecords = this._cacheInsertedElements(modifiedItems, this._cachedInsertedItemRecords, this._cachedItemRecords); - this._cachedInsertedHeaderRecords = this._cacheInsertedElements(modifiedGroups, this._cachedInsertedHeaderRecords, this._cachedHeaderRecords); - }, - _filterRemovedElements: function _LayoutCommon_filterRemovedElements() { - this._removedElements = []; - - if (this._site.animationsDisabled) { - this._resetStylesForRemovedRecords(this._cachedRemovedItems); - this._resetStylesForRemovedRecords(this._cachedRemovedHeaders); - return; - } - - var that = this; - var oldLeftStr = this.orientation === "horizontal" ? "oldLeft" : "oldTop"; - var widthStr = this.orientation === "horizontal" ? "width" : "height"; - - var visibleFirstPixel = this._site.scrollbarPos; - var visibleLastPixel = visibleFirstPixel + this._site.viewportSize[widthStr] - 1; - - function filterRemovedElements(removedRecordArray, removedElementsArray) { - for (var i = 0, len = removedRecordArray.length; i < len; i++) { - var removedItem = removedRecordArray[i]; - var container = removedItem.element; - if (removedItem[oldLeftStr] + removedItem[widthStr] - 1 < visibleFirstPixel || removedItem[oldLeftStr] > visibleLastPixel || !that._site.viewport.contains(container)) { - if (container.parentNode) { - WinJS.Utilities._disposeElement(container); - container.parentNode.removeChild(container); - } - } else { - removedElementsArray.push(container); - } - } - } - - filterRemovedElements(this._cachedRemovedItems, this._removedElements); - filterRemovedElements(this._cachedRemovedHeaders, this._removedElements); - }, - - _filterInsertedElements: function _LayoutCommon_filterInsertedElements() { - this._insertedElements = []; - if (this._site.animationsDisabled) { - this._resetStylesForInsertedRecords(this._cachedInsertedItemRecords); - this._resetStylesForInsertedRecords(this._cachedInsertedHeaderRecords); - return; - } - - var that = this; - var visibleRange = this._getVisibleRange(); - - function filterInsertedElements(cachedInsertedRecords, insertedElementsArray) { - var recordKeys = Object.keys(cachedInsertedRecords); - for (var i = 0, len = recordKeys.length; i < len; i++) { - var itemIndex = recordKeys[i]; - var insertedRecord = cachedInsertedRecords[itemIndex]; - if (itemIndex < visibleRange.firstIndex || itemIndex > visibleRange.lastIndex || that._site.viewport.contains(insertedRecord.element)) { - insertedRecord.style.opacity = 1; - } else { - insertedElementsArray.push(insertedRecord); - } - } - } - - filterInsertedElements(this._cachedInsertedItemRecords, this._insertedElements); - filterInsertedElements(this._cachedInsertedHeaderRecords, this._insertedElements); - }, - - _filterMovedElements: function _LayoutCommon_filterMovedElements() { - var that = this; - - // This filters all the items and groups down which could have moved to just the items on screen. - // The items which are not going to animate are immediately shown in their correct final location. - var oldLeftStr = this.orientation === "horizontal" ? "oldLeft" : "oldTop"; - var leftStr = this.orientation === "horizontal" ? "left" : "top"; - var widthStr = this.orientation === "horizontal" ? "width" : "height"; - - var realizationRange = this._getRealizationRange(); - var visibleFirstPixel = this._site.scrollbarPos; - var visibleLastPixel = visibleFirstPixel + this._site.viewportSize[widthStr] - 1; - - // ItemMove can reflow across column or fade in/out due to multisize. - this._itemMoveRecords = []; - this._moveRecords = []; - - if (!this._site.animationsDisabled) { - var tree = this._site.tree; - var itemIndex = 0; - for (var i = 0, treeLength = tree.length; i < treeLength; i++) { - var groupBundle = tree[i]; - var groupHasItemToAnimate = false; - - forEachContainer(groupBundle.itemsContainer, function (container) { - if (realizationRange.firstIndex <= itemIndex && realizationRange.lastIndex >= itemIndex) { - var cachedItemRecord = this._cachedItemRecords[itemIndex]; - if (cachedItemRecord) { - var shouldAnimate = ((cachedItemRecord[oldLeftStr] + cachedItemRecord[widthStr] - 1 >= visibleFirstPixel && cachedItemRecord[oldLeftStr] <= visibleLastPixel) || - (cachedItemRecord[leftStr] + cachedItemRecord[widthStr] - 1 >= visibleFirstPixel && cachedItemRecord[leftStr] <= visibleLastPixel)) && - that._site.viewport.contains(cachedItemRecord.element); - if (shouldAnimate) { - groupHasItemToAnimate = true; - if (cachedItemRecord.needsToResetTransform) { - this._itemMoveRecords.push(cachedItemRecord); - delete this._cachedItemRecords[itemIndex]; - } - } - } - } - itemIndex++; - }.bind(this)); - - var groupIndex = i; - var cachedHeaderRecord = this._cachedHeaderRecords[groupIndex]; - if (cachedHeaderRecord) { - if (groupHasItemToAnimate && cachedHeaderRecord.needsToResetTransform) { - this._moveRecords.push(cachedHeaderRecord); - delete this._cachedHeaderRecords[groupIndex]; - } - } - - var cachedGroupRecord = this._cachedGroupRecords[groupBundle.itemsContainer.element.uniqueID]; - if (cachedGroupRecord) { - if (groupHasItemToAnimate && cachedGroupRecord.needsToResetTransform) { - this._moveRecords.push(cachedGroupRecord); - delete this._cachedGroupRecords[groupBundle.itemsContainer.element.uniqueID]; - } - } - } - } - - // Reset transform for groups and items that were never on screen. - this._resetStylesForRecords(this._cachedGroupRecords); - this._resetStylesForRecords(this._cachedItemRecords); - this._resetStylesForRecords(this._cachedHeaderRecords); - }, - - _getItemPositionForAnimations: function _LayoutCommon_getItemPositionForAnimations(itemIndex, groupIndex, itemOfGroupIndex) { - // Top/Left are used to know if the item has moved and also used to position the item if removed. - // Row/Column are used to know if a reflow animation should occur - // Height/Width are used when positioning a removed item without impacting layout. - // The returned rectangle refers to the win-container's border/padding/content box. Coordinates - // are relative to the viewport. - var group = this._groups[groupIndex]; - var itemPosition = group.getItemPositionForAnimations(itemOfGroupIndex); - var groupOffset = (this._groups[groupIndex] ? this._groups[groupIndex].offset : 0); - var headerWidth = (this._groupsEnabled && this._groupHeaderPosition === WinJS.UI.HeaderPosition.left ? this._sizes.headerContainerWidth : 0); - var headerHeight = (this._groupsEnabled && this._groupHeaderPosition === WinJS.UI.HeaderPosition.top ? this._sizes.headerContainerHeight : 0); - - itemPosition.left += this._sizes.layoutOriginX + headerWidth + this._sizes.itemsContainerOuterX; - itemPosition.top += this._sizes.layoutOriginY + headerHeight + this._sizes.itemsContainerOuterY; - itemPosition[this._horizontal ? "left" : "top"] += groupOffset; - return itemPosition; - }, - - _getHeaderPositionForAnimations: function (groupIndex) { - // Top/Left are used to know if the item has moved. - // Height/Width are used when positioning a removed item without impacting layout. - // The returned rectangle refers to the header container's content box. Coordinates - // are relative to the viewport. - - var headerPosition; - - if (this._groupsEnabled) { - var width = this._sizes.headerContainerWidth - this._sizes.headerContainerOuterWidth, - height = this._sizes.headerContainerHeight - this._sizes.headerContainerOuterHeight; - if (this._groupHeaderPosition === WinJS.UI.HeaderPosition.left && !this._horizontal) { - height = this._groups[groupIndex].getItemsContainerSize() - this._sizes.headerContainerOuterHeight; - } else if (this._groupHeaderPosition === WinJS.UI.HeaderPosition.top && this._horizontal) { - width = this._groups[groupIndex].getItemsContainerSize() - this._sizes.headerContainerOuterWidth; - } - - var offsetX = this._horizontal ? this._groups[groupIndex].offset : 0, - offsetY = this._horizontal ? 0 : this._groups[groupIndex].offset; - headerPosition = { - top: this._sizes.layoutOriginY + offsetY + this._sizes.headerContainerOuterY, - left: this._sizes.layoutOriginX + offsetX + this._sizes.headerContainerOuterX, - height: height, - width: width - }; - } else { - headerPosition = { - top: 0, - left: 0, - height: 0, - width: 0 - }; - } - return headerPosition; - }, - - _rangeContainsItems: function _LayoutCommon_rangeContainsItems(firstPixel, lastPixel) { - if (this._groups.length === 0) { - return false; - } else { - var lastGroup = this._groups[this._groups.length - 1], - lastPixelOfLayout = this._sizes.layoutOrigin + lastGroup.offset + this._getGroupSize(lastGroup) - 1; - - return lastPixel >= 0 && firstPixel <= lastPixelOfLayout; - } - }, - - _itemFromOffset: function _LayoutCommon_itemFromOffset(offset, options) { - // supported options are: - // - wholeItem: when set to true the fully visible item is returned - // - last: if 1 the last item is returned. if 0 the first - var that = this; - if (this._groups.length === 0) { - return 0; - } - - function assignItemMargins(offset) { - if (!options.wholeItem) { - // This makes it such that if a container's margin is on screen but all of its - // content is off screen then we'll treat the container as being off screen. - var marginPropLast = (that._horizontal ? (that._site.rtl ? "right" : "left") : "top"), - marginPropFirst = (that._horizontal ? (that._site.rtl ? "left" : "right") : "bottom"); - if (options.last) { - // When looking for the *last* item, treat all container margins - // as belonging to the container *before* the margin. - return offset - that._sizes.containerMargins[marginPropLast]; - } else { - // When looking for the *first* item, treat all container margins - // as belonging to the container *after* the margin. - return offset + that._sizes.containerMargins[marginPropFirst]; - } - } - return offset; - } - - // Assign the headers and margins to the appropriate groups. - function assignGroupMarginsAndHeaders(offset) { - if (options.last) { - // When looking for the *last* group, the *trailing* header and margin belong to the group. - return offset - that._getHeaderSizeGroupAdjustment() - that._sizes.itemsContainerOuterStart; - } else { - // When looking for the *first* group, the *leading* header and margin belong to the group. - // No need to make any adjustments to offset because the correct header and margin - // already belong to the group. - return offset; - } - } - - options = options || {}; - - // Make offset relative to layout's content box - offset -= this._sizes.layoutOrigin; - - offset = assignItemMargins(offset); - - var groupIndex = this._groupFromOffset(assignGroupMarginsAndHeaders(offset)), - group = this._groups[groupIndex]; - - // Make offset relative to the margin box of the group's items container - offset -= group.offset; - offset -= this._getHeaderSizeGroupAdjustment(); - - return group.startIndex + group.itemFromOffset(offset, options); - }, - - _firstItemFromRange: function _LayoutCommon_firstItemFromRange(firstPixel, options) { - // supported options are: - // - wholeItem: when set to true the first fully visible item is returned - options = options || {}; - options.last = 0; - return this._itemFromOffset(firstPixel, options); - }, - - _lastItemFromRange: function _LayoutCommon_lastItemFromRange(lastPixel, options) { - // supported options are: - // - wholeItem: when set to true the last fully visible item is returned - options = options || {}; - options.last = 1; - return this._itemFromOffset(lastPixel, options); - }, - - _adjustedKeyForRTL: function _LayoutCommon_adjustedKeyForRTL(key) { - if (this._site.rtl) { - if (key === Key.leftArrow) { - key = Key.rightArrow; - } else if (key === Key.rightArrow) { - key = Key.leftArrow; - } - } - return key; - }, - - _adjustedKeyForOrientationAndBars: function _LayoutCommon_adjustedKeyForOrientationAndBars(key, cellSpanningGroup) { - var newKey = key; - - // Don't support cell spanning - if (cellSpanningGroup) { - return key; - } - // First, convert the key into a virtual form based off of horizontal layouts. - // In a horizontal layout, left/right keys switch between columns (AKA "bars"), and - // up/down keys switch between rows (AKA "slots"). - // In vertical mode, we want up/down to switch between rows (AKA "bars" when vertical), - // and left/right to switch between columns (AKA "slots" when vertical). - // The first step is to convert keypresses in vertical so that up/down always correspond to moving between slots, - // and left/right moving between bars. - if (!this._horizontal) { - switch (newKey) { - case Key.leftArrow: - newKey = Key.upArrow; - break; - case Key.rightArrow: - newKey = Key.downArrow; - break; - case Key.upArrow: - newKey = Key.leftArrow; - break; - case Key.downArrow: - newKey = Key.rightArrow; - break; - } - } - - // Next, if we only have one item per bar, we'll make the change-slots-key the same as the change-bars-key - if (this._itemsPerBar === 1) { - if (newKey === Key.upArrow) { - newKey = Key.leftArrow; - } else if (newKey === Key.downArrow) { - newKey = Key.rightArrow; - } - } - - return newKey; - }, - - _getAdjacentForPageKeys: function _LayoutCommon_getAdjacentForPageKeys(currentItem, pressedKey) { - var containerMargins = this._sizes.containerMargins, - marginSum = (this.orientation === "horizontal" ? - containerMargins.left + containerMargins.right : - containerMargins.top + containerMargins.bottom); - - var viewportLength = this._site.viewportSize[this.orientation === "horizontal" ? "width" : "height"], - firstPixel = this._site.scrollbarPos, - lastPixel = firstPixel + viewportLength - 1 - containerMargins[(this.orientation === "horizontal" ? "right" : "bottom")], - newFocus; - - // Handles page up by attempting to choose the first fully visible item - // on the current page. If that item already has focus, chooses the - // first item on the previous page. Page down is handled similarly. - - var firstIndex = this._firstItemFromRange(firstPixel, { wholeItem: true }), - lastIndex = this._lastItemFromRange(lastPixel, { wholeItem: false }), - currentItemPosition = this._getItemPosition(currentItem.index); - - - var offscreen = false; - if (currentItem.index < firstIndex || currentItem.index > lastIndex) { - offscreen = true; - if (this.orientation === "horizontal") { - firstPixel = currentItemPosition.left - marginSum; - } else { - firstPixel = currentItemPosition.top - marginSum; - } - lastPixel = firstPixel + viewportLength - 1; - firstIndex = this._firstItemFromRange(firstPixel, { wholeItem: true }); - lastIndex = this._lastItemFromRange(lastPixel, { wholeItem: false }); - } - - if (pressedKey === Key.pageUp) { - if (!offscreen && firstIndex !== currentItem.index) { - return { type: WinJS.UI.ObjectType.item, index: firstIndex }; - } - var end; - if (this.orientation === "horizontal") { - end = currentItemPosition.left + currentItemPosition.width + marginSum + containerMargins.left; - } else { - end = currentItemPosition.top + currentItemPosition.height + marginSum + containerMargins.bottom; - } - var firstIndexOnPrevPage = this._firstItemFromRange(end - viewportLength, { wholeItem: true }); - if (currentItem.index === firstIndexOnPrevPage) { - // The current item is so big that it spanned from the previous page, so we want to at least - // move to the previous item. - newFocus = Math.max(0, currentItem.index - this._itemsPerBar); - } else { - newFocus = firstIndexOnPrevPage; - } - } else { - if (!offscreen && lastIndex !== currentItem.index) { - return { type: WinJS.UI.ObjectType.item, index: lastIndex }; - } - // We need to subtract twice the marginSum from the item's starting position because we need to - // consider that ensureVisible will scroll the viewport to include the new items margin as well - // which may push the current item just off screen. - var start; - if (this.orientation === "horizontal") { - start = currentItemPosition.left - marginSum - containerMargins.right; - } else { - start = currentItemPosition.top - marginSum - containerMargins.bottom; - } - var lastIndexOnNextPage = Math.max(0, this._lastItemFromRange(start + viewportLength - 1, { wholeItem: true })); - if (currentItem.index === lastIndexOnNextPage) { - // The current item is so big that it spans across the next page, so we want to at least - // move to the next item. It is also ok to blindly increment this index w/o bound checking - // since the browse mode clamps the bounds for page keys. This way we do not have to - // asynchronoulsy request the count here. - newFocus = currentItem.index + this._itemsPerBar; - } else { - newFocus = lastIndexOnNextPage; - } - } - - return { type: WinJS.UI.ObjectType.item, index: newFocus }; - }, - - _isCellSpanning: function _LayoutCommon_isCellSpanning(groupIndex) { - var group = this._site.groupFromIndex(groupIndex), - groupInfo = this._groupInfo; - - if (groupInfo) { - return !!(typeof groupInfo === "function" ? groupInfo(group) : groupInfo).enableCellSpanning; - } else { - return false; - } - }, - - // Can only be called after measuring has been completed - _getGroupInfo: function _LayoutCommon_getGroupInfo(groupIndex) { - var group = this._site.groupFromIndex(groupIndex), - groupInfo = this._groupInfo, - margins = this._sizes.containerMargins, - adjustedInfo = { enableCellSpanning: false }; - - groupInfo = (typeof groupInfo === "function" ? groupInfo(group) : groupInfo); - if (groupInfo) { - if (groupInfo.enableCellSpanning && (+groupInfo.cellWidth !== groupInfo.cellWidth || +groupInfo.cellHeight !== groupInfo.cellHeight)) { - throw new WinJS.ErrorFromName("WinJS.UI.GridLayout.GroupInfoResultIsInvalid", strings.groupInfoResultIsInvalid); - } - adjustedInfo = { - enableCellSpanning: !!groupInfo.enableCellSpanning, - cellWidth: groupInfo.cellWidth + margins.left + margins.right, - cellHeight: groupInfo.cellHeight + margins.top + margins.bottom - }; - } - - return adjustedInfo; - }, - - // itemIndex is optional - _getItemInfo: function _LayoutCommon_getItemInfo(itemIndex) { - var result; - if (!this._itemInfo || typeof this._itemInfo !== "function") { - if (this._useDefaultItemInfo) { - result = this._defaultItemInfo(itemIndex); - } else { - throw new WinJS.ErrorFromName("WinJS.UI.GridLayout.ItemInfoIsInvalid", strings.itemInfoIsInvalid); - } - } else { - result = this._itemInfo(itemIndex); - } - return WinJS.Promise.as(result).then(function (size) { - if (!size || +size.width !== size.width || +size.height !== size.height) { - throw new WinJS.ErrorFromName("WinJS.UI.GridLayout.ItemInfoIsInvalid", strings.itemInfoIsInvalid); - } - return size; - }); - }, - - _defaultItemInfo: function _LayoutCommon_defaultItemInfo(itemIndex) { - var that = this; - return this._site.renderItem(this._site.itemFromIndex(itemIndex)).then(function (element) { - that._elementsToMeasure[itemIndex] = { - element: element - }; - return that._measureElements(); - }).then( - function () { - var entry = that._elementsToMeasure[itemIndex], - size = { - width: entry.width, - height: entry.height - }; - - delete that._elementsToMeasure[itemIndex]; - return size; - }, - function (error) { - delete that._elementsToMeasure[itemIndex]; - return WinJS.Promise.wrapError(error); - } - ); - }, - - _getGroupSize: function _LayoutCommon_getGroupSize(group) { - var headerContainerMinSize = 0; - - if (this._groupsEnabled) { - if (this._horizontal && this._groupHeaderPosition === WinJS.UI.HeaderPosition.top) { - headerContainerMinSize = this._sizes.headerContainerMinWidth; - } else if (!this._horizontal && this._groupHeaderPosition === WinJS.UI.HeaderPosition.left) { - headerContainerMinSize = this._sizes.headerContainerMinHeight; - } - } - return Math.max(headerContainerMinSize, group.getItemsContainerSize() + this._getHeaderSizeGroupAdjustment()); - }, - - // offset should be relative to the grid layout's content box - _groupFromOffset: function _LayoutCommon_groupFromOffset(offset) { - return offset < this._groups[0].offset ? - 0 : - this._groupFrom(function (group, groupIndex) { - //#DBG _ASSERT(group.offset !== undefined); - return offset < group.offset; - }); - }, - - _groupFromImpl: function _LayoutCommon_groupFromImpl(fromGroup, toGroup, comp) { - if (toGroup < fromGroup) { - return null; - } - - var center = fromGroup + Math.floor((toGroup - fromGroup) / 2), - centerGroup = this._groups[center]; - - if (comp(centerGroup, center)) { - return this._groupFromImpl(fromGroup, center - 1, comp); - } else if (center < toGroup && !comp(this._groups[center + 1], center + 1)) { - return this._groupFromImpl(center + 1, toGroup, comp); - } else { - return center; - } - }, - - _groupFrom: function _LayoutCommon_groupFrom(comp) { - //#DBG _ASSERT(this.assertValid()); - if (this._groups.length > 0) { - var lastGroupIndex = this._groups.length - 1, - lastGroup = this._groups[lastGroupIndex]; - - if (!comp(lastGroup, lastGroupIndex)) { - return lastGroupIndex; - } else { - return this._groupFromImpl(0, this._groups.length - 1, comp); - } - } else { - return null; - } - }, - - _invalidateLayout: function _LayoutCommon_invalidateLayout() { - if (this._site) { - this._site.invalidateLayout(); - } - }, - - _resetMeasurements: function _LayoutCommon_resetMeasurements() { - if (this._measuringPromise) { - this._measuringPromise.cancel(); - this._measuringPromise = null; - } - if (this._containerSizeClassName) { - Utilities.removeClass(this._site.surface, this._containerSizeClassName); - deleteDynamicCssRule(this._containerSizeClassName); - this._containerSizeClassName = null; - } - this._sizes = null; - this._resetAnimationCaches(); - }, - - _measureElements: function _LayoutCommon_measureElements() { - // batching measurements to minimalize number of layout passes - if (!this._measuringElements) { - var that = this; - // Schedule a job so that: - // 1. Calls to _measureElements are batched. - // 2. that._measuringElements is set before the promise handler is executed - // (that._measuringElements is used within the handler). - that._measuringElements = Scheduler.schedulePromiseHigh(null, "WinJS.UI.GridLayout._measuringElements").then( - function measure() { - that._site._writeProfilerMark("_measureElements,StartTM"); - - var surface = that._createMeasuringSurface(), - itemsContainer = document.createElement("div"), - site = that._site, - measuringElements = that._measuringElements, - elementsToMeasure = that._elementsToMeasure, - stopMeasuring = false; - - itemsContainer.className = WinJS.UI._itemsContainerClass + " " + WinJS.UI._laidOutClass; - // This code is executed by CellSpanningGroups where styling is configured for –ms-grid. Let's satisfy these assumptions - itemsContainer.style.cssText += - ";display: -ms-grid" + - ";-ms-grid-column: 1" + - ";-ms-grid-row: 1"; - - var keys = Object.keys(elementsToMeasure), - len, - i; - - for (i = 0, len = keys.length; i < len; i++) { - var element = elementsToMeasure[keys[i]].element; - element.style["-ms-grid-column"] = i + 1; - element.style["-ms-grid-row"] = i + 1; - itemsContainer.appendChild(element); - } - - surface.appendChild(itemsContainer); - site.viewport.insertBefore(surface, site.viewport.firstChild); - - // Reading from the DOM may cause the app's resize handler to - // be run synchronously which may invalidate this measuring - // operation. When this happens, stop measuring. - measuringElements.then(null, function () { - stopMeasuring = true; - }); - - for (i = 0, len = keys.length; i < len && !stopMeasuring; i++) { - var entry = elementsToMeasure[keys[i]], - item = entry.element.querySelector("." + WinJS.UI._itemClass); - - entry.width = Utilities.getTotalWidth(item); - entry.height = Utilities.getTotalHeight(item); - - } - - if (surface.parentNode) { - surface.parentNode.removeChild(surface); - } - if (measuringElements === that._measuringElements) { - that._measuringElements = null; - } - - site._writeProfilerMark("_measureElements,StopTM"); - }, - function (error) { - that._measuringElements = null; - return WinJS.Promise.wrapError(error); - } - ); - } - return this._measuringElements; - }, - - _createMeasuringSurface: function _LayoutCommon_createMeasuringSurface() { - var surface = document.createElement("div"); - - surface.style.cssText = - "visibility: hidden" + - ";-ms-grid-columns: auto" + - ";-ms-grid-rows: auto"; - surface.className = WinJS.UI._scrollableClass + " " + (this._inListMode ? WinJS.UI._listLayoutClass : WinJS.UI._gridLayoutClass); - if (this._groupsEnabled) { - if (this._groupHeaderPosition === WinJS.UI.HeaderPosition.top) { - Utilities.addClass(surface, WinJS.UI._headerPositionTopClass); - } else { - //#DBG _ASSERT(this._groupHeaderPosition === WinJS.UI.HeaderPosition.left); - Utilities.addClass(surface, WinJS.UI._headerPositionLeftClass); - } - } - - return surface; - }, - - // Assumes that the size of the item at the specified index is representative - // of the size of all items, measures it, and stores the measurements in - // this._sizes. If necessary, also: - // - Creates a CSS rule to give the containers a height and width - // - Stores the name associated with the rule in this._containerSizeClassName - // - Adds the class name associated with the rule to the surface - _measureItem: function _LayoutCommon_measureItem(index) { - var that = this; - var perfId = "Layout:measureItem"; - var site = that._site; - var measuringPromise = that._measuringPromise; - - // itemPromise is optional. It is provided when taking a second attempt at measuring. - function measureItemImpl(index, itemPromise) { - var secondTry = !!itemPromise, - elementPromises = {}, - itemPromise, - left = site.rtl ? "right" : "left", - right = site.rtl ? "left" : "right"; - - return site.itemCount.then(function (count) { - if (!count || (that._groupsEnabled && !site.groupCount)) { - return WinJS.Promise.cancel; - } - - itemPromise = itemPromise || site.itemFromIndex(index); - elementPromises.container = site.renderItem(itemPromise); - if (that._groupsEnabled) { - elementPromises.headerContainer = site.renderHeader(that._site.groupFromIndex(site.groupIndexFromItemIndex(index))); - } - - return WinJS.Promise.join(elementPromises); - }).then(function (elements) { - - // Reading from the DOM is tricky because each read may trigger a resize handler which - // may invalidate this layout object. To make it easier to minimize bugs in this edge case: - // 1. All DOM reads for _LayoutCommon_measureItem should be contained within this function. - // 2. This function should remain as simple as possible. Stick to DOM reads, avoid putting - // logic in here, and cache all needed instance variables at the top of the function. - // - // Returns null if the measuring operation was invalidated while reading from the DOM. - // Otherwise, returns an object containing the measurements. - function readMeasurementsFromDOM() { - var horizontal = that._horizontal; - var groupsEnabled = that._groupsEnabled; - var stopMeasuring = false; - - // Reading from the DOM may cause the app's resize handler to - // be run synchronously which may invalidate this measuring - // operation. When this happens, stop measuring. - measuringPromise.then(null, function () { - stopMeasuring = true; - }); - - var firstElementOnSurfaceMargins = WinJS.UI._getMargins(firstElementOnSurface); - var firstElementOnSurfaceOffsetX = site.rtl ? - (site.viewport.offsetWidth - (firstElementOnSurface.offsetLeft + firstElementOnSurface.offsetWidth)) : - firstElementOnSurface.offsetLeft; - var firstElementOnSurfaceOffsetY = firstElementOnSurface.offsetTop; - - var sizes = { - // These will be set by _viewportSizeChanged - viewportContentSize: 0, - surfaceContentSize: 0, - maxItemsContainerContentSize: 0, - - surfaceOuterHeight: getOuterHeight(surface), - surfaceOuterWidth: getOuterWidth(surface), - - // Origin of the grid layout's content in viewport coordinates - layoutOriginX: firstElementOnSurfaceOffsetX - firstElementOnSurfaceMargins[left], - layoutOriginY: firstElementOnSurfaceOffsetY - firstElementOnSurfaceMargins.top, - itemsContainerOuterHeight: getOuterHeight(itemsContainer), - itemsContainerOuterWidth: getOuterWidth(itemsContainer), - // Amount of space between the items container's margin and its content - itemsContainerOuterX: getOuter(site.rtl ? "Right" : "Left", itemsContainer), - itemsContainerOuterY: getOuter("Top", itemsContainer), - - itemBoxOuterHeight: getOuterHeight(itemBox), - itemBoxOuterWidth: getOuterWidth(itemBox), - containerOuterHeight: getOuterHeight(elements.container), - containerOuterWidth: getOuterWidth(elements.container), - emptyContainerContentHeight: Utilities.getContentHeight(emptyContainer), - emptyContainerContentWidth: Utilities.getContentWidth(emptyContainer), - - containerMargins: WinJS.UI._getMargins(elements.container), - // containerWidth/Height are computed when a uniform group is detected - containerWidth: 0, - containerHeight: 0, - // true when both containerWidth and containerHeight have been measured - containerSizeLoaded: false - }; - - if (groupsEnabled) { - // Amount of space between the header container's margin and its content - sizes.headerContainerOuterX = getOuter(site.rtl ? "Right" : "Left", elements.headerContainer), - sizes.headerContainerOuterY = getOuter("Top", elements.headerContainer), - - sizes.headerContainerOuterWidth = getOuterWidth(elements.headerContainer); - sizes.headerContainerOuterHeight = getOuterHeight(elements.headerContainer); - sizes.headerContainerWidth = Utilities.getTotalWidth(elements.headerContainer); - sizes.headerContainerHeight = Utilities.getTotalHeight(elements.headerContainer); - sizes.headerContainerMinWidth = getDimension(elements.headerContainer, "minWidth") + sizes.headerContainerOuterWidth; - sizes.headerContainerMinHeight = getDimension(elements.headerContainer, "minHeight") + sizes.headerContainerOuterHeight; - } - - var measurements = { - // Measurements which are needed after measureItem has returned. - sizes: sizes, - - // Measurements which are only needed within measureItem. - viewportContentWidth: Utilities.getContentWidth(site.viewport), - viewportContentHeight: Utilities.getContentHeight(site.viewport), - containerContentWidth: Utilities.getContentWidth(elements.container), - containerContentHeight: Utilities.getContentHeight(elements.container), - containerWidth: Utilities.getTotalWidth(elements.container), - containerHeight: Utilities.getTotalHeight(elements.container) - }; - measurements.viewportCrossSize = measurements[horizontal ? "viewportContentHeight" : "viewportContentWidth"]; - - site.readyToMeasure(); - - return stopMeasuring ? null : measurements; - } - - function cleanUp() { - if (surface.parentNode) { - surface.parentNode.removeChild(surface); - } - } - - var surface = that._createMeasuringSurface(), - itemsContainer = document.createElement("div"), - emptyContainer = document.createElement("div"), - itemBox = elements.container.querySelector("." + WinJS.UI._itemBoxClass), - groupIndex = site.groupIndexFromItemIndex(index); - - emptyContainer.className = WinJS.UI._containerClass; - itemsContainer.className = WinJS.UI._itemsContainerClass + " " + WinJS.UI._laidOutClass; - // Use display=inline-block so that the width sizes to content when not in list mode. - // When in grid mode, put items container and header container in different rows and columns so that the size of the items container does not affect the size of the header container and vice versa. - // Use the same for list mode when headers are inline with item containers. - // When headers are to the left of a vertical list, or above a horizontal list, put the rows/columns they would be in when laid out normally - // into the CSS text for measuring. We have to do this because list item containers should take up 100% of the space left over in the surface - // once the group's header is laid out. - var itemsContainerRow = 1, - itemsContainerColumn = 1, - headerContainerRow = 2, - headerContainerColumn = 2, - firstElementOnSurface = itemsContainer; - if (that._inListMode && that._groupsEnabled) { - if (that._horizontal && that._groupHeaderPosition === WinJS.UI.HeaderPosition.top) { - itemsContainerRow = 2; - headerContainerColumn = 1; - headerContainerRow = 1; - firstElementOnSurface = elements.headerContainer; - } else if (!that._horizontal && that._groupHeaderPosition === WinJS.UI.HeaderPosition.left) { - itemsContainerColumn = 2; - headerContainerColumn = 1; - headerContainerRow = 1; - firstElementOnSurface = elements.headerContainer; - } - } - // ListMode needs to use display block to proprerly measure items in vertical mode, and display flex to properly measure items in horizontal mode - itemsContainer.style.cssText += - ";display: " + (that._inListMode ? ((that._horizontal ? "flex" : "block") + "; overflow: hidden") : "inline-block") + - ";-ms-grid-column: " + itemsContainerColumn + - ";-ms-grid-row: " + itemsContainerRow; - if (!that._inListMode) { - elements.container.style.display = "inline-block"; - } - if (that._groupsEnabled) { - elements.headerContainer.style.cssText += - ";display: inline-block" + - ";-ms-grid-column: " + headerContainerColumn + - ";-ms-grid-row: " + headerContainerRow; - WinJS.Utilities.addClass(elements.headerContainer, WinJS.UI._laidOutClass + " " + WinJS.UI._groupLeaderClass); - if ((that._groupHeaderPosition === WinJS.UI.HeaderPosition.top && that._horizontal) || - (that._groupHeaderPosition === WinJS.UI.HeaderPosition.left && !that._horizontal)) { - WinJS.Utilities.addClass(itemsContainer, WinJS.UI._groupLeaderClass); - } - } - - itemsContainer.appendChild(elements.container); - itemsContainer.appendChild(emptyContainer); - - surface.appendChild(itemsContainer); - if (that._groupsEnabled) { - surface.appendChild(elements.headerContainer); - } - site.viewport.insertBefore(surface, site.viewport.firstChild); - - var measurements = readMeasurementsFromDOM(); - - if (!measurements) { - // While reading from the DOM, the measuring operation was invalidated. Bail out. - cleanUp(); - return WinJS.Promise.cancel; - } else if ((that._horizontal && measurements.viewportContentHeight === 0) || (!that._horizontal && measurements.viewportContentWidth === 0)) { - // ListView is invisible so we can't measure. Return a canceled promise. - cleanUp(); - return WinJS.Promise.cancel; - } else if (!secondTry && !that._isCellSpanning(groupIndex) && - (measurements.containerContentWidth === 0 || measurements.containerContentHeight === 0)) { - // win-container has no size. For backwards compatibility, wait for the item promise and then try measuring again. - cleanUp(); - return itemPromise.then(function () { - return measureItemImpl(index, itemPromise); - }); - } else { - var sizes = that._sizes = measurements.sizes; - - // Wrappers for orientation-specific properties. - // Sizes prefaced with "cross" refer to the sizes orthogonal to the current layout orientation. Sizes without a preface are in the orientation's direction. - Object.defineProperties(sizes, { - surfaceOuterCrossSize: { - get: function () { - return (that._horizontal ? sizes.surfaceOuterHeight : sizes.surfaceOuterWidth); - }, - enumerable: true - }, - layoutOrigin: { - get: function () { - return (that._horizontal ? sizes.layoutOriginX : sizes.layoutOriginY); - }, - enumerable: true - }, - itemsContainerOuterSize: { - get: function () { - return (that._horizontal ? sizes.itemsContainerOuterWidth : sizes.itemsContainerOuterHeight); - }, - enumerable: true - }, - itemsContainerOuterCrossSize: { - get: function () { - return (that._horizontal ? sizes.itemsContainerOuterHeight : sizes.itemsContainerOuterWidth); - }, - enumerable: true - }, - itemsContainerOuterStart: { - get: function () { - return (that._horizontal ? sizes.itemsContainerOuterX : sizes.itemsContainerOuterY); - }, - enumerable: true - }, - itemsContainerOuterCrossStart: { - get: function () { - return (that._horizontal ? sizes.itemsContainerOuterY : sizes.itemsContainerOuterX); - }, - enumerable: true - }, - containerCrossSize: { - get: function () { - return (that._horizontal ? sizes.containerHeight : sizes.containerWidth); - }, - enumerable: true - }, - containerSize: { - get: function () { - return (that._horizontal ? sizes.containerWidth : sizes.containerHeight); - }, - enumerable: true - }, - }); - - // If the measured group is uniform, measure the container height - // and width now. Otherwise, compute them thru itemInfo on demand (via _ensureContainerSize). - if (!that._isCellSpanning(groupIndex)) { - if (that._inListMode) { - var itemsContainerContentSize = measurements.viewportCrossSize - sizes.surfaceOuterCrossSize - that._getHeaderSizeContentAdjustment() - sizes.itemsContainerOuterCrossSize; - if (that._horizontal) { - sizes.containerHeight = itemsContainerContentSize; - sizes.containerWidth = measurements.containerWidth; - } else { - sizes.containerHeight = measurements.containerHeight; - sizes.containerWidth = itemsContainerContentSize; - } - } else { - sizes.containerWidth = measurements.containerWidth; - sizes.containerHeight = measurements.containerHeight; - } - sizes.containerSizeLoaded = true; - } - - that._createContainerStyleRule(); - that._viewportSizeChanged(measurements.viewportCrossSize); - - cleanUp(); - } - }); - } - - if (!measuringPromise) { - site._writeProfilerMark(perfId + ",StartTM"); - // Use a signal to guarantee that measuringPromise is set before the promise - // handler is executed (measuringPromise is referenced within measureItemImpl). - var promiseStoredSignal = new WinJS._Signal(); - that._measuringPromise = measuringPromise = promiseStoredSignal.promise.then(function () { - return measureItemImpl(index); - }).then(function () { - site._writeProfilerMark(perfId + ":complete,info"); - site._writeProfilerMark(perfId + ",StopTM"); - }, function (error) { - // The purpose of the measuring promise is so that we only - // measure once. If measuring fails, clear the promise because - // we still need to measure. - that._measuringPromise = null; - - site._writeProfilerMark(perfId + ":canceled,info"); - site._writeProfilerMark(perfId + ",StopTM"); - - return WinJS.Promise.wrapError(error); - }); - promiseStoredSignal.complete(); - } - return measuringPromise; - }, - - _getHeaderSizeGroupAdjustment: function () { - if (this._groupsEnabled) { - if (this._horizontal && this._groupHeaderPosition === WinJS.UI.HeaderPosition.left) { - return this._sizes.headerContainerWidth; - } else if (!this._horizontal && this._groupHeaderPosition === WinJS.UI.HeaderPosition.top) { - return this._sizes.headerContainerHeight; - } - } - - return 0; - }, - _getHeaderSizeContentAdjustment: function () { - if (this._groupsEnabled) { - if (this._horizontal && this._groupHeaderPosition === WinJS.UI.HeaderPosition.top) { - return this._sizes.headerContainerHeight; - } else if (!this._horizontal && this._groupHeaderPosition === WinJS.UI.HeaderPosition.left) { - return this._sizes.headerContainerWidth; - } - } - - return 0; - }, - - // Horizontal layouts lay items out top to bottom, left to right, whereas vertical layouts lay items out left to right, top to bottom. - // The viewport size is the size layouts use to determine how many items can be placed in one bar, so it should be cross to the - // orientation. - _getViewportCrossSize: function () { - return this._site.viewportSize[this._horizontal ? "height" : "width"]; - }, - - // viewportContentSize is the new viewport size - _viewportSizeChanged: function _LayoutCommon_viewportSizeChanged(viewportContentSize) { - var sizes = this._sizes; - - sizes.viewportContentSize = viewportContentSize; - sizes.surfaceContentSize = viewportContentSize - sizes.surfaceOuterCrossSize; - sizes.maxItemsContainerContentSize = sizes.surfaceContentSize - sizes.itemsContainerOuterCrossSize - this._getHeaderSizeContentAdjustment(); - - // This calculation is for uniform layouts - if (sizes.containerSizeLoaded && !this._inListMode) { - this._itemsPerBar = Math.floor(sizes.maxItemsContainerContentSize / sizes.containerCrossSize); - if (this.maximumRowsOrColumns) { - this._itemsPerBar = Math.min(this._itemsPerBar, this.maximumRowsOrColumns); - } - this._itemsPerBar = Math.max(1, this._itemsPerBar); - } else { - if (this._inListMode) { - sizes[this._horizontal ? "containerHeight" : "containerWidth"] = sizes.maxItemsContainerContentSize; - } - this._itemsPerBar = 1; - } - - // Ignore animations if height changed - this._resetAnimationCaches(); - }, - - _createContainerStyleRule: function _LayoutCommon_createContainerStyleRule() { - // Adding CSS rules is expensive. Add a rule to provide a - // height and width for containers if the app hasn't provided one. - var sizes = this._sizes; - if (!this._containerSizeClassName && sizes.containerSizeLoaded && (sizes.emptyContainerContentHeight === 0 || sizes.emptyContainerContentWidth === 0)) { - var width = sizes.containerWidth - sizes.containerOuterWidth + "px", - height = sizes.containerHeight - sizes.containerOuterHeight + "px"; - if (this._inListMode) { - if (this._horizontal) { - height = "calc(100% - " + (sizes.containerMargins.top + sizes.containerMargins.bottom) + "px)"; - } else { - width = "auto"; - } - } - - if (!this._containerSizeClassName) { - this._containerSizeClassName = uniqueCssClassName("containersize"); - Utilities.addClass(this._site.surface, this._containerSizeClassName); - } - var ruleSelector = "." + WinJS.UI._containerClass, - ruleBody = "width:" + width + ";height:" + height + ";"; - addDynamicCssRule(this._containerSizeClassName, this._site, ruleSelector, ruleBody); - } - }, - - // Computes container width and height if they haven't been computed yet. This - // should happen when the first uniform group is created. - _ensureContainerSize: function _LayoutCommon_ensureContainerSize(group) { - var sizes = this._sizes; - if (!sizes.containerSizeLoaded && !this._ensuringContainerSize) { - var promise; - if ((!this._itemInfo || typeof this._itemInfo !== "function") && this._useDefaultItemInfo) { - var margins = sizes.containerMargins; - promise = WinJS.Promise.wrap({ - width: group.groupInfo.cellWidth - margins.left - margins.right, - height: group.groupInfo.cellHeight - margins.top - margins.bottom - }); - - } else { - promise = this._getItemInfo(); - } - - var that = this; - this._ensuringContainerSize = promise.then(function (itemSize) { - sizes.containerSizeLoaded = true; - sizes.containerWidth = itemSize.width + sizes.itemBoxOuterWidth + sizes.containerOuterWidth; - sizes.containerHeight = itemSize.height + sizes.itemBoxOuterHeight + sizes.containerOuterHeight; - if (!that._inListMode) { - that._itemsPerBar = Math.floor(sizes.maxItemsContainerContentSize / sizes.containerCrossSize); - if (that.maximumRowsOrColumns) { - that._itemsPerBar = Math.min(that._itemsPerBar, that.maximumRowsOrColumns); - } - that._itemsPerBar = Math.max(1, that._itemsPerBar); - } else { - that._itemsPerBar = 1; - } - that._createContainerStyleRule(); - }); - - promise.done( - function () { - that._ensuringContainerSize = null; - }, - function () { - that._ensuringContainerSize = null; - } - ); - - return promise; - } else { - return this._ensuringContainerSize ? this._ensuringContainerSize : WinJS.Promise.wrap(); - } - }, - - _indexToCoordinate: function _LayoutCommon_indexToCoordinate(index, itemsPerBar) { - itemsPerBar = itemsPerBar || this._itemsPerBar; - var bar = Math.floor(index / itemsPerBar); - if (this._horizontal) { - return { - column: bar, - row: index - bar * itemsPerBar - }; - } else { - return { - row: bar, - column: index - bar * itemsPerBar - }; - } - }, - - // Empty ranges are represented by null. Non-empty ranges are represented by - // an object with 2 properties: firstIndex and lastIndex. - _rangeForGroup: function _LayoutCommon_rangeForGroup(group, range) { - var first = group.startIndex, - last = first + group.count - 1; - - if (!range || range.firstIndex > last || range.lastIndex < first) { - // There isn't any overlap between range and the group's indices - return null; - } else { - return { - firstIndex: Math.max(0, range.firstIndex - first), - lastIndex: Math.min(group.count - 1, range.lastIndex - first) - }; - } - }, - - _syncDomWithGroupHeaderPosition: function _LayoutCommon_syncDomWithGroupHeaderPosition(tree) { - if (this._groupsEnabled && this._oldGroupHeaderPosition !== this._groupHeaderPosition) { - // this._oldGroupHeaderPosition may refer to top, left, or null. It will be null - // the first time this function is called which means that no styles have to be - // removed. - - var len = tree.length, - i; - // Remove styles associated with old group header position - if (this._oldGroupHeaderPosition === WinJS.UI.HeaderPosition.top) { - Utilities.removeClass(this._site.surface, WinJS.UI._headerPositionTopClass); - // maxWidth must be cleared because it is used with headers in the top position but not the left position. - // The _groupLeaderClass must be removed from the itemsContainer element because the associated styles - // should only be applied to it when headers are in the top position. - if (this._horizontal) { - for (i = 0; i < len; i++) { - tree[i].header.style.maxWidth = ""; - WinJS.Utilities.removeClass(tree[i].itemsContainer.element, WinJS.UI._groupLeaderClass); - } - } else { - this._site.surface.style.msGridRows = ""; - } - } else if (this._oldGroupHeaderPosition === WinJS.UI.HeaderPosition.left) { - Utilities.removeClass(this._site.surface, WinJS.UI._headerPositionLeftClass); - // msGridColumns is cleared for a similar reason as maxWidth - if (!this._horizontal) { - for (i = 0; i < len; i++) { - tree[i].header.style.maxHeight = ""; - WinJS.Utilities.removeClass(tree[i].itemsContainer.element, WinJS.UI._groupLeaderClass); - } - } - this._site.surface.style.msGridColumns = ""; - } - - // Add styles associated with new group header position - if (this._groupHeaderPosition === WinJS.UI.HeaderPosition.top) { - Utilities.addClass(this._site.surface, WinJS.UI._headerPositionTopClass); - if (this._horizontal) { - for (i = 0; i < len; i++) { - WinJS.Utilities.addClass(tree[i].itemsContainer.element, WinJS.UI._groupLeaderClass); - } - } - } else { - //#DBG _ASSERT(this._groupHeaderPosition === WinJS.UI.HeaderPosition.left); - Utilities.addClass(this._site.surface, WinJS.UI._headerPositionLeftClass); - if (!this._horizontal) { - for (i = 0; i < len; i++) { - WinJS.Utilities.addClass(tree[i].itemsContainer.element, WinJS.UI._groupLeaderClass); - } - } - } - - this._oldGroupHeaderPosition = this._groupHeaderPosition; - } - }, - - _layoutGroup: function _LayoutCommon_layoutGroup(index) { - var group = this._groups[index], - groupBundle = this._site.tree[index], - headerContainer = groupBundle.header, - itemsContainer = groupBundle.itemsContainer.element, - sizes = this._sizes; - - if (this._groupsEnabled) { - if (this._horizontal) { - if (this._groupHeaderPosition === WinJS.UI.HeaderPosition.top) { - var headerContainerMinContentWidth = sizes.headerContainerMinWidth - sizes.headerContainerOuterWidth, - itemsContainerContentWidth = group.getItemsContainerSize() - sizes.headerContainerOuterWidth; - headerContainer.style.msGridColumn = index + 1; - headerContainer.style.maxWidth = Math.max(headerContainerMinContentWidth, itemsContainerContentWidth) + "px"; - itemsContainer.style.msGridColumn = index + 1; - // itemsContainers only get the _groupLeaderClass when header position is top. - Utilities.addClass(itemsContainer, WinJS.UI._groupLeaderClass); - } else { - //#DBG _ASSERT(this._groupHeaderPosition === WinJS.UI.HeaderPosition.left); - headerContainer.style.msGridColumn = index * 2 + 1; - itemsContainer.style.msGridColumn = index * 2 + 2; - } - } else { - if (this._groupHeaderPosition === WinJS.UI.HeaderPosition.left) { - var headerContainerMinContentHeight = sizes.headerContainerMinHeight - sizes.headerContainerOuterHeight, - itemsContainerContentHeight = group.getItemsContainerSize() - sizes.headerContainerOuterHeight; - headerContainer.style.msGridRow = index + 1; - headerContainer.style.maxHeight = Math.max(headerContainerMinContentHeight, itemsContainerContentHeight) + "px"; - itemsContainer.style.msGridRow = index + 1; - // itemsContainers only get the _groupLeaderClass when header position is left. - Utilities.addClass(itemsContainer, WinJS.UI._groupLeaderClass); - } else { - //#DBG _ASSERT(this._groupHeaderPosition === WinJS.UI.HeaderPosition.top); - headerContainer.style.msGridRow = index * 2 + 1; - // It's important to explicitly set the container height in vertical list mode with headers above, since we use flow layout. - // When the header's content is taken from the DOM, the headerContainer will shrink unless it has a height set. - if (this._inListMode) { - headerContainer.style.height = (sizes.headerContainerHeight - sizes.headerContainerOuterHeight) + "px"; - } - itemsContainer.style.msGridRow = index * 2 + 2; - } - - } - // Header containers always get the _groupLeaderClass. - Utilities.addClass(headerContainer, WinJS.UI._laidOutClass + " " + WinJS.UI._groupLeaderClass); - } - Utilities.addClass(itemsContainer, WinJS.UI._laidOutClass); - } - }, { - // The maximum number of rows or columns of win-containers to put into each items block. - // A row/column cannot be split across multiple items blocks. win-containers - // are grouped into items blocks in order to mitigate the costs of the platform doing - // a layout in response to insertions and removals of win-containers. - _barsPerItemsBlock: 4 - }); - }), - - // - // Layouts - // - - _LegacyLayout: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(WinJS.UI._LayoutCommon, null, { - /// - /// Gets or sets a value that indicates whether the layout should disable the backdrop feature - /// which avoids blank areas while panning in a virtualized list. - /// - /// disableBackdrop is deprecated. Style: .win-listview .win-container.win-backdrop { background-color:transparent; } instead. - /// - /// - disableBackdrop: { - get: function _LegacyLayout_disableBackdrop_get() { - return this._backdropDisabled || false; - }, - set: function _LegacyLayout_disableBackdrop_set(value) { - Utilities._deprecated(WinJS.UI._strings.disableBackdropIsDeprecated); - value = !!value; - if (this._backdropDisabled !== value) { - this._backdropDisabled = value; - if (this._disableBackdropClassName) { - deleteDynamicCssRule(this._disableBackdropClassName); - this._site && Utilities.removeClass(this._site.surface, this._disableBackdropClassName); - this._disableBackdropClassName = null; - } - this._disableBackdropClassName = uniqueCssClassName("disablebackdrop"); - this._site && Utilities.addClass(this._site.surface, this._disableBackdropClassName); - if (value) { - var ruleSelector = ".win-container.win-backdrop", - ruleBody = "background-color:transparent;"; - addDynamicCssRule(this._disableBackdropClassName, this._site, ruleSelector, ruleBody); - } - } - } - }, - - /// - /// Gets or sets the fill color for the default pattern used for the backdrops. - /// The default value is "rgba(155,155,155,0.23)". - /// - /// backdropColor is deprecated. Style: .win-listview .win-container.win-backdrop { rgba(155,155,155,0.23); } instead. - /// - /// - backdropColor: { - get: function _LegacyLayout_backdropColor_get() { - return this._backdropColor || "rgba(155,155,155,0.23)"; - }, - set: function _LegacyLayout_backdropColor_set(value) { - Utilities._deprecated(WinJS.UI._strings.backdropColorIsDeprecated); - if (value && this._backdropColor !== value) { - this._backdropColor = value; - if (this._backdropColorClassName) { - deleteDynamicCssRule(this._backdropColorClassName); - this._site && Utilities.removeClass(this._site.surface, this._backdropColorClassName); - this._backdropColorClassName = null; - } - this._backdropColorClassName = uniqueCssClassName("backdropcolor"); - this._site && Utilities.addClass(this._site.surface, this._backdropColorClassName); - var ruleSelector = ".win-container.win-backdrop", - ruleBody = "background-color:" + value + ";"; - addDynamicCssRule(this._backdropColorClassName, this._site, ruleSelector, ruleBody); - } - } - } - }); - }), - - GridLayout: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(WinJS.UI._LegacyLayout, function (options) { - /// - /// - /// Creates a new GridLayout. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. Each property of the options - /// object corresponds to one of the control's properties or events. - /// - /// - /// The new GridLayout. - /// - /// - options = options || {}; - // Executing setters to display compatibility warning - this.itemInfo = options.itemInfo; - this.groupInfo = options.groupInfo; - this._maxRowsOrColumns = 0; - this._useDefaultItemInfo = true; - this._elementsToMeasure = {}; - this._groupHeaderPosition = options.groupHeaderPosition || WinJS.UI.HeaderPosition.top; - this.orientation = options.orientation || "horizontal"; - - if (options.maxRows) { - this.maxRows = +options.maxRows; - } - if (options.maximumRowsOrColumns) { - this.maximumRowsOrColumns = +options.maximumRowsOrColumns; - } - }, { - - // Public - - /// - /// Gets the maximum number of rows or columns, depending on the orientation, that should present before it introduces wrapping to the layout. - /// A value of 0 indicates that there is no maximum. The default value is 0. - /// - maximumRowsOrColumns: { - get: function () { - return this._maxRowsOrColumns; - }, - set: function (value) { - this._setMaxRowsOrColumns(value); - } - }, - - /// - /// Gets or sets the maximum number of rows displayed by the ListView. - /// - /// WinJS.UI.GridLayout.maxRows may be altered or unavailable after the Windows Library for JavaScript 2.0. Instead, use the maximumRowsOrColumns property. - /// - /// - maxRows: { - get: function () { - return this.maximumRowsOrColumns; - }, - set: function (maxRows) { - Utilities._deprecated(WinJS.UI._strings.maxRowsIsDeprecated); - this.maximumRowsOrColumns = maxRows; - } - }, - - /// - /// Determines the size of the item and whether - /// the item should be placed in a new column. - /// - /// GridLayout.itemInfo may be altered or unavailable in future versions. Instead, use CellSpanningLayout. - /// - /// - itemInfo: { - enumerable: true, - get: function () { - return this._itemInfo; - }, - set: function (itemInfo) { - itemInfo && Utilities._deprecated(WinJS.UI._strings.itemInfoIsDeprecated); - this._itemInfo = itemInfo; - this._invalidateLayout(); - } - }, - - /// - /// Indicates whether a group has cell spanning items and specifies the dimensions of the cell. - /// - /// GridLayout.groupInfo may be altered or unavailable in future versions. Instead, use CellSpanningLayout. - /// - /// - groupInfo: { - enumerable: true, - get: function () { - return this._groupInfo; - }, - set: function (groupInfo) { - groupInfo && Utilities._deprecated(WinJS.UI._strings.groupInfoIsDeprecated); - this._groupInfo = groupInfo; - this._invalidateLayout(); - } - } - }); - }) - }); - - var Groups = WinJS.Namespace.defineWithParent(null, null, { - - UniformGroupBase: WinJS.Namespace._lazy(function () { - return WinJS.Class.define(null, { - cleanUp: function UniformGroupBase_cleanUp() { - }, - - itemFromOffset: function UniformGroupBase_itemFromOffset(offset, options) { - // supported options are: - // - wholeItem: when set to true the fully visible item is returned - // - last: if 1 the last item is returned. if 0 the first - options = options || {}; - - var sizes = this._layout._sizes; - - // Make offset relative to the items container's content box - offset -= sizes.itemsContainerOuterStart; - - if (options.wholeItem) { - offset += (options.last ? -1 : 1) * (sizes.containerSize - 1); - } - var lastIndexOfGroup = this.count - 1, - lastBar = Math.floor(lastIndexOfGroup / this._layout._itemsPerBar), - bar = clampToRange(0, lastBar, Math.floor(offset / sizes.containerSize)), - index = (bar + options.last) * this._layout._itemsPerBar - options.last; - return clampToRange(0, this.count - 1, index); - }, - - hitTest: function UniformGroupBase_hitTest(x, y) { - var horizontal = this._layout._horizontal, - itemsPerBar = this._layout._itemsPerBar, - useListSemantics = this._layout._inListMode || itemsPerBar === 1, - directionalLocation = horizontal ? x : y, - crossLocation = horizontal ? y : x, - sizes = this._layout._sizes; - - directionalLocation -= sizes.itemsContainerOuterStart; - crossLocation -= sizes.itemsContainerOuterCrossStart; - - var bar = Math.floor(directionalLocation / sizes.containerSize); - var slotInBar = clampToRange(0, itemsPerBar - 1, Math.floor(crossLocation / sizes.containerCrossSize)); - var index = Math.max(-1, bar * itemsPerBar + slotInBar); - - // insertAfterIndex is determined by which half of the target element the mouse cursor is currently in. - // The trouble is that we can cut the element in half horizontally or cut it in half vertically. - // Which one we choose depends on the order that elements are laid out in the grid. - // A horizontal grid with multiple rows per column will lay items out starting from top to bottom, and move left to right. - // A vertical list is just a horizontal grid with an infinite number of rows per column, so it follows the same order. - // In both of these cases, each item is cut in half horizontally, since for any item n, n-1 should be above it and n+1 below (ignoring column changes). - // A vertical grid lays items out left to right, top to bottom, and a horizontal list left to right (with infinite items per row). - // In this case for item n, n-1 is on the left and n+1 on the right, so we cut the item in half vertically. - var insertAfterSlot; - if ((!horizontal && useListSemantics) || - (horizontal && !useListSemantics)) { - insertAfterSlot = (y - sizes.containerHeight / 2) / sizes.containerHeight; - } else { - insertAfterSlot = (x - sizes.containerWidth / 2) / sizes.containerWidth; - } - if (useListSemantics) { - insertAfterSlot = Math.floor(insertAfterSlot); - return { - index: index, - insertAfterIndex: (insertAfterSlot >= 0 && index >= 0 ? insertAfterSlot : -1) - }; - } - insertAfterSlot = clampToRange(-1, itemsPerBar - 1, insertAfterSlot); - var insertAfterIndex; - if (insertAfterSlot < 0) { - insertAfterIndex = bar * itemsPerBar - 1; - } else { - insertAfterIndex = bar * itemsPerBar + Math.floor(insertAfterSlot); - } - - return { - index: clampToRange(-1, this.count - 1, index), - insertAfterIndex: clampToRange(-1, this.count - 1, insertAfterIndex) - }; - }, - - getAdjacent: function UniformGroupBase_getAdjacent(currentItem, pressedKey) { - var index = currentItem.index, - currentBar = Math.floor(index / this._layout._itemsPerBar), - currentSlot = index % this._layout._itemsPerBar, - newFocus; - - switch (pressedKey) { - case Key.upArrow: - newFocus = (currentSlot === 0 ? "boundary" : index - 1); - break; - case Key.downArrow: - var isLastIndexOfGroup = (index === this.count - 1), - inLastSlot = (this._layout._itemsPerBar > 1 && currentSlot === this._layout._itemsPerBar - 1); - newFocus = (isLastIndexOfGroup || inLastSlot ? "boundary" : index + 1); - break; - case Key.leftArrow: - newFocus = (currentBar === 0 && this._layout._itemsPerBar > 1 ? "boundary" : index - this._layout._itemsPerBar); - break; - case Key.rightArrow: - var lastIndexOfGroup = this.count - 1, - lastBar = Math.floor(lastIndexOfGroup / this._layout._itemsPerBar); - newFocus = (currentBar === lastBar ? "boundary" : Math.min(index + this._layout._itemsPerBar, this.count - 1)); - break; - } - return (newFocus === "boundary" ? newFocus : { type: WinJS.UI.ObjectType.item, index: newFocus }); - }, - - getItemsContainerSize: function UniformGroupBase_getItemsContainerSize() { - var sizes = this._layout._sizes, - barCount = Math.ceil(this.count / this._layout._itemsPerBar); - return barCount * sizes.containerSize + sizes.itemsContainerOuterSize; - }, - - getItemPositionForAnimations: function UniformGroupBase_getItemPositionForAnimations(itemIndex) { - // Top/Left are used to know if the item has moved and also used to position the item if removed. - // Row/Column are used to know if a reflow animation should occur - // Height/Width are used when positioning a removed item without impacting layout. - // The returned rectangle refers to the win-container's border/padding/content box. Coordinates - // are relative to group's items container. - - var sizes = this._layout._sizes; - var leftStr = this._layout._site.rtl ? "right" : "left"; - var containerMargins = this._layout._sizes.containerMargins; - var coordinates = this._layout._indexToCoordinate(itemIndex); - var itemPosition = { - row: coordinates.row, - column: coordinates.column, - top: containerMargins.top + coordinates.row * sizes.containerHeight, - left: containerMargins[leftStr] + coordinates.column * sizes.containerWidth, - height: sizes.containerHeight - sizes.containerMargins.top - sizes.containerMargins.bottom, - width: sizes.containerWidth - sizes.containerMargins.left - sizes.containerMargins.right - }; - return itemPosition; - } - }); - }), - - // - // Groups for GridLayout - // - // Each group implements a 3 function layout interface. The interface is used - // whenever GridLayout has to do a layout. The interface consists of: - // - prepareLayout/prepareLayoutWithCopyOfTree: Called 1st. Group should update all of its internal - // layout state. It should not modify the DOM. Group should implement either prepareLayout or - // prepareLayoutWithCopyOfTree. The former is preferable because the latter is expensive as calling - // it requires copying the group's tree. Implementing prepareLayoutWithCopyOfTree is necessary when - // the group is manually laying out items and is laying out unrealized items asynchronously - // (e.g. CellSpanningGroup). This requires a copy of the tree from the previous layout pass. - // - layoutRealizedRange: Called 2nd. Group should update the DOM so that - // the realized range reflects the internal layout state computed during - // prepareLayout. - // - layoutUnrealizedRange: Called 3rd. Group should update the DOM for the items - // outside of the realized range. This function returns a promise so - // it can do its work asynchronously. When the promise completes, layout will - // be done. - // - // The motivation for this interface is perceived performance. If groups had just 1 - // layout function, all items would have to be laid out before any animations could - // begin. With this interface, animations can begin playing after - // layoutRealizedRange is called. - // - // Each group also implements a cleanUp function which is called when the group is - // no longer needed so that it can clean up the DOM and its resources. After cleanUp - // is called, the group object cannnot be reused. - // - - UniformGroup: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(Groups.UniformGroupBase, function UniformGroup_ctor(layout, itemsContainer) { - this._layout = layout; - this._itemsContainer = itemsContainer; - Utilities.addClass(this._itemsContainer, layout._inListMode ? WinJS.UI._uniformListLayoutClass : WinJS.UI._uniformGridLayoutClass); - }, { - cleanUp: function UniformGroup_cleanUp(skipDomCleanUp) { - if (!skipDomCleanUp) { - Utilities.removeClass(this._itemsContainer, WinJS.UI._uniformGridLayoutClass); - Utilities.removeClass(this._itemsContainer, WinJS.UI._uniformListLayoutClass); - this._itemsContainer.style.height = this._itemsContainer.style.width = ""; - } - this._itemsContainer = null; - this._layout = null; - this.groupInfo = null; - this.startIndex = null; - this.offset = null; - this.count = null; - }, - - prepareLayout: function UniformGroup_prepareLayout(itemsCount, oldChangedRealizedRange, oldState, updatedProperties) { - this.groupInfo = updatedProperties.groupInfo; - this.startIndex = updatedProperties.startIndex; - this.count = itemsCount; - return this._layout._ensureContainerSize(this); - }, - - layoutRealizedRange: function UniformGroup_layoutRealizedRange(changedRange, realizedRange) { - // Explicitly set the items container size. This is required so that the - // surface, which is a grid, will have its width sized to content. - var sizes = this._layout._sizes; - this._itemsContainer.style[this._layout._horizontal ? "width" : "height"] = this.getItemsContainerSize() - sizes.itemsContainerOuterSize + "px"; - this._itemsContainer.style[this._layout._horizontal ? "height" : "width"] = (this._layout._inListMode ? sizes.maxItemsContainerContentSize + "px" : - this._layout._itemsPerBar * sizes.containerCrossSize + "px"); - }, - - layoutUnrealizedRange: function UniformGroup_layoutUnrealizedRange(changedRange, realizedRange, beforeRealizedRange) { - return WinJS.Promise.wrap(); - } - }); - }), - - UniformFlowGroup: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(Groups.UniformGroupBase, function UniformFlowGroup_ctor(layout, tree) { - this._layout = layout; - this._itemsContainer = tree.element; - Utilities.addClass(this._itemsContainer, layout._inListMode ? WinJS.UI._uniformListLayoutClass : WinJS.UI._uniformGridLayoutClass); - }, { - cleanUp: function UniformFlowGroup_cleanUp(skipDomCleanUp) { - if (!skipDomCleanUp) { - Utilities.removeClass(this._itemsContainer, WinJS.UI._uniformListLayoutClass); - Utilities.removeClass(this._itemsContainer, WinJS.UI._uniformGridLayoutClass); - this._itemsContainer.style.height = ""; - } - }, - layout: function UniformFlowGroup_layout() { - this._layout._site._writeProfilerMark("Layout:_UniformFlowGroup:setItemsContainerHeight,info"); - this._itemsContainer.style.height = this.count * this._layout._sizes.containerHeight + "px"; - } - }) - }), - - CellSpanningGroup: WinJS.Namespace._lazy(function () { - return WinJS.Class.define(function CellSpanningGroup_ctor(layout, itemsContainer) { - this._layout = layout; - this._itemsContainer = itemsContainer; - Utilities.addClass(this._itemsContainer, WinJS.UI._cellSpanningGridLayoutClass); - - this.resetMap(); - }, { - cleanUp: function CellSpanningGroup_cleanUp(skipDomCleanUp) { - if (!skipDomCleanUp) { - this._cleanContainers(); - Utilities.removeClass(this._itemsContainer, WinJS.UI._cellSpanningGridLayoutClass); - this._itemsContainer.style.cssText = ""; - } - this._itemsContainer = null; - - if (this._layoutPromise) { - this._layoutPromise.cancel(); - this._layoutPromise = null; - } - this.resetMap(); - this._slotsPerColumn = null; - this._offScreenSlotsPerColumn = null; - this._items = null; - this._layout = null; - this._containersToHide = null; - this.groupInfo = null; - this.startIndex = null; - this.offset = null; - this.count = null; - }, - - prepareLayoutWithCopyOfTree: function CellSpanningGroup_prepareLayoutWithCopyOfTree(tree, oldChangedRealizedRange, oldState, updatedProperties) { - var that = this; - var i; - - // Remember the items in the old realized item range that changed. - // During layoutRealizedRange, they either need to be relaid out or hidden. - this._containersToHide = {}; - if (oldChangedRealizedRange) { - for (i = oldChangedRealizedRange.firstIndex; i <= oldChangedRealizedRange.lastIndex; i++) { - this._containersToHide[oldState._items[i].uniqueID] = oldState._items[i]; - } - } - - // Update public properties - this.groupInfo = updatedProperties.groupInfo; - this.startIndex = updatedProperties.startIndex; - this.count = tree.items.length; - - this._items = tree.items; - this._slotsPerColumn = Math.floor(this._layout._sizes.maxItemsContainerContentSize / this.groupInfo.cellHeight); - if (this._layout.maximumRowsOrColumns) { - this._slotsPerColumn = Math.min(this._slotsPerColumn, this._layout.maximumRowsOrColumns); - } - this._slotsPerColumn = Math.max(this._slotsPerColumn, 1); - - this.resetMap(); - var itemInfoPromises = new Array(this.count); - for (i = 0; i < this.count; i++) { - itemInfoPromises[i] = this._layout._getItemInfo(this.startIndex + i); - } - return WinJS.Promise.join(itemInfoPromises).then(function (itemInfos) { - itemInfos.forEach(function (itemInfo, index) { - that.addItemToMap(index, itemInfo); - }); - }); - }, - - layoutRealizedRange: function CellSpanningGroup_layoutRealizedRange(firstChangedIndex, realizedRange) { - // Lay out the changed items within the realized range - if (realizedRange) { - var firstChangedRealizedIndex = Math.max(firstChangedIndex, realizedRange.firstIndex), - i; - for (i = firstChangedRealizedIndex; i <= realizedRange.lastIndex; i++) { - this._layoutItem(i); - delete this._containersToHide[this._items[i].uniqueID]; - } - } - - // Hide the old containers that are in the realized range but weren't relaid out - Object.keys(this._containersToHide).forEach(function (id) { - WinJS.Utilities.removeClass(this._containersToHide[id], WinJS.UI._laidOutClass); - }.bind(this)); - this._containersToHide = {}; - - // Explicitly set the items container height. This is required so that the - // surface, which is a grid, will have its width sized to content. - this._itemsContainer.style.cssText += - ";width:" + (this.getItemsContainerSize() - this._layout._sizes.itemsContainerOuterSize) + - "px;height:" + this._layout._sizes.maxItemsContainerContentSize + - "px;-ms-grid-columns: (" + this.groupInfo.cellWidth + "px)[" + this.getColumnCount() + - "];-ms-grid-rows: (" + this.groupInfo.cellHeight + "px)[" + (this._slotsPerColumn + this._offScreenSlotsPerColumn) + "]"; - }, - - layoutUnrealizedRange: function CellSpanningGroup_layoutUnrealizedRange(firstChangedIndex, realizedRange, beforeRealizedRange) { - var that = this; - var layoutJob; - - that._layoutPromise = new WinJS.Promise(function (complete) { - function completeLayout() { - layoutJob = null; - complete(); - } - - function schedule(fn) { - return Scheduler.schedule(fn, Scheduler.Priority.normal, null, - "WinJS.UI.GridLayout.CellSpanningGroup.LayoutUnrealizedRange"); - } - - // These loops are built to lay out the items that are closest to - // the realized range first. - - if (realizedRange) { - var stop = false; - // For laying out the changed items that are before the realized range - var before = realizedRange.firstIndex - 1; - // For laying out the changed items that are after the realized range - var after = Math.max(firstChangedIndex, realizedRange.lastIndex + 1); - after = Math.max(before + 1, after); - - // Alternate between laying out items before and after the realized range - layoutJob = schedule(function unrealizedRangeWork(info) { - while (!stop) { - if (info.shouldYield) { - info.setWork(unrealizedRangeWork); - return; - } - - stop = true; - - if (before >= firstChangedIndex) { - that._layoutItem(before); - before--; - stop = false; - } - if (after < that.count) { - that._layoutItem(after); - after++; - stop = false; - } - } - completeLayout(); - }); - } else if (beforeRealizedRange) { - // The items we are laying out come before the realized range. - // so lay them out in descending order. - var i = that.count - 1; - layoutJob = schedule(function beforeRealizedRangeWork(info) { - for (; i >= firstChangedIndex; i--) { - if (info.shouldYield) { - info.setWork(beforeRealizedRangeWork); - return; - } - that._layoutItem(i); - } - completeLayout(); - }); - } else { - // The items we are laying out come after the realized range - // so lay them out in ascending order. - var i = firstChangedIndex; - layoutJob = schedule(function afterRealizedRangeWork(info) { - for (; i < that.count; i++) { - if (info.shouldYield) { - info.setWork(afterRealizedRangeWork); - return; - } - that._layoutItem(i); - } - completeLayout(); - }); - } - }, function () { - // Cancellation handler for that._layoutPromise - layoutJob && layoutJob.cancel(); - layoutJob = null; - }); - - return that._layoutPromise; - }, - - itemFromOffset: function CellSpanningGroup_itemFromOffset(offset, options) { - // supported options are: - // - wholeItem: when set to true the fully visible item is returned - // - last: if 1 the last item is returned. if 0 the first - options = options || {}; - - var sizes = this._layout._sizes, - margins = sizes.containerMargins; - - // Make offset relative to the items container's content box - offset -= sizes.itemsContainerOuterX; - - offset -= ((options.last ? 1 : -1) * margins[options.last ? "left" : "right"]); - - var value = this.indexFromOffset(offset, options.wholeItem, options.last).item; - return clampToRange(0, this.count - 1, value); - }, - - getAdjacent: function CellSpanningGroup_getAdjacent(currentItem, pressedKey) { - var index, - originalIndex; - - index = originalIndex = currentItem.index; - - var newIndex, inMap, inMapIndex; - if (this.lastAdjacent === index) { - inMapIndex = this.lastInMapIndex; - } else { - inMapIndex = this.findItem(index); - } - - do { - var column = Math.floor(inMapIndex / this._slotsPerColumn), - row = inMapIndex - column * this._slotsPerColumn, - lastColumn = Math.floor((this.occupancyMap.length - 1) / this._slotsPerColumn), - entry, - c; - - switch (pressedKey) { - case Key.upArrow: - if (row > 0) { - inMapIndex--; - } else { - return { type: WinJS.UI.ObjectType.item, index: originalIndex }; - } - break; - case Key.downArrow: - if (row + 1 < this._slotsPerColumn) { - inMapIndex++; - } else { - return { type: WinJS.UI.ObjectType.item, index: originalIndex }; - } - break; - case Key.leftArrow: - inMapIndex = (column > 0 ? inMapIndex - this._slotsPerColumn : -1); - break; - case Key.rightArrow: - inMapIndex = (column < lastColumn ? inMapIndex + this._slotsPerColumn : this.occupancyMap.length); - break; - } - - inMap = inMapIndex >= 0 && inMapIndex < this.occupancyMap.length; - if (inMap) { - newIndex = this.occupancyMap[inMapIndex] ? this.occupancyMap[inMapIndex].index : undefined; - } - - } while (inMap && (index === newIndex || newIndex === undefined)); - - this.lastAdjacent = newIndex; - this.lastInMapIndex = inMapIndex; - - return (inMap ? { type: WinJS.UI.ObjectType.item, index: newIndex } : "boundary"); - }, - - hitTest: function CellSpanningGroup_hitTest(x, y) { - var sizes = this._layout._sizes, - itemIndex = 0; - - // Make the coordinates relative to the items container's content box - x -= sizes.itemsContainerOuterX; - y -= sizes.itemsContainerOuterY; - - if (this.occupancyMap.length > 0) { - var result = this.indexFromOffset(x, false, 0); - - var counter = Math.min(this._slotsPerColumn - 1, Math.floor(y / this.groupInfo.cellHeight)), - curr = result.index, - lastValidIndex = curr; - while (counter-- > 0) { - curr++; - if (this.occupancyMap[curr]) { - lastValidIndex = curr; - } - } - if (!this.occupancyMap[lastValidIndex]) { - lastValidIndex--; - } - itemIndex = this.occupancyMap[lastValidIndex].index; - } - - var itemSize = this.getItemSize(itemIndex), - itemLeft = itemSize.column * this.groupInfo.cellWidth, - itemTop = itemSize.row * this.groupInfo.cellHeight, - useListSemantics = this._slotsPerColumn === 1, - insertAfterIndex = itemIndex; - - if ((useListSemantics && (x < (itemLeft + itemSize.contentWidth / 2))) || - (!useListSemantics && (y < (itemTop + itemSize.contentHeight / 2)))) { - insertAfterIndex--; - } - - return { - type: WinJS.UI.ObjectType.item, - index: clampToRange(0, this.count - 1, itemIndex), - insertAfterIndex: clampToRange(-1, this.count - 1, insertAfterIndex) - }; - }, - - getItemsContainerSize: function CellSpanningGroup_getItemsContainerSize() { - var sizes = this._layout._sizes; - return this.getColumnCount() * this.groupInfo.cellWidth + sizes.itemsContainerOuterSize; - }, - - getItemPositionForAnimations: function CellSpanningGroup_getItemPositionForAnimations(itemIndex) { - // Top/Left are used to know if the item has moved and also used to position the item if removed. - // Row/Column are used to know if a reflow animation should occur - // Height/Width are used when positioning a removed item without impacting layout. - // The returned rectangle refers to the win-container's border/padding/content box. Coordinates - // are relative to group's items container. - - var sizes = this._layout._sizes; - var leftStr = this._layout._site.rtl ? "right" : "left"; - var containerMargins = this._layout._sizes.containerMargins; - var coordinates = this.getItemSize(itemIndex); - var groupInfo = this.groupInfo; - var itemPosition = { - row: coordinates.row, - column: coordinates.column, - top: containerMargins.top + coordinates.row * groupInfo.cellHeight, - left: containerMargins[leftStr] + coordinates.column * groupInfo.cellWidth, - height: coordinates.contentHeight, - width: coordinates.contentWidth - }; - - return itemPosition; - }, - - _layoutItem: function CellSpanningGroup_layoutItem(index) { - var groupInfo = this.groupInfo, - margins = this._layout._sizes.containerMargins, - entry = this.getItemSize(index); - this._items[index].style.cssText += - ";-ms-grid-row:" + (entry.row + 1) + - ";-ms-grid-column:" + (entry.column + 1) + - ";-ms-grid-row-span:" + entry.rows + - ";-ms-grid-column-span:" + entry.columns + - ";height:" + entry.contentHeight + - "px;width:" + entry.contentWidth + "px"; - Utilities.addClass(this._items[index], WinJS.UI._laidOutClass); - - return this._items[index]; - }, - - _cleanContainers: function CellSpanningGroup_cleanContainers() { - var items = this._items, - len = items.length, - i; - for (i = 0; i < len; i++) { - items[i].style.cssText = ""; - Utilities.removeClass(items[i], WinJS.UI._laidOutClass); - } - }, - - // Occupancy map - - getColumnCount: function CellSpanningGroup_getColumnCount() { - return Math.ceil(this.occupancyMap.length / this._slotsPerColumn); - }, - - getOccupancyMapItemCount: function CellSpanningGroup_getOccupancyMapItemCount() { - var index = -1; - - // Use forEach as the map may be sparse - this.occupancyMap.forEach(function (item) { - if (item.index > index) { - index = item.index; - } - }); - - return index + 1; - }, - - coordinateToIndex: function CellSpanningGroup_coordinateToIndex(c, r) { - return c * this._slotsPerColumn + r; - }, - - markSlotAsFull: function CellSpanningGroup_markSlotAsFull(index, itemEntry) { - var coordinates = this._layout._indexToCoordinate(index, this._slotsPerColumn), - toRow = coordinates.row + itemEntry.rows; - for (var r = coordinates.row; r < toRow && r < this._slotsPerColumn; r++) { - for (var c = coordinates.column, toColumn = coordinates.column + itemEntry.columns; c < toColumn; c++) { - this.occupancyMap[this.coordinateToIndex(c, r)] = itemEntry; - } - } - this._offScreenSlotsPerColumn = Math.max(this._offScreenSlotsPerColumn, toRow - this._slotsPerColumn); - }, - - isSlotEmpty: function CellSpanningGroup_isSlotEmpty(itemSize, row, column) { - for (var r = row, toRow = row + itemSize.rows; r < toRow; r++) { - for (var c = column, toColumn = column + itemSize.columns; c < toColumn; c++) { - if ((r >= this._slotsPerColumn) || (this.occupancyMap[this.coordinateToIndex(c, r)] !== undefined)) { - return false; - } - } - } - return true; - }, - - findEmptySlot: function CellSpanningGroup_findEmptySlot(startIndex, itemSize, newColumn) { - var coordinates = this._layout._indexToCoordinate(startIndex, this._slotsPerColumn), - startRow = coordinates.row, - lastColumn = Math.floor((this.occupancyMap.length - 1) / this._slotsPerColumn); - - if (newColumn) { - for (var c = coordinates.column + 1; c <= lastColumn; c++) { - if (this.isSlotEmpty(itemSize, 0, c)) { - return this.coordinateToIndex(c, 0); - } - } - } else { - for (var c = coordinates.column; c <= lastColumn; c++) { - for (var r = startRow; r < this._slotsPerColumn; r++) { - if (this.isSlotEmpty(itemSize, r, c)) { - return this.coordinateToIndex(c, r); - } - } - startRow = 0; - } - } - - return (lastColumn + 1) * this._slotsPerColumn; - }, - - findItem: function CellSpanningGroup_findItem(index) { - for (var inMapIndex = index, len = this.occupancyMap.length; inMapIndex < len; inMapIndex++) { - var entry = this.occupancyMap[inMapIndex]; - if (entry && entry.index === index) { - return inMapIndex; - } - } - return inMapIndex; - }, - - getItemSize: function CellSpanningGroup_getItemSize(index) { - var inMapIndex = this.findItem(index), - entry = this.occupancyMap[inMapIndex], - coords = this._layout._indexToCoordinate(inMapIndex, this._slotsPerColumn); - - if (index === entry.index) { - return { - row: coords.row, - column: coords.column, - contentWidth: entry.contentWidth, - contentHeight: entry.contentHeight, - columns: entry.columns, - rows: entry.rows - }; - } else { - return null; - } - }, - - resetMap: function CellSpanningGroup_resetMap() { - this.occupancyMap = []; - this.lastAdded = 0; - this._offScreenSlotsPerColumn = 0; - }, - - addItemToMap: function CellSpanningGroup_addItemToMap(index, itemInfo) { - var that = this; - - function add(mapEntry, newColumn) { - var inMapIndex = that.findEmptySlot(that.lastAdded, mapEntry, newColumn); - that.lastAdded = inMapIndex; - that.markSlotAsFull(inMapIndex, mapEntry); - } - - var groupInfo = that.groupInfo, - margins = that._layout._sizes.containerMargins, - mapEntry = { - index: index, - contentWidth: itemInfo.width, - contentHeight: itemInfo.height, - columns: Math.max(1, Math.ceil((itemInfo.width + margins.left + margins.right) / groupInfo.cellWidth)), - rows: Math.max(1, Math.ceil((itemInfo.height + margins.top + margins.bottom) / groupInfo.cellHeight)) - }; - - add(mapEntry, itemInfo.newColumn); - }, - - indexFromOffset: function CellSpanningGroup_indexFromOffset(adjustedOffset, wholeItem, last) { - var measuredWidth = 0, - lastItem = 0, - groupInfo = this.groupInfo, - index = 0; - - if (this.occupancyMap.length > 0) { - lastItem = this.getOccupancyMapItemCount() - 1; - measuredWidth = Math.ceil((this.occupancyMap.length - 1) / this._slotsPerColumn) * groupInfo.cellWidth; - - if (adjustedOffset < measuredWidth) { - var counter = this._slotsPerColumn, - index = (Math.max(0, Math.floor(adjustedOffset / groupInfo.cellWidth)) + last) * this._slotsPerColumn - last; - while (!this.occupancyMap[index] && counter-- > 0) { - index += (last > 0 ? -1 : 1); - } - return { - index: index, - item: this.occupancyMap[index].index - } - } else { - index = this.occupancyMap.length - 1; - } - } - - return { - index: index, - item: lastItem + (Math.max(0, Math.floor((adjustedOffset - measuredWidth) / groupInfo.cellWidth)) + last) * this._slotsPerColumn - last - }; - } - }); - }) - - }); - - WinJS.Namespace.define("WinJS.UI", { - - ListLayout: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(WinJS.UI._LegacyLayout, function ListLayout_ctor(options) { - /// - /// - /// Creates a new ListLayout object. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. Each property of the options - /// object corresponds to one of the object's properties or events. Event names must begin with "on". - /// - /// - /// The new ListLayout object. - /// - /// - options = options || {}; - this._itemInfo = {}; - this._groupInfo = {}; - this._groupHeaderPosition = options.groupHeaderPosition || WinJS.UI.HeaderPosition.top; - this._inListMode = true; - this.orientation = options.orientation || "vertical"; - }, { - initialize: function ListLayout_initialize(site, groupsEnabled) { - Utilities.addClass(site.surface, WinJS.UI._listLayoutClass); - WinJS.UI._LegacyLayout.prototype.initialize.call(this, site, groupsEnabled); - }, - - uninitialize: function ListLayout_uninitialize() { - if (this._site) { - Utilities.removeClass(this._site.surface, WinJS.UI._listLayoutClass); - } - WinJS.UI._LegacyLayout.prototype.uninitialize.call(this); - }, - - layout: function ListLayout_layout(tree, changedRange, modifiedItems, modifiedGroups) { - if (!this._groupsEnabled && !this._horizontal) { - return this._layoutNonGroupedVerticalList(tree, changedRange, modifiedItems, modifiedGroups); - } else { - return WinJS.UI._LegacyLayout.prototype.layout.call(this, tree, changedRange, modifiedItems, modifiedGroups); - } - }, - - _layoutNonGroupedVerticalList: function ListLayout_layoutNonGroupedVerticalList(tree, changedRange, modifiedItems, modifiedGroups) { - var that = this; - var perfId = "Layout:_layoutNonGroupedVerticalList"; - that._site._writeProfilerMark(perfId + ",StartTM"); - this._layoutPromise = that._measureItem(0).then(function () { - WinJS.Utilities[that._usingStructuralNodes ? "addClass" : "removeClass"](that._site.surface, WinJS.UI._structuralNodesClass); - - if (that._sizes.viewportContentSize !== that._getViewportCrossSize()) { - that._viewportSizeChanged(that._getViewportCrossSize()); - } - - that._cacheRemovedElements(modifiedItems, that._cachedItemRecords, that._cachedInsertedItemRecords, that._cachedRemovedItems, false); - that._cacheRemovedElements(modifiedGroups, that._cachedHeaderRecords, that._cachedInsertedHeaderRecords, that._cachedRemovedHeaders, true); - - var itemsContainer = tree[0].itemsContainer, - group = new Groups.UniformFlowGroup(that, itemsContainer); - that._groups = [group]; - group.groupInfo = { enableCellSpanning: false }; - group.startIndex = 0; - group.count = getItemsContainerLength(itemsContainer); - group.offset = 0; - group.layout(); - - that._site._writeProfilerMark(perfId + ":setSurfaceWidth,info"); - that._site.surface.style.width = that._sizes.surfaceContentSize + "px"; - - that._layoutAnimations(modifiedItems, modifiedGroups); - that._site._writeProfilerMark(perfId + ":complete,info"); - that._site._writeProfilerMark(perfId + ",StopTM"); - }, function (error) { - that._site._writeProfilerMark(perfId + ":canceled,info"); - that._site._writeProfilerMark(perfId + ",StopTM"); - return WinJS.Promise.wrapError(error); - }); - return { - realizedRangeComplete: this._layoutPromise, - layoutComplete: this._layoutPromise - }; - }, - - numberOfItemsPerItemsBlock: { - get: function ListLayout_getNumberOfItemsPerItemsBlock() { - // Measure when numberOfItemsPerItemsBlock is called so that we measure before ListView has created the full tree structure - // which reduces the trident layout required by measure. - this._usingStructuralNodes = WinJS.UI.ListLayout._numberOfItemsPerItemsBlock > 0; - return this._measureItem(0).then(function () { - return WinJS.UI.ListLayout._numberOfItemsPerItemsBlock; - }); - } - }, - }, { - // The maximum number of win-containers to put into each items block. win-containers - // are grouped into items blocks in order to mitigate the costs of the platform doing - // a layout in response to insertions and removals of win-containers. - _numberOfItemsPerItemsBlock: 10 - }); - }), - - CellSpanningLayout: WinJS.Namespace._lazy(function () { - return WinJS.Class.derive(WinJS.UI._LayoutCommon, function CellSpanningLayout_ctor(options) { - /// - /// - /// Creates a new CellSpanningLayout object. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new object. Each property of the options - /// object corresponds to one of the object's properties or events. Event names must begin with "on". - /// - /// - /// The new CellSpanningLayout object. - /// - /// - options = options || {}; - this._itemInfo = options.itemInfo; - this._groupInfo = options.groupInfo; - this._groupHeaderPosition = options.groupHeaderPosition || WinJS.UI.HeaderPosition.top; - this._horizontal = true; - this._cellSpanning = true; - }, { - - /// - /// Gets or set the maximum number of rows or columns, depending on the orientation, to display before content begins to wrap. - /// A value of 0 indicates that there is no maximum. - /// - maximumRowsOrColumns: { - get: function () { - return this._maxRowsOrColumns; - }, - set: function (value) { - this._setMaxRowsOrColumns(value); - } - }, - - /// - /// Gets or sets a function that returns the width and height of an item, as well as whether - /// it should appear in a new column. Setting this function improves performance because - /// the ListView can allocate space for an item without having to measure it first. - /// The function takes a single parameter: the index of the item to render. - /// The function returns an object that has three properties: - /// width: The total width of the item. - /// height: The total height of the item. - /// newColumn: Set to true to create a column break; otherwise, false. - /// - itemInfo: { - enumerable: true, - get: function () { - return this._itemInfo; - }, - set: function (itemInfo) { - this._itemInfo = itemInfo; - this._invalidateLayout(); - } - }, - - /// - /// Gets or sets a function that enables cell-spanning and establishes base cell dimensions. - /// The function returns an object that has these properties: - /// enableCellSpanning: Set to true to allow the ListView to contain items of multiple sizes. - /// cellWidth: The width of the base cell. - /// cellHeight: The height of the base cell. - /// - groupInfo: { - enumerable: true, - get: function () { - return this._groupInfo; - }, - set: function (groupInfo) { - this._groupInfo = groupInfo; - this._invalidateLayout(); - } - }, - - /// - /// Gets the orientation of the layout. CellSpanning layout only supports horizontal orientation. - /// - orientation: { - enumerable: true, - get: function () { - return "horizontal"; - } - } - }); - }), - - _LayoutWrapper: WinJS.Namespace._lazy(function () { - return WinJS.Class.define(function LayoutWrapper_ctor(layout) { - this.defaultAnimations = true; - - // Initialize and hitTest are required - this.initialize = function LayoutWrapper_initialize(site, groupsEnabled) { - layout.initialize(site, groupsEnabled); - }; - this.hitTest = function LayoutWrapper_hitTest(x, y) { - return layout.hitTest(x, y); - }; - - // These methods are optional - layout.uninitialize && (this.uninitialize = function LayoutWrapper_uninitialize() { - layout.uninitialize(); - }); - - if ("numberOfItemsPerItemsBlock" in layout) { - Object.defineProperty(this, "numberOfItemsPerItemsBlock", { - get: function LayoutWrapper_getNumberOfItemsPerItemsBlock() { - return layout.numberOfItemsPerItemsBlock; - } - }); - } - - layout._getItemPosition && (this._getItemPosition = function LayoutWrapper_getItemPosition(index) { - return layout._getItemPosition(index); - }); - - layout.itemsFromRange && (this.itemsFromRange = function LayoutWrapper_itemsFromRange(start, end) { - return layout.itemsFromRange(start, end); - }); - - layout.getAdjacent && (this.getAdjacent = function LayoutWrapper_getAdjacent(currentItem, pressedKey) { - return layout.getAdjacent(currentItem, pressedKey); - }); - - layout.dragOver && (this.dragOver = function LayoutWrapper_dragOver(x, y, dragInfo) { - return layout.dragOver(x, y, dragInfo); - }); - - layout.dragLeave && (this.dragLeave = function LayoutWrapper_dragLeave() { - return layout.dragLeave(); - }); - var propertyDefinition = { - enumerable: true, - get: function () { - return "vertical"; - } - } - if (layout.orientation !== undefined) { - propertyDefinition.get = function () { - return layout.orientation; - } - propertyDefinition.set = function (value) { - layout.orientation = value; - } - } - Object.defineProperty(this, "orientation", propertyDefinition); - - if (layout.setupAnimations || layout.executeAnimations) { - this.defaultAnimations = false; - this.setupAnimations = function LayoutWrapper_setupAnimations() { - return layout.setupAnimations(); - }; - this.executeAnimations = function LayoutWrapper_executeAnimations() { - return layout.executeAnimations(); - }; - } - - if (layout.layout) { - if (this.defaultAnimations) { - var that = this; - this.layout = function LayoutWrapper_layout(tree, changedRange, modifiedItems, modifiedGroups) { - var promises = normalizeLayoutPromises(layout.layout(tree, changedRange, [], [])), - synchronous; - promises.realizedRangeComplete.then(function () { - synchronous = true; - }); - synchronous && that._layoutAnimations(modifiedItems, modifiedGroups); - return promises; - }; - } else { - this.layout = function LayoutWrapper_layout(tree, changedRange, modifiedItems, modifiedGroups) { - return normalizeLayoutPromises(layout.layout(tree, changedRange, modifiedItems, modifiedGroups)); - }; - } - } - }, { - uninitialize: function LayoutWrapper_uninitialize() { - }, - numberOfItemsPerItemsBlock: { - get: function LayoutWrapper_getNumberOfItemsPerItemsBlock() { - } - }, - layout: function LayoutWrapper_layout(tree, changedRange, modifiedItems, modifiedGroups) { - if (this.defaultAnimations) { - this._layoutAnimations(modifiedItems, modifiedGroups); - } - return normalizeLayoutPromises(); - }, - itemsFromRange: function LayoutWrapper_itemsFromRange(start, end) { - return { firstIndex: 0, lastIndex: Number.MAX_VALUE }; - }, - getAdjacent: function LayoutWrapper_getAdjacent(currentItem, pressedKey) { - var key = WinJS.Utilities.Key; - - switch (pressedKey) { - case key.pageUp: - case key.upArrow: - case key.leftArrow: - return { type: currentItem.type, index: currentItem.index - 1 }; - case key.downArrow: - case key.rightArrow: - case key.pageDown: - return { type: currentItem.type, index: currentItem.index + 1 }; - } - }, - dragOver: function LayoutWrapper_dragOver(x, y) { - }, - dragLeave: function LayoutWrapper_dragLeaver() { - }, - setupAnimations: function LayoutWrapper_setupAnimations() { - }, - executeAnimations: function LayoutWrapper_executeAnimations() { - }, - _getItemPosition: function LayoutWrapper_getItemPosition() { - }, - _layoutAnimations: function LayoutWrapper_layoutAnimations(modifiedItems, modifiedGroups) { - }, - }); - }), - }); - - function normalizeLayoutPromises(retVal) { - if (WinJS.Promise.is(retVal)) { - return { - realizedRangeComplete: retVal, - layoutComplete: retVal - }; - } else if (typeof retVal === "object" && retVal && retVal.layoutComplete) { - return retVal; - } else { - return { - realizedRangeComplete: WinJS.Promise.wrap(), - layoutComplete: WinJS.Promise.wrap() - }; - } - } - - function getMargins(element) { - return { - left: getDimension(element, "marginLeft"), - right: getDimension(element, "marginRight"), - top: getDimension(element, "marginTop"), - bottom: getDimension(element, "marginBottom") - }; - } - - // Layout, _LayoutCommon, and _LegacyLayout are defined ealier so that their fully - // qualified names can be used in WinJS.Class.derive. This is required by Blend. - WinJS.Namespace.define("WinJS.UI", { - HeaderPosition: { - left: "left", - top: "top" - }, - _getMargins: getMargins - }); -})(this, WinJS); - - -(function listViewImplInit(global, WinJS, undefined) { - "use strict"; - - var DISPOSE_TIMEOUT = 1000; - var controlsToDispose = []; - var disposeControlTimeout; - function disposeControls() { - var temp = controlsToDispose; - controlsToDispose = []; - temp = temp.filter(function (c) { - if (c._isZombie()) { - c._dispose(); - return false; - } else { - return true; - } - }); - controlsToDispose = controlsToDispose.concat(temp); - } - function scheduleForDispose(lv) { - controlsToDispose.push(lv); - disposeControlTimeout && disposeControlTimeout.cancel(); - disposeControlTimeout = WinJS.Promise.timeout(DISPOSE_TIMEOUT).then(disposeControls); - } - - function ensureId(element) { - if (!element.id) { - element.id = element.uniqueID; - } - } - - function setFlow(from, to) { - WinJS.UI._setAttribute(from, "aria-flowto", to.id); - WinJS.UI._setAttribute(to, "x-ms-aria-flowfrom", from.id); - } - - // Only set the attribute if its value has changed - function setAttribute(element, attribute, value) { - if (element.getAttribute(attribute) !== "" + value) { - element.setAttribute(attribute, value); - } - } - - function nodeListToArray(nodeList) { - return Array.prototype.slice.call(nodeList); - } - - function repeat(markup, count) { - return new Array(count + 1).join(markup); - } - - function getOffsetRight(element) { - return element.offsetParent ? (element.offsetParent.offsetWidth - element.offsetLeft - element.offsetWidth) : 0; - } - - // Default renderer for Listview - var trivialHtmlRenderer = WinJS.UI.simpleItemRenderer(function (item) { - if (utilities._isDOMElement(item.data)) { - return item.data; - } - - var data = item.data; - if (data === undefined) { - data = "undefined"; - } else if (data === null) { - data = "null"; - } else if (typeof data === "object") { - data = JSON.stringify(data); - } - - var element = document.createElement("span"); - element.innerText = data.toString(); - return element; - }); - - WinJS.Namespace.define("WinJS.UI", { - _trivialHtmlRenderer: trivialHtmlRenderer, - _disposeControls: disposeControls, - _ensureId: ensureId, - _setFlow: setFlow, - _setAttribute: setAttribute, - _nodeListToArray: nodeListToArray, - _repeat: repeat, - _ListViewAnimationHelper: { - fadeInElement: function (element) { - return WinJS.UI.Animation.fadeIn(element); - }, - fadeOutElement: function (element) { - return WinJS.UI.Animation.fadeOut(element); - }, - animateEntrance: function (canvas, firstEntrance) { - return WinJS.UI.Animation.enterContent(canvas, [{ left: firstEntrance ? "100px" : "40px", top: "0px", rtlflip: true }], { mechanism: "transition" }); - }, - } - }); - - var ScrollToPriority = { - uninitialized: 0, - low: 1, // used by layoutSite.invalidateLayout, forceLayout, _processReload, _update and _onMSElementResize - operations that preserve the scroll position - medium: 2, // used by dataSource change, layout change and etc - operations that reset the scroll position to 0 - high: 3 // used by indexOfFirstVisible, ensureVisible, scrollPosition - operations in which the developer explicitly sets the scroll position - }; - - var ViewChange = { - rebuild: 0, - remeasure: 1, - relayout: 2, - realize: 3 - }; - - var thisWinUI = WinJS.UI, - utilities = WinJS.Utilities, - Promise = WinJS.Promise, - Scheduler = utilities.Scheduler, - AnimationHelper = WinJS.UI._ListViewAnimationHelper; - - var strings = { - get notCompatibleWithSemanticZoom() { return WinJS.Resources._getWinJSString("ui/notCompatibleWithSemanticZoom").value; }, - get listViewInvalidItem() { return WinJS.Resources._getWinJSString("ui/listViewInvalidItem").value; }, - get listViewViewportAriaLabel() { return WinJS.Resources._getWinJSString("ui/listViewViewportAriaLabel").value; } - }; - - var requireSupportedForProcessing = WinJS.Utilities.requireSupportedForProcessing; - - // ListView implementation - - WinJS.Namespace.define("WinJS.UI", { - _ScrollToPriority: ScrollToPriority, - - _ViewChange: ViewChange, - - /// - /// Specifies the type of an IListViewEntity. - /// - ObjectType: { - /// - /// This value represents a ListView item. - /// - item: "item", - /// - /// This value represents a ListView group header. - /// - groupHeader: "groupHeader" - }, - - /// - /// Specifies the selection mode for a ListView. - /// - SelectionMode: { - /// - /// Items cannot be selected. - /// - none: "none", - /// - /// A single item may be selected. - /// - single: "single", - /// - /// Multiple items may be selected. - /// - /// - multi: "multi" - }, - - /// - /// Specifies how an ItemContainer or items in a ListView respond to the tap interaction. - /// - TapBehavior: { - /// - /// Tapping the item invokes it and selects it. Navigating to the item with the keyboard changes the - /// the selection so that the focused item is the only item that is selected. - /// - /// - directSelect: "directSelect", - /// - /// Tapping the item invokes it. If the item was selected, tapping it clears the selection. If the item wasn't - /// selected, tapping the item selects it. - /// Navigating to the item with the keyboard does not select or invoke it. - /// - toggleSelect: "toggleSelect", - /// - /// Tapping the item invokes it. Navigating to the item with keyboard does not select it or invoke it. - /// - invokeOnly: "invokeOnly", - /// - /// Nothing happens. - /// - none: "none" - }, - - /// - /// Specifies how group headers in a ListView respond to the tap interaction. - /// - GroupHeaderTapBehavior: { - /// - /// Tapping the group header invokes it. - /// - invoke: "invoke", - /// - /// Nothing happens. - /// - none: "none" - }, - - /// - /// Specifies whether items are selected when the user performs a swipe interaction. - /// - /// - SwipeBehavior: { - /// - /// The swipe interaction selects the items touched by the swipe. - /// - /// - select: "select", - /// - /// The swipe interaction does not change which items are selected. - /// - /// - none: "none" - }, - - /// - /// Specifies whether the ListView animation is an entrance animation or a transition animation. - /// - /// - ListViewAnimationType: { - /// - /// The animation plays when the ListView is first displayed. - /// - /// - entrance: "entrance", - /// - /// The animation plays when the ListView is changing its content. - /// - /// - contentTransition: "contentTransition" - }, - - /// - /// Displays items in a customizable list or grid. - /// - /// - /// - /// ]]> - /// Raised when the ListView is about to play an entrance or a transition animation. - /// Raised when the user taps or clicks an item. - /// Raised when the user taps or clicks a group header. - /// Raised before items are selected or deselected. - /// Raised after items are selected or deselected. - /// Raised when the loading state changes. - /// Raised when the focused item changes. - /// Raised when the the user begins dragging ListView items. - /// Raised when the user drags into the ListView. - /// Raised when a drag operation begun in a ListView ends. - /// Raised when the user drags between two ListView items. - /// Raised when the user drags outside of the ListView region. - /// Raised when the items being dragged are changed due to a datasource modification. - /// Raised when the user drops items into the ListView. - /// Raised when the accessibility attributes have been added to the ListView items. - /// The entire ListView control. - /// The viewport of the ListView. - /// The scrollable region of the ListView. - /// An item in the ListView. - /// The background of a selection checkmark. - /// A selection checkmark. - /// The header of a group. - /// The progress indicator of the ListView. - /// - /// - /// - ListView: WinJS.Namespace._lazy(function () { - var AffectedRange = WinJS.Class.define(function () { - this.clear(); - }, { - // Marks the union of the current affected range and range as requiring layout - add: function (range, itemsCount) { - range._lastKnownSizeOfData = itemsCount; // store this in order to make unions. - if (!this._range) { - this._range = range; - } else { - // Take the union of these two ranges. - this._range.start = Math.min(this._range.start, range.start); - // To accurately calculate the new unioned range 'end' value, we need to convert the current and new range end - // positions into values that represent the remaining number of un-modified items in between the end of the range - // and the end of the list of data. - var previousUnmodifiedItemsFromEnd = (this._range._lastKnownSizeOfData - this._range.end); - var newUnmodifiedItemsFromEnd = (range._lastKnownSizeOfData - range.end); - var finalUnmodifiedItemsFromEnd = Math.min(previousUnmodifiedItemsFromEnd, newUnmodifiedItemsFromEnd); - this._range._lastKnownSizeOfData = range._lastKnownSizeOfData; - // Convert representation of the unioned end position back into a value which matches the above definition of _affecteRange.end - this._range.end = this._range._lastKnownSizeOfData - finalUnmodifiedItemsFromEnd; - } - }, - - // Marks everything as requiring layout - addAll: function () { - this.add({ start: 0, end: Number.MAX_VALUE }, Number.MAX_VALUE); - }, - - // Marks nothing as requiring layout - clear: function () { - this._range = null; - }, - - get: function () { - return this._range; - } - }); - - var ZoomableView = WinJS.Class.define(function ZoomableView_ctor(listView) { - // Constructor - - this._listView = listView; - }, { - // Public methods - - getPanAxis: function () { - return this._listView._getPanAxis(); - }, - - configureForZoom: function (isZoomedOut, isCurrentView, triggerZoom, prefetchedPages) { - this._listView._configureForZoom(isZoomedOut, isCurrentView, triggerZoom, prefetchedPages); - }, - - setCurrentItem: function (x, y) { - this._listView._setCurrentItem(x, y); - }, - - getCurrentItem: function () { - return this._listView._getCurrentItem(); - }, - - beginZoom: function () { - this._listView._beginZoom(); - }, - - positionItem: function (item, position) { - return this._listView._positionItem(item, position); - }, - - endZoom: function (isCurrentView) { - this._listView._endZoom(isCurrentView); - } - }); - - var ListView = WinJS.Class.define(function ListView_ctor(element, options) { - /// - /// - /// Creates a new ListView. - /// - /// - /// The DOM element that hosts the ListView control. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. - /// Each property of the options object corresponds to one of the control's properties or events. - /// Event names must begin with "on". For example, to provide a handler for the selectionchanged event, - /// add a property named "onselectionchanged" to the options object and set its value to the event handler. - /// - /// - /// The new ListView. - /// - /// - element = element || document.createElement("div"); - this._id = element.id || ""; - this._writeProfilerMark("constructor,StartTM"); - - options = options || {}; - - // Attaching JS control to DOM element - element.winControl = this; - WinJS.Utilities.addClass(element, "win-disposable"); - this._affectedRange = new AffectedRange(); - this._mutationObserver = new MutationObserver(this._itemPropertyChange.bind(this)); - this._versionManager = null; - this._insertedItems = {}; - this._element = element; - this._startProperty = null; - this._scrollProperty = null; - this._scrollLength = null; - this._scrolling = false; - this._zooming = false; - this._pinching = false; - this._itemsManager = null; - this._canvas = null; - this._cachedCount = WinJS.UI._UNINITIALIZED; - this._loadingState = this._LoadingState.complete; - this._firstTimeDisplayed = true; - this._currentScrollPosition = 0; - this._lastScrollPosition = 0; - this._notificationHandlers = []; - this._itemsBlockExtent = -1; - this._viewportWidth = WinJS.UI._UNINITIALIZED; - this._viewportHeight = WinJS.UI._UNINITIALIZED; - this._manipulationState = MSManipulationEvent.MS_MANIPULATION_STATE_STOPPED; - this._maxDeferredItemCleanup = Number.MAX_VALUE; - this._groupsToRemove = {}; - this._setupInternalTree(); - this._isCurrentZoomView = true; - this._dragSource = false; - this._reorderable = false; - this._groupFocusCache = new WinJS.UI._UnsupportedGroupFocusCache(); - this._viewChange = ViewChange.rebuild; - this._scrollToFunctor = null; - this._setScrollbarPosition = false; - // The view needs to be initialized after the internal tree is setup, because the view uses the canvas node immediately to insert an element in its constructor - this._view = new WinJS.UI._VirtualizeContentsView(this); - this._selection = new WinJS.UI._SelectionManager(this); - this._createTemplates(); - var that = this; - this._groupHeaderRenderer = WinJS.UI._trivialHtmlRenderer; - this._itemRenderer = WinJS.UI._trivialHtmlRenderer; - this._groupHeaderRelease = null; - this._itemRelease = null; - if (!options.itemDataSource) { - var list = new WinJS.Binding.List(); - this._dataSource = list.dataSource; - } else { - this._dataSource = options.itemDataSource; - } - this._selectionMode = WinJS.UI.SelectionMode.multi; - this._tap = WinJS.UI.TapBehavior.invokeOnly; - this._groupHeaderTap = WinJS.UI.GroupHeaderTapBehavior.invoke; - this._swipeBehavior = WinJS.UI.SwipeBehavior.select; - this._mode = new WinJS.UI._SelectionMode(this); - - // Call after swipeBehavior and modes are set - this._setSwipeClass(); - - this._groups = new WinJS.UI._NoGroups(this); - this._updateItemsAriaRoles(); - this._updateGroupHeadersAriaRoles(); - this._element.setAttribute("aria-multiselectable", this._multiSelection()); - this._tabIndex = (this._element.tabIndex !== undefined && this._element.tabIndex >= 0) ? this._element.tabIndex : 0; - this._element.tabIndex = -1; - this._tabManager.tabIndex = this._tabIndex; - if (this._element.style.position !== "absolute" && this._element.style.position !== "relative") { - this._element.style.position = "relative"; - } - this._updateItemsManager(); - if (!options.layout) { - this._updateLayout(new WinJS.UI.GridLayout()); - } - this._attachEvents(); - - this._runningInit = true; - WinJS.UI.setOptions(this, options); - this._runningInit = false; - - this._batchViewUpdates(ViewChange.rebuild, ScrollToPriority.medium, 0); - this._writeProfilerMark("constructor,StopTM"); - }, { - // Public properties - - /// - element: { - get: function () { return this._element; } - }, - - /// - /// Gets or sets an object that controls the layout of the ListView. - /// - layout: { - get: function () { - return this._layoutImpl; - }, - set: function (layoutObject) { - this._updateLayout(layoutObject); - - if (!this._runningInit) { - this._view.reset(); - this._updateItemsManager(); - this._batchViewUpdates(ViewChange.rebuild, ScrollToPriority.medium, 0, true); - } - } - }, - - /// - /// Gets or sets the number of pages to load when the user scrolls beyond the - /// threshold specified by the pagesToLoadThreshold property if - /// the loadingBehavior property is set to incremental. - /// - /// pagesToLoad is deprecated. The control will not use this property. Please refer to the 'ListView loading behaviors' SDK Sample for guidance on how to implement incremental load behavior. - /// - /// - pagesToLoad: { - get: function () { - return (WinJS.UI._VirtualizeContentsView._pagesToPrefetch * 2) + 1; - }, - set: function (newValue) { - utilities._deprecated(WinJS.UI._strings.pagesToLoadIsDeprecated); - } - }, - - /// - /// Gets or sets the threshold (in pages) for initiating an incremental load. When the last visible item is - /// within the specified number of pages from the end of the loaded portion of the list, - /// and if automaticallyLoadPages is true and loadingBehavior is set to "incremental", - /// the ListView initiates an incremental load. - /// - /// pagesToLoadThreshold is deprecated. The control will not use this property. Please refer to the 'ListView loading behaviors' SDK Sample for guidance on how to implement incremental load behavior. - /// - /// - pagesToLoadThreshold: { - get: function () { - return 0; - }, - set: function (newValue) { - utilities._deprecated(WinJS.UI._strings.pagesToLoadThresholdIsDeprecated); - } - }, - - /// - /// Gets or sets the data source that contains the groups for the items in the itemDataSource. - /// - groupDataSource: { - get: function () { - return this._groupDataSource; - }, - set: function (newValue) { - this._writeProfilerMark("set_groupDataSource,info"); - - var that = this; - - function groupStatusChanged(eventObject) { - if (eventObject.detail === thisWinUI.DataSourceStatus.failure) { - that.itemDataSource = null; - that.groupDataSource = null; - } - } - - if (this._groupDataSource && this._groupDataSource.removeEventListener) { - this._groupDataSource.removeEventListener("statuschanged", groupStatusChanged, false); - } - - this._groupDataSource = newValue; - this._groupFocusCache = (newValue && this._supportsGroupHeaderKeyboarding) ? new WinJS.UI._GroupFocusCache(this) : new WinJS.UI._UnsupportedGroupFocusCache(); - - if (this._groupDataSource && this._groupDataSource.addEventListener) { - this._groupDataSource.addEventListener("statuschanged", groupStatusChanged, false); - } - - this._createGroupsContainer(); - - if (!this._runningInit) { - this._view.reset(); - this._pendingLayoutReset = true; - this._pendingGroupWork = true; - this._batchViewUpdates(ViewChange.rebuild, ScrollToPriority.medium, 0, true); - } else { - this._updateGroupWork(); - this._resetLayout(); - } - } - }, - - _updateGroupWork: function () { - this._pendingGroupWork = false; - - if (this._groupDataSource) { - utilities.addClass(this._element, WinJS.UI._groupsClass); - } else { - utilities.removeClass(this._element, WinJS.UI._groupsClass); - } - this._resetLayout(); - }, - - /// - /// Gets or sets a value that indicates whether the next set of pages is automatically loaded - /// when the user scrolls beyond the number of pages specified by the - /// pagesToLoadThreshold property. - /// - /// automaticallyLoadPages is deprecated. The control will default this property to false. Please refer to the 'ListView loading behaviors' SDK Sample for guidance on how to implement incremental load behavior. - /// - /// - automaticallyLoadPages: { - get: function () { - return false; - }, - set: function (newValue) { - utilities._deprecated(WinJS.UI._strings.automaticallyLoadPagesIsDeprecated); - } - }, - - /// - /// Gets or sets a value that determines how many data items are loaded into the DOM. - /// - /// pagesToLoadThreshold is deprecated. The control will default this property to 'randomAccess'. Please refer to the 'ListView loading behaviors' SDK Sample for guidance on how to implement incremental load behavior. - /// - /// - loadingBehavior: { - get: function () { - return "randomAccess"; - }, - set: function (newValue) { - utilities._deprecated(WinJS.UI._strings.loadingBehaviorIsDeprecated); - } - }, - - /// - /// Gets or sets a value that specifies how many ListView items the user can select: "none", "single", or "multi". - /// - selectionMode: { - get: function () { - return this._selectionMode; - }, - set: function (newMode) { - if (typeof newMode === "string") { - if (newMode.match(/^(none|single|multi)$/)) { - this._selectionMode = newMode; - this._element.setAttribute("aria-multiselectable", this._multiSelection()); - this._updateItemsAriaRoles(); - this._setSwipeClass(); - return; - } - } - throw new WinJS.ErrorFromName("WinJS.UI.ListView.ModeIsInvalid", WinJS.UI._strings.modeIsInvalid); - } - }, - - /// - /// Gets or sets how the ListView reacts when the user taps or clicks an item. - /// The tap or click can invoke the item, select it and invoke it, or have no - /// effect. - /// - tapBehavior: { - get: function () { - return this._tap; - }, - set: function (tap) { - this._tap = tap; - this._updateItemsAriaRoles(); - } - }, - - /// - /// Gets or sets how the ListView reacts when the user taps or clicks a group header. - /// - groupHeaderTapBehavior: { - get: function () { - return this._groupHeaderTap; - }, - set: function (tap) { - this._groupHeaderTap = tap; - this._updateGroupHeadersAriaRoles(); - } - }, - - /// - /// Gets or sets how the ListView reacts to the swipe interaction. - /// The swipe gesture can select the swiped items or it can - /// have no effect on the current selection. - /// - /// - swipeBehavior: { - get: function () { - return this._swipeBehavior; - }, - set: function (swipeBehavior) { - this._swipeBehavior = swipeBehavior; - this._setSwipeClass(); - } - }, - - /// - /// Gets or sets the data source that provides items for the ListView. - /// - itemDataSource: { - get: function () { - return this._itemsManager.dataSource; - }, - set: function (newData) { - this._writeProfilerMark("set_itemDataSource,info"); - this._dataSource = newData || new WinJS.Binding.List().dataSource; - this._groupFocusCache.clear(); - - if (!this._runningInit) { - this._selection._reset(); - this._cancelAsyncViewWork(true); - this._updateItemsManager(); - this._pendingLayoutReset = true; - this._batchViewUpdates(ViewChange.rebuild, ScrollToPriority.medium, 0, true); - } - } - }, - - /// - /// Gets or sets the templating function that creates the DOM elements - /// for each item in the itemDataSource. Each item can contain multiple - /// DOM elements, but we recommend that it have a single root element. - /// - itemTemplate: { - get: function () { - return this._itemRenderer; - }, - set: function (newRenderer) { - this._setRenderer(newRenderer, false); - - if (!this._runningInit) { - this._cancelAsyncViewWork(true); - this._updateItemsManager(); - this._pendingLayoutReset = true; - this._batchViewUpdates(ViewChange.rebuild, ScrollToPriority.medium, 0, true); - } - } - }, - - /// - /// Gets or sets the function that is called when the ListView recycles the - /// element representation of an item. - /// - /// resetItem may be altered or unavailable in future versions. Instead, mark the element as disposable using WinJS.Utilities.markDisposable. - /// - /// - resetItem: { - get: function () { - return this._itemRelease; - }, - set: function (release) { - utilities._deprecated(WinJS.UI._strings.resetItemIsDeprecated); - this._itemRelease = release; - } - }, - - /// - /// Gets or sets the templating function that creates the DOM elements - /// for each group header in the groupDataSource. Each group header - /// can contain multiple elements, but it must have a single root element. - /// - groupHeaderTemplate: { - get: function () { - return this._groupHeaderRenderer; - }, - set: function (newRenderer) { - this._setRenderer(newRenderer, true); - - if (!this._runningInit) { - this._cancelAsyncViewWork(true); - this._pendingLayoutReset = true; - this._batchViewUpdates(ViewChange.rebuild, ScrollToPriority.medium, 0, true); - } - } - }, - - /// - /// Gets or sets the function that is called when the ListView recycles the DOM element representation - /// of a group header. - /// - /// resetGroupHeader may be altered or unavailable in future versions. Instead, mark the header element as disposable using WinJS.Utilities.markDisposable. - /// - /// - resetGroupHeader: { - get: function () { - return this._groupHeaderRelease; - }, - set: function (release) { - utilities._deprecated(WinJS.UI._strings.resetGroupHeaderIsDeprecated); - this._groupHeaderRelease = release; - } - }, - - /// - loadingState: { - get: function () { - return this._loadingState; - } - }, - - /// - /// Gets an ISelection object that contains the currently selected items. - /// - selection: { - get: function () { - return this._selection; - } - }, - - /// - /// Gets or sets the first visible item. When setting this property, the ListView scrolls so that the - /// item with the specified index is at the top of the list. - /// - indexOfFirstVisible: { - get: function () { - return this._view.firstIndexDisplayed; - }, - - set: function (itemIndex) { - if (itemIndex < 0) { - return; - } - - this._writeProfilerMark("set_indexOfFirstVisible(" + itemIndex + "),info"); - this._raiseViewLoading(true); - - var that = this; - this._batchViewUpdates(ViewChange.realize, ScrollToPriority.high, function () { - var range; - return that._entityInRange({ type: WinJS.UI.ObjectType.item, index: itemIndex }).then(function (validated) { - if (!validated.inRange) { - return { - position: 0, - direction: "left" - }; - } else { - return that._getItemOffset({ type: WinJS.UI.ObjectType.item, index: validated.index }).then(function (r) { - range = r; - return that._ensureFirstColumnRange(WinJS.UI.ObjectType.item); - }).then(function () { - range = that._correctRangeInFirstColumn(range, WinJS.UI.ObjectType.item); - range = that._convertFromCanvasCoordinates(range); - - return that._view.waitForValidScrollPosition(range.begin); - }).then(function (begin) { - var direction = (begin < that._lastScrollPosition) ? "left" : "right"; - var max = that._viewport[that._scrollLength] - that._getViewportLength(); - begin = utilities._clamp(begin, 0, max); - - return { - position: begin, - direction: direction - }; - }); - } - }); - }, true); - } - }, - - /// - /// Gets the index of the last visible item. - /// - indexOfLastVisible: { - get: function () { - return this._view.lastIndexDisplayed; - } - }, - - /// - /// Gets or sets an object that indicates which item should get keyboard focus and its focus status. - /// The object has these properties: - /// index: the index of the item in the itemDataSource. - /// key: the key of the item in the itemDataSource. - /// hasFocus: when getting this property, this value is true if the item already has focus; otherwise, it's false. - /// When setting this property, set this value to true if the item should get focus immediately; otherwise, set it to - /// false and the item will get focus eventually. - /// showFocus: true if the item displays the focus rectangle; otherwise, false. - /// - currentItem: { - get: function () { - var focused = this._selection._getFocused(); - var retVal = { - index: focused.index, - type: focused.type, - key: null, - hasFocus: !!this._hasKeyboardFocus, - showFocus: false - }; - if (focused.type === WinJS.UI.ObjectType.groupHeader) { - var group = this._groups.group(focused.index); - if (group) { - retVal.key = group.key; - retVal.showFocus = !!(group.header && WinJS.Utilities.hasClass(group.header, WinJS.UI._itemFocusClass)); - } - } else { - var item = this._view.items.itemAt(focused.index); - if (item) { - var record = this._itemsManager._recordFromElement(item); - retVal.key = record.item && record.item.key; - retVal.showFocus = !!item.parentNode.querySelector("." + thisWinUI._itemFocusOutlineClass); - } - } - return retVal; - }, - - set: function (data) { - this._hasKeyboardFocus = data.hasFocus || this._hasKeyboardFocus; - var that = this; - function setItemFocused(item, isInTree, entity) { - var drawKeyboardFocus = !!data.showFocus && that._hasKeyboardFocus; - that._unsetFocusOnItem(isInTree); - that._selection._setFocused(entity, drawKeyboardFocus); - if (that._hasKeyboardFocus) { - that._keyboardFocusInbound = drawKeyboardFocus; - that._setFocusOnItem(entity); - } else { - that._tabManager.childFocus = (isInTree ? item : null); - } - if (entity.type !== WinJS.UI.ObjectType.groupHeader) { - that._updateFocusCache(entity.index); - if (that._updater) { - that._updater.newSelectionPivot = entity.index; - that._updater.oldSelectionPivot = -1; - } - that._selection._pivot = entity.index; - } - } - - if (data.key && - ((data.type !== WinJS.UI.ObjectType.groupHeader && this._dataSource.itemFromKey) || - (data.type === WinJS.UI.ObjectType.groupHeader && this._groupDataSource && this._groupDataSource.itemFromKey))) { - if (this.oldCurrentItemKeyFetch) { - this.oldCurrentItemKeyFetch.cancel(); - } - var dataSource = (data.type === WinJS.UI.ObjectType.groupHeader ? this._groupDataSource : this._dataSource); - this.oldCurrentItemKeyFetch = dataSource.itemFromKey(data.key).then(function (item) { - that.oldCurrentItemKeyFetch = null; - if (item) { - var element = (data.type === WinJS.UI.ObjectType.groupHeader ? that._groups.group(item.index).header : that._view.items.itemAt(item.index)); - setItemFocused(element, !!element, { type: data.type || WinJS.UI.ObjectType.item, index: item.index }); - } - }); - } else { - if (data.index !== undefined) { - var element; - if (data.type === WinJS.UI.ObjectType.groupHeader) { - var group = that._groups.group(data.index); - element = group && group.header; - } else { - element = that._view.items.itemAt(data.index); - } - setItemFocused(element, !!element, { type: data.type || WinJS.UI.ObjectType.item, index: data.index }); - } - } - } - }, - - /// - /// Gets a ZoomableView. This API supports the SemanticZoom infrastructure - /// and is not intended to be used directly from your code. - /// - zoomableView: { - get: function () { - if (!this._zoomableView) { - this._zoomableView = new ZoomableView(this); - } - - return this._zoomableView; - } - }, - - /// - /// Gets or sets whether the ListView's items can be dragged via drag and drop. - /// - /// - itemsDraggable: { - get: function () { - return this._dragSource; - }, - - set: function (value) { - if (this._dragSource !== value) { - this._dragSource = value; - this._setSwipeClass(); - } - } - }, - - /// - /// Gets or sets whether the ListView's items can be reordered within itself via drag and drop. When a ListView is marked as reorderable, its items can be dragged about inside itself, but it will not require the itemdrag events it fires to be handled. - /// - /// - itemsReorderable: { - get: function () { - return this._reorderable; - }, - - set: function (value) { - if (this._reorderable !== value) { - this._reorderable = value; - this._setSwipeClass(); - } - } - }, - - /// - /// Gets or sets the maximum number of realized items. - /// - maxDeferredItemCleanup: { - get: function () { - return this._maxDeferredItemCleanup; - }, - - set: function (value) { - this._maxDeferredItemCleanup = Math.max(0, +value || 0); - } - }, - - // Public methods - - dispose: function () { - /// - /// - /// Disposes this ListView. - /// - /// - this._dispose(); - }, - - elementFromIndex: function (itemIndex) { - /// - /// - /// Returns the DOM element that represents the item at the specified index. - /// - /// - /// The index of the item. - /// - /// - /// The DOM element that represents the specified item. - /// - /// - - return this._view.items.itemAt(itemIndex); - }, - - indexOfElement: function (element) { - /// - /// - /// Returns the index of the item that the specified DOM element displays. - /// - /// - /// The DOM element that displays the item. - /// - /// - /// The index of item that the specified DOM element displays. - /// - /// - - return this._view.items.index(element); - }, - - ensureVisible: function ListView_ensureVisible(value) { - /// - /// - /// Makes the specified item visible. The ListView scrolls to the item if needed. - /// - /// - /// The index of the ListView item or IListViewEntity to bring into view. - /// - /// - var type = WinJS.UI.ObjectType.item, - itemIndex = value; - if (+value !== value) { - type = value.type; - itemIndex = value.index; - } - this._writeProfilerMark("ensureVisible(" + type + ": " + itemIndex + "),info"); - - if (itemIndex < 0) { - return; - } - - this._raiseViewLoading(true); - - var that = this; - this._batchViewUpdates(ViewChange.realize, ScrollToPriority.high, function () { - var range; - - return that._entityInRange({ type: type, index: itemIndex }).then(function (validated) { - if (!validated.inRange) { - return { - position: 0, - direction: "left" - }; - } else { - return that._getItemOffset({ type: type, index: validated.index }).then(function (r) { - range = r; - return that._ensureFirstColumnRange(type); - }).then(function () { - range = that._correctRangeInFirstColumn(range, type); - - var viewportLength = that._getViewportLength(), - left = that._viewportScrollPosition, - right = left + viewportLength, - newPosition = that._viewportScrollPosition, - entityWidth = range.end - range.begin; - - range = that._convertFromCanvasCoordinates(range); - - var handled = false; - if (type === WinJS.UI.ObjectType.groupHeader && left <= range.begin) { - // EnsureVisible on a group where the entire header is fully visible does not - // scroll. This prevents tabbing from an item in a very large group to align - // the scroll to the header element. - var header = that._groups.group(validated.index).header; - if (header) { - var headerEnd; - var margins = WinJS.UI._getMargins(header); - if (that._horizontalLayout) { - var rtl = that._rtl(); - var headerStart = (rtl ? getOffsetRight(header) - margins.right : header.offsetLeft - margins.left); - headerEnd = headerStart + header.offsetWidth + (rtl ? margins.left : margins.right); - } else { - headerEnd = header.offsetTop + header.offsetHeight + margins.top; - } - handled = headerEnd <= right; - } - } - if (!handled) { - if (entityWidth >= right - left) { - // This item is larger than the viewport so we will just set - // the scroll position to the beginning of the item. - newPosition = range.begin; - } else { - if (range.begin < left) { - newPosition = range.begin; - } else if (range.end > right) { - newPosition = range.end - viewportLength; - } - } - } - - var direction = (newPosition < that._lastScrollPosition) ? "left" : "right"; - var max = that._viewport[that._scrollLength] - viewportLength; - newPosition = utilities._clamp(newPosition, 0, max); - - return { - position: newPosition, - direction: direction - }; - }); - } - }); - }, true); - }, - - loadMorePages: function ListView_loadMorePages() { - /// - /// - /// Loads the next set of pages if the ListView object's loadingBehavior is set to incremental. - /// - /// loadMorePages is deprecated. Invoking this function will not have any effect. Please refer to the 'ListView loading behaviors' SDK Sample for guidance on how to implement incremental load behavior. - /// - /// - /// - utilities._deprecated(WinJS.UI._strings.loadMorePagesIsDeprecated); - }, - - recalculateItemPosition: function ListView_recalculateItemPosition() { - /// - /// - /// Repositions all the visible items in the ListView to adjust for items whose sizes have changed. Use this function or forceLayout when making the ListView visible again after you set its style.display property to "none" or after style changes have been made that affect the size or position of the ListView or its items. Unlike forceLayout, this method doesn’t recreate items and it doesn’t display entrance animation. - /// - /// - this._writeProfilerMark("recalculateItemPosition,info"); - this._forceLayoutImpl(ViewChange.relayout); - }, - - forceLayout: function ListView_forceLayout() { - /// - /// - /// Forces the ListView to update its layout. Use this function or relcaculateItemPosition when making the ListView visible again after you set its style.display property to "none” or after style changes have been made that affect the size or position of the ListView or its items. - /// after you set its style.display property to "none". - /// - /// - this._writeProfilerMark("forceLayout,info"); - this._forceLayoutImpl(ViewChange.remeasure); - }, - - _entityInRange: function ListView_entityInRange(entity) { - if (entity.type === WinJS.UI.ObjectType.item) { - return this._itemsCount().then(function (itemsCount) { - var index = utilities._clamp(entity.index, 0, itemsCount - 1); - return { - inRange: index >= 0 && index < itemsCount, - index: index - }; - }); - } else { - var index = utilities._clamp(entity.index, 0, this._groups.length() - 1); - return Promise.wrap({ - inRange: index >= 0 && index < this._groups.length(), - index: index - }); - } - }, - - _forceLayoutImpl: function ListView_forceLayoutImpl(viewChange) { - var that = this; - this._versionManager.unlocked.then(function () { - that._writeProfilerMark("_forceLayoutImpl viewChange(" + viewChange + "),info"); - - that._cancelAsyncViewWork(); - that._pendingLayoutReset = true; - that._resizeViewport(); - - that._batchViewUpdates(viewChange, ScrollToPriority.low, function () { - return { - position: that._lastScrollPosition, - direction: "right" - }; - }, true, true); - }); - }, - - _supportsGroupHeaderKeyboarding: { - get: function () { - return this._groupDataSource; - } - }, - - _viewportScrollPosition: { - get: function () { - this._currentScrollPosition = this._viewport[this._scrollProperty]; - return this._currentScrollPosition; - }, - set: function (value) { - this._viewport[this._scrollProperty] = value; - this._currentScrollPosition = value; - } - }, - - _canvasStart: { - get: function () { - return this._canvasStartValue || 0; - }, - set: function (value) { - var transformX = this._horizontal() ? (this._rtl() ? -value : value) : 0, - transformY = this._horizontal() ? 0 : value; - if (value !== 0) { - this._canvas.style.transform = "translate( " + transformX + "px, " + transformY + "px)"; - } else { - this._canvas.style.transform = ""; - } - this._canvasStartValue = value; - } - }, - - /// - /// Gets or sets the position of the ListView's scrollbar. - /// - scrollPosition: { - get: function () { - //#DBG _ASSERT(this._lastScrollPosition >= 0); - return this._currentScrollPosition; - }, - set: function (newPosition) { - var that = this; - this._batchViewUpdates(ViewChange.realize, ScrollToPriority.high, function () { - return that._view.waitForValidScrollPosition(newPosition).then(function () { - var max = that._viewport[that._scrollLength] - that._getViewportLength(); - newPosition = utilities._clamp(newPosition, 0, max); - var direction = (newPosition < that._lastScrollPosition) ? "left" : "right"; - return { - position: newPosition, - direction: direction - }; - }); - }, true); - } - }, - - _setRenderer: function ListView_setRenderer(newRenderer, isGroupHeaderRenderer) { - var renderer; - if (!newRenderer) { - if (WinJS.validation) { - throw new WinJS.ErrorFromName("WinJS.UI.ListView.invalidTemplate", WinJS.UI._strings.invalidTemplate); - } - renderer = trivialHtmlRenderer; - } else if (typeof newRenderer === "function") { - renderer = newRenderer; - } else if (typeof newRenderer === "object") { - if (WinJS.validation && !newRenderer.renderItem) { - throw new WinJS.ErrorFromName("WinJS.UI.ListView.invalidTemplate", WinJS.UI._strings.invalidTemplate); - } - renderer = newRenderer.renderItem; - } - - if (renderer) { - if (isGroupHeaderRenderer) { - this._groupHeaderRenderer = renderer; - } else { - this._itemRenderer = renderer; - } - } - }, - - _renderWithoutReuse: function ListView_renderWithoutReuse(itemPromise, oldElement) { - if (oldElement) { - WinJS.Utilities._disposeElement(oldElement); - } - return this._itemRenderer(itemPromise); - }, - - _isInsertedItem: function ListView_isInsertedItem(itemPromise) { - return !!this._insertedItems[itemPromise.handle]; - }, - - _clearInsertedItems: function ListView_clearInsertedItems() { - var keys = Object.keys(this._insertedItems); - for (var i = 0, len = keys.length; i < len; i++) { - this._insertedItems[keys[i]].release(); - } - this._insertedItems = {}; - this._modifiedElements = []; - this._countDifference = 0; - }, - - // Private methods - _cancelAsyncViewWork: function (stopTreeCreation) { - this._view.stopWork(stopTreeCreation); - }, - - _updateView: function ListView_updateView() { - if (this._isZombie()) { return; } - - var that = this; - function resetCache() { - that._itemsBlockExtent = -1; - that._firstItemRange = null; - that._firstHeaderRange = null; - that._itemMargins = null; - that._headerMargins = null; - that._canvasMargins = null; - that._cachedRTL = null; - // Retrieve the values before DOM modifications occur - that._rtl(); - } - - var viewChange = this._viewChange; - this._viewChange = ViewChange.realize; - - function functorWrapper() { - that._scrollToPriority = ScrollToPriority.uninitialized; - var setScrollbarPosition = that._setScrollbarPosition; - that._setScrollbarPosition = false; - - var position = typeof that._scrollToFunctor === "number" ? { position: that._scrollToFunctor } : that._scrollToFunctor(); - return Promise.as(position).then( - function (scroll) { - scroll = scroll || {}; - if (setScrollbarPosition && +scroll.position === scroll.position) { - that._lastScrollPosition = scroll.position; - that._viewportScrollPosition = scroll.position; - } - return scroll; - }, - function (error) { - that._setScrollbarPosition |= setScrollbarPosition; - return Promise.wrapError(error); - } - ); - } - - if (viewChange === ViewChange.rebuild) { - if (this._pendingGroupWork) { - this._updateGroupWork(); - } - if (this._pendingLayoutReset) { - this._resetLayout(); - } - resetCache(); - if (!this._firstTimeDisplayed) { - this._view.reset(); - } - this._view.reload(functorWrapper, true); - this._setFocusOnItem(this._selection._getFocused()); - } else if (viewChange === ViewChange.remeasure) { - this._view.resetItems(true); - this._resetLayout(); - resetCache(); - this._view.refresh(functorWrapper); - this._setFocusOnItem(this._selection._getFocused()); - } else if (viewChange === ViewChange.relayout) { - if (this._pendingLayoutReset) { - this._resetLayout(); - resetCache(); - } - this._view.refresh(functorWrapper); - } else { - this._view.onScroll(functorWrapper); - } - }, - - _batchViewUpdates: function ListView_batchViewUpdates(viewChange, scrollToPriority, positionFunctor, setScrollbarPosition, skipFadeout) { - this._viewChange = Math.min(this._viewChange, viewChange); - - if (this._scrollToFunctor === null || scrollToPriority >= this._scrollToPriority) { - this._scrollToPriority = scrollToPriority; - this._scrollToFunctor = positionFunctor; - } - - this._setScrollbarPosition |= !!setScrollbarPosition; - - if (!this._batchingViewUpdates) { - this._raiseViewLoading(); - - var that = this; - this._batchingViewUpdatesSignal = new WinJS._Signal(); - this._batchingViewUpdates = Promise.any([this._batchingViewUpdatesSignal.promise, Scheduler.schedulePromiseHigh(null, "WinJS.UI.ListView._updateView")]).then(function () { - if (that._isZombie()) { return; } - - // If we're displaying for the first time, or there were no items visible in the view, we can skip the fade out animation - // and go straight to the refresh. _view.items._itemData.length is the most trustworthy way to find how many items are visible. - if (that._viewChange === ViewChange.rebuild && !that._firstTimeDisplayed && Object.keys(that._view.items._itemData).length !== 0 && !skipFadeout) { - return that._fadeOutViewport(); - } - }).then( - function () { - that._batchingViewUpdates = null; - that._batchingViewUpdatesSignal = null; - that._updateView(); - that._firstTimeDisplayed = false; - }, - function () { - that._batchingViewUpdates = null; - that._batchingViewUpdatesSignal = null; - } - ); - } - - return this._batchingViewUpdatesSignal; - }, - - _resetItemCanvas: function () { - // The item canvas MUST have style.position = absolute, otherwise clipping will not be done. - var tabManagerEl = this._canvas; - if (this._tabManager) { - this._tabManager.dispose(); - } - - this._tabManager = new WinJS.UI.TabContainer(tabManagerEl); - function tabManagerHandler(eventName) { - return { - name: eventName, - handler: function (eventObject) { - that["_" + eventName](eventObject); - that._mode[eventName](eventObject); - }, - capture: false - }; - } - - var itemCanvasEvents = [ - tabManagerHandler("onTabEnter"), - tabManagerHandler("onTabExit") - ]; - var that = this; - itemCanvasEvents.forEach(function (itemCanvasEvent) { - tabManagerEl.addEventListener(itemCanvasEvent.name, itemCanvasEvent.handler, false); - }); - this._tabManager.tabIndex = this._tabIndex; - }, - - _resetCanvas: function () { - if (this._disposed) { - return; - } - - // Layouts do not currently support saving the scroll position when forceLayout() is called. - // Layouts need to recreate the canvas because the tabManager is there and you don't want to - // construct 2 instances of WinJS.UI.TabContainer for the same element. - var newCanvas = document.createElement('div'); - newCanvas.className = this._canvas.className; - this._viewport.replaceChild(newCanvas, this._canvas); - this._canvas = newCanvas; - this._groupsToRemove = {}; - // We reset the itemCanvas on _resetCanvas in case a ListView client uses two separate custom layouts, and each layout - // changes different styles on the itemCanvas without resetting it. - this._canvas.appendChild(this._canvasProxy); - this._resetItemCanvas(); - }, - - _setupInternalTree: function ListView_setupInternalTree() { - - utilities.addClass(this._element, WinJS.UI._listViewClass); - utilities[this._rtl() ? "addClass" : "removeClass"](this._element, WinJS.UI._rtlListViewClass); - - this._element.innerHTML = - '
    ' + - '
    ' + - // Create a proxy element inside the canvas so that during an MSPointerDown event we can call - // msSetPointerCapture on it. This allows hover to not be passed to it which saves a large invalidation. - '
    ' + - '
    ' + - '
    ' + - '
    ' + - // The keyboard event helper is a dummy node that allows us to keep getting keyboard events when a virtualized element - // gets discarded. It has to be positioned in the center of the viewport, though, otherwise calling .focus() on it - // can move our viewport around when we don't want it moved. - // The keyboard event helper element will be skipped in the tab order if it doesn't have width+height set on it. - ''; - - this._viewport = this._element.firstElementChild; - this._canvas = this._viewport.firstElementChild; - this._canvasProxy = this._canvas.firstElementChild; - // The deleteWrapper div is used to maintain the scroll width (after delete(s)) until the animation is done - this._deleteWrapper = this._canvas.nextElementSibling; - this._keyboardEventsHelper = this._viewport.nextElementSibling.firstElementChild; - this._tabIndex = this._element.tabIndex !== undefined ? this._element.tabIndex : 0; - this._tabEventsHelper = new WinJS.UI.TabContainer(this._keyboardEventsHelper.parentNode); - this._tabEventsHelper.tabIndex = this._tabIndex; - this._resetItemCanvas(); - - this._progressBar = document.createElement("progress"); - utilities.addClass(this._progressBar, WinJS.UI._progressClass); - this._progressBar.style.position = "absolute"; - this._progressBar.max = 100; - }, - - _unsetFocusOnItem: function ListView_unsetFocusOnItem(newFocusExists) { - if (this._tabManager.childFocus) { - this._clearFocusRectangle(this._tabManager.childFocus); - } - if (this._isZombie()) { - return; - } - if (!newFocusExists) { - // _setFocusOnItem may run asynchronously so prepare the keyboardEventsHelper - // to receive focus. - if (this._tabManager.childFocus) { - this._tabManager.childFocus = null; - } - - this._keyboardEventsHelper._shouldHaveFocus = false; - this._tabEventsHelper.childFocus = this._keyboardEventsHelper; - // If the viewport has focus, leave it there. This will prevent focus from jumping - // from the viewport to the keyboardEventsHelper when scrolling with Narrator Touch. - if (document.activeElement !== this._viewport && this._hasKeyboardFocus) { - this._keyboardEventsHelper._shouldHaveFocus = true; - try { - this._keyboardEventsHelper.setActive(); - } catch (ex) { - } - } - } - this._itemFocused = false; - }, - - _setFocusOnItem: function ListView_setFocusOnItem(entity) { - this._writeProfilerMark("_setFocusOnItem,info"); - if (this._focusRequest) { - this._focusRequest.cancel(); - } - if (this._isZombie()) { - return; - } - var that = this; - var setFocusOnItemImpl = function (item) { - if (that._isZombie()) { - return; - } - that._tabEventsHelper.childFocus = null; - - if (that._tabManager.childFocus !== item) { - that._tabManager.childFocus = item; - } - that._focusRequest = null; - if (that._hasKeyboardFocus && !that._itemFocused) { - if (that._selection._keyboardFocused()) { - that._drawFocusRectangle(item); - } - //#DBG _ASSERT(that._cachedCount !== WinJS.UI._UNINITIALIZED); - // The requestItem promise just completed so _cachedCount will - // be initialized. - that._view.updateAriaForAnnouncement(item, (entity.type === WinJS.UI.ObjectType.groupHeader ? that._groups.length() : that._cachedCount)); - - // Some consumers of ListView listen for item invoked events and hide the listview when an item is clicked. - // Since keyboard interactions rely on async operations, sometimes an invoke event can be received before we get - // to item.setActive(), and the listview will be made invisible. If that happens and we call item.setActive(), an exception - // is raised for trying to focus on an invisible item. Checking visibility is non-trivial, so it's best - // just to catch the exception and ignore it. - try { - that._itemFocused = true; - item.setActive(); - } catch (error) { } - } - }; - - if (entity.type !== WinJS.UI.ObjectType.groupHeader) { - this._focusRequest = this._view.items.requestItem(entity.index).then(setFocusOnItemImpl); - } else { - this._focusRequest = this._groups.requestHeader(entity.index).then(setFocusOnItemImpl); - } - }, - - _attachEvents: function ListView_attachEvents() { - var that = this; - - function listViewHandler(eventName, caseSensitive, capture) { - return { - name: (caseSensitive ? eventName : eventName.toLowerCase()), - handler: function (eventObject) { - that["_on" + eventName](eventObject); - }, - capture: capture - }; - } - - function modeHandler(eventName, caseSensitive, capture) { - return { - capture: capture, - name: (caseSensitive ? eventName : eventName.toLowerCase()), - handler: function (eventObject) { - var currentMode = that._mode, - name = "on" + eventName; - if (!that._disposed && currentMode[name]) { - currentMode[name](eventObject); - } - } - }; - } - - function observerHandler(handlerName, attributesFilter) { - return { - handler: function (listOfChanges) { - that["_on" + handlerName](listOfChanges); - }, - filter: attributesFilter - }; - } - - // Observers for specific element attribute changes - var elementObservers = [ - observerHandler("PropertyChange", ["dir", "style", "tabindex"]) - ]; - this._cachedStyleDir = this._element.style.direction; - - elementObservers.forEach(function (elementObserver) { - new MutationObserver(elementObserver.handler).observe(that._element, { attributes: true, attributeFilter: elementObserver.filter }); - }); - - // KeyDown handler needs to be added explicitly via addEventListener instead of using attachEvent. - // If it's not added via addEventListener, the eventObject given to us on event does not have the functions stopPropagation() and preventDefault(). - var events = [ - modeHandler("PointerDown"), - modeHandler("click", false), - modeHandler("PointerUp"), - modeHandler("LostPointerCapture"), - modeHandler("MSHoldVisual", true), - modeHandler("PointerCancel", true), - modeHandler("DragStart"), - modeHandler("DragOver"), - modeHandler("DragEnter"), - modeHandler("DragLeave"), - modeHandler("Drop"), - modeHandler("ContextMenu"), - modeHandler("MSManipulationStateChanged", true, true) - ]; - events.forEach(function (eventHandler) { - that._viewport.addEventListener(eventHandler.name, eventHandler.handler, !!eventHandler.capture); - }); - - // Focus and Blur events need to be handled during the capturing phase, they do not bubble. - var elementEvents = [ - listViewHandler("Focus", false, true), - listViewHandler("Blur", false, true), - modeHandler("KeyDown"), - modeHandler("KeyUp"), - listViewHandler("MSElementResize", false, false) - ]; - elementEvents.forEach(function (eventHandler) { - that._element.addEventListener(eventHandler.name, eventHandler.handler, !!eventHandler.capture); - }); - - var viewportEvents = [ - listViewHandler("MSManipulationStateChanged", true), - listViewHandler("Scroll") - ]; - viewportEvents.forEach(function (viewportEvent) { - that._viewport.addEventListener(viewportEvent.name, viewportEvent.handler, false); - }); - - this._keyboardEventsHelper.parentNode.addEventListener("onTabEnter", this._onTabEnter.bind(this), false); - this._keyboardEventsHelper.parentNode.addEventListener("onTabExit", this._onTabExit.bind(this), false); - }, - - _updateItemsManager: function ListView_updateItemsManager() { - var that = this, - notificationHandler = { - // Following methods are used by ItemsManager - beginNotifications: function ListView_beginNotifications() { - }, - - changed: function ListView_changed(newItem, oldItem, oldItemObject) { - if (that._ifZombieDispose()) { return; } - - that._createUpdater(); - - //#DBG _ASSERT(utilities._isDOMElement(newItem)); - - var elementInfo = that._updater.elements[oldItem.uniqueID]; - if (elementInfo) { - var selected = that.selection._isIncluded(elementInfo.index); - if (selected) { - that._updater.updateDrag = true; - } - - if (oldItem !== newItem) { - if (that._tabManager.childFocus === oldItem || that._updater.newFocusedItem === oldItem) { - that._updater.newFocusedItem = newItem; - that._tabManager.childFocus = null; - } - - if (elementInfo.itemBox) { - utilities.addClass(newItem, WinJS.UI._itemClass); - that._setupAriaSelectionObserver(newItem); - - var next = oldItem.nextElementSibling; - elementInfo.itemBox.removeChild(oldItem); - elementInfo.itemBox.insertBefore(newItem, next); - } - - that._setAriaSelected(newItem, selected); - that._view.items.setItemAt(elementInfo.newIndex, { - element: newItem, - itemBox: elementInfo.itemBox, - container: elementInfo.container, - itemsManagerRecord: elementInfo.itemsManagerRecord - }); - delete that._updater.elements[oldItem.uniqueID]; - WinJS.Utilities._disposeElement(oldItem); - that._updater.elements[newItem.uniqueID] = { - item: newItem, - container: elementInfo.container, - itemBox: elementInfo.itemBox, - index: elementInfo.index, - newIndex: elementInfo.newIndex, - itemsManagerRecord: elementInfo.itemsManagerRecord - }; - } else if (elementInfo.itemBox && elementInfo.container) { - WinJS.UI._ItemEventsHandler.renderSelection(elementInfo.itemBox, newItem, selected, true); - utilities[selected ? "addClass" : "removeClass"](elementInfo.container, WinJS.UI._selectedClass); - } - that._updater.changed = true; - } - for (var i = 0, len = that._notificationHandlers.length; i < len; i++) { - that._notificationHandlers[i].changed(newItem, oldItem); - } - that._writeProfilerMark("changed,info"); - }, - - removed: function ListView_removed(item, mirage, handle) { - if (that._ifZombieDispose()) { return; } - - that._createUpdater(); - - function removeFromSelection(index) { - that._updater.updateDrag = true; - if (that._currentMode()._dragging && that._currentMode()._draggingUnselectedItem && that._currentMode()._dragInfo._isIncluded(index)) { - that._updater.newDragInfo = new WinJS.UI._Selection(that, []); - } - - var firstRange = that._updater.selectionFirst[index], - lastRange = that._updater.selectionLast[index], - range = firstRange || lastRange; - - if (range) { - delete that._updater.selectionFirst[range.oldFirstIndex]; - delete that._updater.selectionLast[range.oldLastIndex]; - that._updater.selectionChanged = true; - } - } - - var insertedItem = that._insertedItems[handle]; - if (insertedItem) { - delete that._insertedItems[handle]; - } - - var index; - if (item) { - var elementInfo = that._updater.elements[item.uniqueID], - itemObject = that._itemsManager.itemObject(item); - - if (itemObject) { - that._groupFocusCache.deleteItem(itemObject.key); - } - - if (elementInfo) { - index = elementInfo.index; - - // We track removed elements for animation purposes (layout - // component consumes this). - // - if (elementInfo.itemBox) { - that._updater.removed.push({ - index: index, - itemBox: elementInfo.itemBox - }); - } - that._updater.deletesCount++; - - // The view can't access the data from the itemsManager - // anymore, so we need to flag the itemData that it - // has been removed. - // - var itemData = that._view.items.itemDataAt(index); - itemData.removed = true; - - /*#DBG - delete elementInfo.itemsManagerRecord.updater; - #DBG*/ - delete that._updater.elements[item.uniqueID]; - } else { - index = itemObject && itemObject.index; - } - - if (that._updater.oldFocus.type !== WinJS.UI.ObjectType.groupHeader && that._updater.oldFocus.index === index) { - that._updater.newFocus.index = index; // If index is too high, it'll be fixed in endNotifications - that._updater.focusedItemRemoved = true; - } - - removeFromSelection(index); - } else { - index = that._updater.selectionHandles[handle]; - if (index === +index) { - removeFromSelection(index); - } - } - that._writeProfilerMark("removed(" + index + "),info"); - - that._updater.changed = true; - }, - - updateAffectedRange: function ListView_updateAffectedRange(newerRange) { - that._itemsCount().then(function (count) { - // When we receive insertion notifications before all of the containers have - // been created and the affected range is beyond the container range, the - // affected range indices will not correspond to the indices of the containers - // created by updateContainers. In this case, start the affected range at the end - // of the containers so that the affected range includes any containers that get - // appended due to this batch of notifications. - var containerCount = that._view.containers ? that._view.containers.length : 0; - newerRange.start = Math.min(newerRange.start, containerCount); - - that._affectedRange.add(newerRange, count); - }); - that._createUpdater(); - that._updater.changed = true; - }, - - indexChanged: function ListView_indexChanged(item, newIndex, oldIndex) { - // We should receive at most one indexChanged notification per oldIndex - // per notification cycle. - if (that._ifZombieDispose()) { return; } - - that._createUpdater(); - - if (item) { - var itemObject = that._itemsManager.itemObject(item); - if (itemObject) { - that._groupFocusCache.updateItemIndex(itemObject.key, newIndex); - } - - var elementInfo = that._updater.elements[item.uniqueID]; - if (elementInfo) { - elementInfo.newIndex = newIndex; - that._updater.changed = true; - } - that._updater.itemsMoved = true; - } - if (that._currentMode()._dragging && that._currentMode()._draggingUnselectedItem && that._currentMode()._dragInfo._isIncluded(oldIndex)) { - that._updater.newDragInfo = new WinJS.UI._Selection(that, [{ firstIndex: newIndex, lastIndex: newIndex }]); - that._updater.updateDrag = true; - } - - if (that._updater.oldFocus.type !== WinJS.UI.ObjectType.groupHeader && that._updater.oldFocus.index === oldIndex) { - that._updater.newFocus.index = newIndex; - that._updater.changed = true; - } - - if (that._updater.oldSelectionPivot === oldIndex) { - that._updater.newSelectionPivot = newIndex; - that._updater.changed = true; - } - - var range = that._updater.selectionFirst[oldIndex]; - if (range) { - range.newFirstIndex = newIndex; - that._updater.changed = true; - that._updater.updateDrag = true; - } - range = that._updater.selectionLast[oldIndex]; - if (range) { - range.newLastIndex = newIndex; - that._updater.changed = true; - that._updater.updateDrag = true; - } - }, - - endNotifications: function ListView_endNotifications() { - that._update(); - }, - - inserted: function ListView_inserted(itemPromise) { - if (that._ifZombieDispose()) { return; } - that._writeProfilerMark("inserted,info"); - - that._createUpdater(); - that._updater.changed = true; - itemPromise.retain(); - that._updater.insertsCount++; - that._insertedItems[itemPromise.handle] = itemPromise; - }, - - moved: function ListView_moved(item, previous, next, itemPromise) { - if (that._ifZombieDispose()) { return; } - - that._createUpdater(); - - that._updater.movesCount++; - if (item) { - that._updater.itemsMoved = true; - - var elementInfo = that._updater.elements[item.uniqueID]; - if (elementInfo) { - elementInfo.moved = true; - } - } - - var index = that._updater.selectionHandles[itemPromise.handle]; - if (index === +index) { - that._updater.updateDrag = true; - - var firstRange = that._updater.selectionFirst[index], - lastRange = that._updater.selectionLast[index], - range = firstRange || lastRange; - - if (range && range.oldFirstIndex !== range.oldLastIndex) { - delete that._updater.selectionFirst[range.oldFirstIndex]; - delete that._updater.selectionLast[range.oldLastIndex]; - that._updater.selectionChanged = true; - that._updater.changed = true; - } - } - that._writeProfilerMark("moved(" + index + "),info"); - }, - - countChanged: function ListView_countChanged(newCount, oldCount) { - if (that._ifZombieDispose()) { return; } - that._writeProfilerMark("countChanged(" + newCount + "),info"); - - //#DBG _ASSERT(newCount !== undefined); - that._cachedCount = newCount; - that._createUpdater(); - - if ((that._view.lastIndexDisplayed + 1) === oldCount) { - that._updater.changed = true; - } - - that._updater.countDifference += newCount - oldCount; - }, - - reload: function ListView_reload() { - if (that._ifZombieDispose()) { - return; - } - that._writeProfilerMark("reload,info"); - - that._processReload(); - } - }; - - function statusChanged(eventObject) { - if (eventObject.detail === thisWinUI.DataSourceStatus.failure) { - that.itemDataSource = null; - that.groupDataSource = null; - } - } - - if (this._versionManager) { - this._versionManager._dispose(); - } - - this._versionManager = new WinJS.UI._VersionManager(); - this._updater = null; - - var ranges = this._selection.getRanges(); - this._selection._selected.clear(); - - if (this._itemsManager) { - - if (this._itemsManager.dataSource && this._itemsManager.dataSource.removeEventListener) { - this._itemsManager.dataSource.removeEventListener("statuschanged", statusChanged, false); - } - - this._clearInsertedItems(); - this._itemsManager.release(); - } - - if (this._itemsCountPromise) { - this._itemsCountPromise.cancel(); - this._itemsCountPromise = null; - } - this._cachedCount = WinJS.UI._UNINITIALIZED; - - this._itemsManager = thisWinUI._createItemsManager( - this._dataSource, - this._renderWithoutReuse.bind(this), - notificationHandler, - { - ownerElement: this._element, - versionManager: this._versionManager, - indexInView: function (index) { - return (index >= that.indexOfFirstVisible && index <= that.indexOfLastVisible); - }, - viewCallsReady: true, - profilerId: this._id - }); - - if (this._dataSource.addEventListener) { - this._dataSource.addEventListener("statuschanged", statusChanged, false); - } - - this._selection._selected.set(ranges); - }, - - _processReload: function () { - this._affectedRange.addAll(); - - // Inform scroll view that a realization pass is coming so that it doesn't restart the - // realization pass itself. - this._cancelAsyncViewWork(true); - if (this._currentMode()._dragging) { - this._currentMode()._clearDragProperties(); - } - - this._groupFocusCache.clear(); - this._selection._reset(); - this._updateItemsManager(); - this._pendingLayoutReset = true; - this._batchViewUpdates(ViewChange.rebuild, ScrollToPriority.low, this.scrollPosition); - }, - - _createUpdater: function ListView_createUpdater() { - if (!this._updater) { - if (this.itemDataSource instanceof WinJS.UI.VirtualizedDataSource) { - // VDS doesn't support the _updateAffectedRange notification so assume - // that everything needs to be relaid out. - this._affectedRange.addAll(); - } - this._versionManager.beginUpdating(); - - // Inform scroll view that a realization pass is coming so that it doesn't restart the - // realization pass itself. - this._cancelAsyncViewWork(); - - var updater = { - changed: false, - elements: {}, - selectionFirst: {}, - selectionLast: {}, - selectionHandles: {}, - oldSelectionPivot: { type: WinJS.UI.ObjectType.item, index: WinJS.UI._INVALID_INDEX }, - newSelectionPivot: { type: WinJS.UI.ObjectType.item, index: WinJS.UI._INVALID_INDEX }, - removed: [], - selectionChanged: false, - oldFocus: { type: WinJS.UI.ObjectType.item, index: WinJS.UI._INVALID_INDEX }, - newFocus: { type: WinJS.UI.ObjectType.item, index: WinJS.UI._INVALID_INDEX }, - hadKeyboardFocus: this._hasKeyboardFocus, - itemsMoved: false, - lastVisible: this.indexOfLastVisible, - updateDrag: false, - movesCount: 0, - insertsCount: 0, - deletesCount: 0, - countDifference: 0 - }; - - this._view.items.each(function (index, item, itemData) { - /*#DBG - if (itemData.itemsManagerRecord.released) { - throw "ACK! found released data in items collection"; - } - itemData.itemsManagerRecord.updater = updater; - #DBG*/ - updater.elements[item.uniqueID] = { - item: item, - container: itemData.container, - itemBox: itemData.itemBox, - index: index, - newIndex: index, - itemsManagerRecord: itemData.itemsManagerRecord, - detached: itemData.detached - }; - }); - - var selection = this._selection._selected._ranges; - for (var i = 0, len = selection.length; i < len; i++) { - var range = selection[i]; - var newRange = { - newFirstIndex: selection[i].firstIndex, - oldFirstIndex: selection[i].firstIndex, - newLastIndex: selection[i].lastIndex, - oldLastIndex: selection[i].lastIndex - }; - updater.selectionFirst[newRange.oldFirstIndex] = newRange; - updater.selectionLast[newRange.oldLastIndex] = newRange; - updater.selectionHandles[range.firstPromise.handle] = newRange.oldFirstIndex; - updater.selectionHandles[range.lastPromise.handle] = newRange.oldLastIndex; - } - updater.oldSelectionPivot = this._selection._pivot; - updater.newSelectionPivot = updater.oldSelectionPivot; - updater.oldFocus = this._selection._getFocused(); - updater.newFocus = this._selection._getFocused(); - - this._updater = updater; - } - }, - - _synchronize: function ListView_synchronize() { - var updater = this._updater; - this._updater = null; - var groupsChanged = this._groupsChanged; - this._groupsChanged = false; - - /*#DBG - if (updater) { - for (i in updater.elements) { - if (updater.elements.hasOwnProperty(i)) { - var elementInfo = updater.elements[i]; - delete elementInfo.itemsManagerRecord.updater; - } - } - } - #DBG*/ - - this._countDifference = this._countDifference || 0; - - if (updater && updater.changed) { - if (updater.itemsMoved) { - this._layout.itemsMoved && this._layout.itemsMoved(); - } - if (updater.removed.length) { - this._layout.itemsRemoved && this._layout.itemsRemoved(updater.removed.map(function (node) { - return node.itemBox; - })); - } - - if (updater.itemsMoved || updater.removed.length || Object.keys(this._insertedItems).length) { - this._layout.setupAnimations && this._layout.setupAnimations(); - } - - if (this._currentMode().onDataChanged) { - this._currentMode().onDataChanged(); - } - - var newSelection = []; - for (var i in updater.selectionFirst) { - if (updater.selectionFirst.hasOwnProperty(i)) { - var range = updater.selectionFirst[i]; - updater.selectionChanged = updater.selectionChanged || ((range.newLastIndex - range.newFirstIndex) != (range.oldLastIndex - range.oldFirstIndex)); - if (range.newFirstIndex <= range.newLastIndex) { - newSelection.push({ - firstIndex: range.newFirstIndex, - lastIndex: range.newLastIndex - }); - } - } - } - - if (updater.selectionChanged) { - var newSelectionItems = new WinJS.UI._Selection(this, newSelection); - - // We do not allow listeners to cancel the selection - // change because the cancellation would also have to - // prevent the deletion. - this._selection._fireSelectionChanging(newSelectionItems); - this._selection._selected.set(newSelection); - this._selection._fireSelectionChanged(); - newSelectionItems.clear(); - } else { - this._selection._selected.set(newSelection); - } - this._selection._updateCount(this._cachedCount); - updater.newSelectionPivot = Math.min(this._cachedCount - 1, updater.newSelectionPivot); - this._selection._pivot = (updater.newSelectionPivot >= 0 ? updater.newSelectionPivot : WinJS.UI._INVALID_INDEX); - - if (updater.newFocus.type !== WinJS.UI.ObjectType.groupHeader) { - updater.newFocus.index = Math.max(0, Math.min(this._cachedCount - 1, updater.newFocus.index)); - } - this._selection._setFocused(updater.newFocus, this._selection._keyboardFocused()); - - // If there are 2 edits before layoutAnimations runs we need to merge the 2 groups of modified elements. - // For example: - // If you start with A, B, C and add item Z to the beginning you will have - // [ -1 -> 0, 0 -> 1, 1 -> 2, 2 -> 3] - // However before layout is called an insert of Y to the beginning also happens you should get - // [ -1 -> 0, -1 -> 1, 0 -> 2, 1 -> 3, 2 -> 4] - var previousModifiedElements = this._modifiedElements || []; - var previousModifiedElementsHash = {}; - this._modifiedElements = []; - this._countDifference += updater.countDifference; - - for (i = 0; i < previousModifiedElements.length; i++) { - var modifiedElement = previousModifiedElements[i]; - if (modifiedElement.newIndex === -1) { - this._modifiedElements.push(modifiedElement); - } else { - previousModifiedElementsHash[modifiedElement.newIndex] = modifiedElement; - } - } - - for (i = 0; i < updater.removed.length; i++) { - var removed = updater.removed[i]; - var modifiedElement = previousModifiedElementsHash[removed.index]; - if (modifiedElement) { - delete previousModifiedElementsHash[removed.index]; - } else { - modifiedElement = { - oldIndex: removed.index - }; - } - modifiedElement.newIndex = -1; - if (!modifiedElement._removalHandled) { - modifiedElement._itemBox = removed.itemBox; - } - this._modifiedElements.push(modifiedElement); - } - - var insertedKeys = Object.keys(this._insertedItems); - for (i = 0; i < insertedKeys.length; i++) { - this._modifiedElements.push({ - oldIndex: -1, - newIndex: this._insertedItems[insertedKeys[i]].index - }); - } - - this._writeProfilerMark("_synchronize:update_modifiedElements,StartTM"); - var newItems = {}; - for (i in updater.elements) { - if (updater.elements.hasOwnProperty(i)) { - var elementInfo = updater.elements[i]; - /*#DBG - if (elementInfo.itemsManagerRecord.released) { - throw "ACK! attempt to put released record into list of items for ScrollView"; - } - #DBG*/ - newItems[elementInfo.newIndex] = { - element: elementInfo.item, - container: elementInfo.container, - itemBox: elementInfo.itemBox, - itemsManagerRecord: elementInfo.itemsManagerRecord, - detached: elementInfo.detached - }; - - var modifiedElement = previousModifiedElementsHash[elementInfo.index]; - if (modifiedElement) { - delete previousModifiedElementsHash[elementInfo.index]; - modifiedElement.newIndex = elementInfo.newIndex; - } else { - modifiedElement = { - oldIndex: elementInfo.index, - newIndex: elementInfo.newIndex - }; - } - modifiedElement.moved = elementInfo.moved; - this._modifiedElements.push(modifiedElement); - } - } - this._writeProfilerMark("_synchronize:update_modifiedElements,StopTM"); - - var previousIndices = Object.keys(previousModifiedElementsHash); - for (i = 0; i < previousIndices.length; i++) { - var key = previousIndices[i]; - var modifiedElement = previousModifiedElementsHash[key]; - if (modifiedElement.oldIndex !== -1) { - this._modifiedElements.push(modifiedElement); - } - } - - this._view.items._itemData = newItems; - if (updater.updateDrag && this._currentMode()._dragging) { - if (!this._currentMode()._draggingUnselectedItem) { - this._currentMode()._dragInfo = this._selection; - } else if (updater.newDragInfo) { - this._currentMode()._dragInfo = updater.newDragInfo; - } - this._currentMode().fireDragUpdateEvent(); - } - - // If the focused item is removed, or the item we're trying to focus on has been moved before we can focus on it, - // we need to update our focus request to get the item from the appropriate index. - if (updater.focusedItemRemoved || (this._focusRequest && (updater.oldFocus.index !== updater.newFocus.index) || (updater.oldFocus.type !== updater.newFocus.type))) { - this._itemFocused = false; - this._setFocusOnItem(this._selection._getFocused()); - } else if (updater.newFocusedItem) { - // We need to restore the value of _hasKeyboardFocus because a changed item - // gets removed from the DOM at the time of the notification. If the item - // had focus at that time, then our value of _hasKeyboardFocus will have changed. - this._hasKeyboardFocus = updater.hadKeyboardFocus; - this._itemFocused = false; - this._setFocusOnItem(this._selection._getFocused()); - } - - var that = this; - return this._groups.synchronizeGroups().then(function () { - if (updater.newFocus.type === WinJS.UI.ObjectType.groupHeader) { - updater.newFocus.index = Math.min(that._groups.length() - 1, updater.newFocus.index); - - if (updater.newFocus.index < 0) { - // An empty listview has currentFocus = item 0 - updater.newFocus = { type: WinJS.UI.ObjectType.item, index: 0 }; - } - that._selection._setFocused(updater.newFocus, that._selection._keyboardFocused()); - } - - that._versionManager.endUpdating(); - if (updater.deletesCount > 0) { - that._updateDeleteWrapperSize(); - } - - return that._view.updateTree(that._cachedCount, that._countDifference, that._modifiedElements); - }).then(function () { - return that._lastScrollPosition; - }); - } else { - this._countDifference += updater ? updater.countDifference : 0; - - var that = this; - return this._groups.synchronizeGroups().then(function ListView_synchronizeGroups_success_groupsChanged() { - updater && that._versionManager.endUpdating(); - return that._view.updateTree(that._cachedCount, that._countDifference, that._modifiedElements); - }).then(function () { - return that.scrollPosition; - }); - } - }, - - _updateDeleteWrapperSize: function ListView_updateDeleteWrapperSize(clear) { - var sizeProperty = this._horizontal() ? "width" : "height"; - this._deleteWrapper.style["min-" + sizeProperty] = (clear ? 0 : this.scrollPosition + this._getViewportSize()[sizeProperty]) + "px"; - }, - - _verifyRealizationNeededForChange: function ListView_skipRealization() { - // If the updater indicates that only deletes occurred, and we have not lost a viewport full of items, - // we skip realizing all the items and appending new ones until other action causes a full realize (e.g. scrolling). - // - var skipRealization = false; - var totalInViewport = (this._view.lastIndexDisplayed || 0) - (this._view.firstIndexDisplayed || 0); - var deletesOnly = this._updater && this._updater.movesCount === 0 && this._updater.insertsCount === 0 && this._updater.deletesCount > 0 && (this._updater.deletesCount === Math.abs(this._updater.countDifference)); - if (deletesOnly && this._updater.elements) { - // Verify that the indices of the elements in the updater are within the valid range - var elementsKeys = Object.keys(this._updater.elements); - for (var i = 0, len = elementsKeys.length; i < len; i++) { - var element = this._updater.elements[elementsKeys[i]]; - var delta = element.index - element.newIndex; - if (delta < 0 || delta > this._updater.deletesCount) { - deletesOnly = false; - break; - } - } - } - this._view.deletesWithoutRealize = this._view.deletesWithoutRealize || 0; - - if (deletesOnly && - (this._view.lastIndexDisplayed < this._view.end - totalInViewport) && - (this._updater.deletesCount + this._view.deletesWithoutRealize) < totalInViewport) { - - skipRealization = true; - this._view.deletesWithoutRealize += Math.abs(this._updater.countDifference); - this._writeProfilerMark("skipping realization on delete,info"); - } else { - this._view.deletesWithoutRealize = 0; - } - this._view._setSkipRealizationForChange(skipRealization); - }, - - _update: function ListView_update() { - this._writeProfilerMark("update,StartTM"); - if (this._ifZombieDispose()) { return; } - - this._updateJob = null; - - var that = this; - if (this._versionManager.noOutstandingNotifications) { - if (this._updater || this._groupsChanged) { - this._cancelAsyncViewWork(); - this._verifyRealizationNeededForChange(); - this._synchronize().then(function (scrollbarPos) { - that._writeProfilerMark("update,StopTM"); - that._batchViewUpdates(ViewChange.relayout, ScrollToPriority.low, scrollbarPos).complete(); - }); - } else { - // Even if nothing important changed we need to restart aria work if it was canceled. - this._batchViewUpdates(ViewChange.relayout, ScrollToPriority.low, this._lastScrollPosition).complete(); - } - } - }, - - _scheduleUpdate: function ListView_scheduleUpdate() { - if (!this._updateJob) { - var that = this; - // Batch calls to _scheduleUpdate - this._updateJob = Scheduler.schedulePromiseHigh(null, "WinJS.UI.ListView._update").then(function () { - if (that._updateJob) { - that._update(); - } - }); - - this._raiseViewLoading(); - } - }, - - _createGroupsContainer: function () { - if (this._groups) { - this._groups.cleanUp(); - } - - if (this._groupDataSource) { - this._groups = new WinJS.UI._UnvirtualizedGroupsContainer(this, this._groupDataSource); - } else { - this._groups = new WinJS.UI._NoGroups(this); - } - }, - - _createLayoutSite: function () { - var that = this; - return Object.create({ - invalidateLayout: function () { - that._pendingLayoutReset = true; - var orientationChanged = (that._layout.orientation === "horizontal") !== that._horizontalLayout; - that._affectedRange.addAll(); - that._batchViewUpdates(ViewChange.rebuild, ScrollToPriority.low, orientationChanged ? 0 : that.scrollPosition, false, true); - }, - itemFromIndex: function (itemIndex) { - return that._itemsManager._itemPromiseAtIndex(itemIndex); - }, - groupFromIndex: function (groupIndex) { - if (that._groupsEnabled()) { - return groupIndex < that._groups.length() ? that._groups.group(groupIndex).userData : null; - } else { - return { key: "-1" }; - } - }, - groupIndexFromItemIndex: function (itemIndex) { - // If itemIndex < 0, returns 0. If itemIndex is larger than the - // biggest item index, returns the last group index. - itemIndex = Math.max(0, itemIndex); - return that._groups.groupFromItem(itemIndex); - }, - renderItem: function (itemPromise) { - return WinJS.Promise._cancelBlocker(that._itemsManager._itemFromItemPromise(itemPromise)).then(function (element) { - if (element) { - var record = that._itemsManager._recordFromElement(element); - if (record.pendingReady) { - record.pendingReady(); - } - - element = element.cloneNode(true); - - utilities.addClass(element, WinJS.UI._itemClass); - - var itemBox = document.createElement("div"); - utilities.addClass(itemBox, thisWinUI._itemBoxClass); - itemBox.appendChild(element); - - var container = document.createElement("div"); - utilities.addClass(container, thisWinUI._containerClass); - container.appendChild(itemBox); - - return container; - } else { - return WinJS.Promise.cancel; - } - }); - }, - renderHeader: function (group) { - var rendered = WinJS.UI._normalizeRendererReturn(that.groupHeaderTemplate(Promise.wrap(group))); - return rendered.then(function (headerRecord) { - utilities.addClass(headerRecord.element, thisWinUI._headerClass); - var container = document.createElement("div"); - utilities.addClass(container, thisWinUI._headerContainerClass); - container.appendChild(headerRecord.element); - return container; - }); - }, - readyToMeasure: function () { - that._getViewportLength(); - that._getCanvasMargins(); - }, - _isZombie: function () { - return that._isZombie(); - }, - _writeProfilerMark: function (text) { - that._writeProfilerMark(text); - } - }, { - _itemsManager: { - enumerable: true, - get: function () { - return that._itemsManager; - } - }, - rtl: { - enumerable: true, - get: function () { - return that._rtl(); - } - }, - surface: { - enumerable: true, - get: function () { - return that._canvas; - } - }, - viewport: { - enumerable: true, - get: function () { - return that._viewport; - } - }, - scrollbarPos: { - enumerable: true, - get: function () { - return that.scrollPosition; - } - }, - viewportSize: { - enumerable: true, - get: function () { - return that._getViewportSize(); - } - }, - loadingBehavior: { - enumerable: true, - get: function () { - return that.loadingBehavior; - } - }, - animationsDisabled: { - enumerable: true, - get: function () { - return that._animationsDisabled(); - } - }, - tree: { - enumerable: true, - get: function () { - return that._view.tree; - } - }, - realizedRange: { - enumerable: true, - get: function () { - return { - firstPixel: Math.max(0, that.scrollPosition - 2 * that._getViewportLength()), - lastPixel: that.scrollPosition + 3 * that._getViewportLength() - 1 - } - } - }, - visibleRange: { - enumerable: true, - get: function () { - return { - firstPixel: that.scrollPosition, - lastPixel: that.scrollPosition + that._getViewportLength() - 1 - } - } - }, - itemCount: { - enumerable: true, - get: function () { - return that._itemsCount(); - } - }, - groupCount: { - enumerable: true, - get: function () { - return that._groups.length(); - } - } - }); - }, - - _initializeLayout: function () { - this._affectedRange.addAll(); - var layoutSite = this._createLayoutSite(); - this._layout.initialize(layoutSite, this._groupsEnabled()); - return this._layout.orientation === "horizontal"; - }, - - _resetLayoutOrientation: function ListView_resetLayoutOrientation(resetScrollPosition) { - if (this._horizontalLayout) { - this._startProperty = "left"; - this._scrollProperty = "scrollLeft"; - this._scrollLength = "scrollWidth"; - this._deleteWrapper.style.minHeight = ""; - utilities.addClass(this._viewport, WinJS.UI._horizontalClass); - utilities.removeClass(this._viewport, WinJS.UI._verticalClass); - if (resetScrollPosition) { - this._viewport.scrollTop = 0; - } - } else { - this._startProperty = "top"; - this._scrollProperty = "scrollTop"; - this._scrollLength = "scrollHeight"; - this._deleteWrapper.style.minWidth = ""; - utilities.addClass(this._viewport, WinJS.UI._verticalClass); - utilities.removeClass(this._viewport, WinJS.UI._horizontalClass); - if (resetScrollPosition) { - this._viewport.scrollLeft = 0; - } - } - }, - - _resetLayout: function ListView_resetLayout() { - this._pendingLayoutReset = false; - this._affectedRange.addAll(); - if (this._layout) { - this._layout.uninitialize(); - this._horizontalLayout = this._initializeLayout(); - this._resetLayoutOrientation(); - } - }, - - _updateLayout: function ListView_updateLayout(layoutObject) { - var hadPreviousLayout = false; - if (this._layout) { - // The old layout is reset here in case it was in the middle of animating when the layout got changed. Reset - // will cancel out the animations. - this._cancelAsyncViewWork(true); - this._layout.uninitialize(); - hadPreviousLayout = true; - } - - var layoutImpl; - if (layoutObject && typeof layoutObject.type === "function") { - var LayoutCtor = requireSupportedForProcessing(layoutObject.type); - layoutImpl = new LayoutCtor(layoutObject); - } else if (layoutObject && (layoutObject.initialize)) { - layoutImpl = layoutObject; - } else { - layoutImpl = new WinJS.UI.GridLayout(layoutObject); - } - - hadPreviousLayout && this._resetCanvas(); - - this._layoutImpl = layoutImpl; - this._layout = new WinJS.UI._LayoutWrapper(layoutImpl); - - hadPreviousLayout && this._unsetFocusOnItem(); - this._setFocusOnItem({ type: WinJS.UI.ObjectType.item, index: 0 }); - this._selection._setFocused({ type: WinJS.UI.ObjectType.item, index: 0 }); - - this._horizontalLayout = this._initializeLayout(); - this._resetLayoutOrientation(hadPreviousLayout); - - if (hadPreviousLayout) { - this._canvas.style.width = this._canvas.style.height = ""; - } - }, - - _currentMode: function ListView_currentMode() { - return this._mode; - }, - - _setSwipeClass: function ListView_setSwipeClass() { - // We apply an -ms-touch-action style to block panning and swiping from occurring at the same time. It is - // possible to pan in the margins between items and on lists without the swipe ability. - if ((this._currentMode() instanceof WinJS.UI._SelectionMode && this._selectionAllowed() && this._swipeBehavior === WinJS.UI.SwipeBehavior.select) || - this._dragSource || this._reorderable) { - this._swipeable = true; - utilities.addClass(this._element, WinJS.UI._swipeableClass); - } else { - this._swipeable = false; - utilities.removeClass(this._element, WinJS.UI._swipeableClass); - } - var dragEnabled = (this.itemsDraggable || this.itemsReorderable), - swipeSelectEnabled = (this._selectionAllowed() && this._swipeBehavior === WinJS.UI.SwipeBehavior.select), - swipeEnabled = this._swipeable; - - this._view.items.each(function (index, item, itemData) { - if (itemData.itemBox) { - var dragDisabledOnItem = utilities.hasClass(item, WinJS.UI._nonDraggableClass), - selectionDisabledOnItem = utilities.hasClass(item, WinJS.UI._nonSelectableClass), - nonSwipeable = utilities.hasClass(itemData.itemBox, WinJS.UI._nonSwipeableClass); - itemData.itemBox.draggable = (dragEnabled && !dragDisabledOnItem); - if (!swipeEnabled && nonSwipeable) { - utilities.removeClass(itemData.itemBox, WinJS.UI._nonSwipeableClass); - } else if (swipeEnabled) { - var makeNonSwipeable = (dragEnabled && !swipeSelectEnabled && dragDisabledOnItem) || - (swipeSelectEnabled && !dragEnabled && selectionDisabledOnItem) || - (dragDisabledOnItem && selectionDisabledOnItem); - if (makeNonSwipeable && !nonSwipeable) { - utilities.addClass(itemData.itemBox, WinJS.UI._nonSwipeableClass); - } else if (!makeNonSwipeable && nonSwipeable) { - utilities.removeClass(itemData.itemBox, WinJS.UI._nonSwipeableClass); - } - } - } - }); - }, - - _resizeViewport: function ListView_resizeViewport() { - this._viewportWidth = WinJS.UI._UNINITIALIZED; - this._viewportHeight = WinJS.UI._UNINITIALIZED; - }, - - _onMSElementResize: function ListView_onResize() { - this._writeProfilerMark("_onMSElementResize,info"); - Scheduler.schedule(function () { - if (this._isZombie()) { return; } - // If these values are uninitialized there is already a realization pass pending. - if (this._viewportWidth !== WinJS.UI._UNINITIALIZED && this._viewportHeight !== WinJS.UI._UNINITIALIZED) { - var newWidth = this._element.offsetWidth, - newHeight = this._element.offsetHeight; - if ((this._previousWidth !== newWidth) || (this._previousHeight !== newHeight)) { - - this._writeProfilerMark("resize (" + this._previousWidth + "x" + this._previousHeight + ") => (" + newWidth + "x" + newHeight + "),info"); - - this._previousWidth = newWidth; - this._previousHeight = newHeight; - - this._resizeViewport(); - - var that = this; - this._affectedRange.addAll(); - this._batchViewUpdates(ViewChange.relayout, ScrollToPriority.low, function () { - return { - position: that.scrollPosition, - direction: "right" - }; - }); - } - } - }, Scheduler.Priority.max, this, "WinJS.UI.ListView._onMSElementResize"); - }, - - _onFocus: function ListView_onFocus(event) { - this._hasKeyboardFocus = true; - var that = this; - function moveFocusToItem(keyboardFocused) { - that._changeFocus(that._selection._getFocused(), true, false, false, keyboardFocused); - } - // The keyboardEventsHelper object can get focus through three ways: We give it focus explicitly, in which case _shouldHaveFocus will be true, - // or the item that should be focused isn't in the viewport, so keyboard focus could only go to our helper. The third way happens when - // focus was already on the keyboard helper and someone alt tabbed away from and eventually back to the app. In the second case, we want to navigate - // back to the focused item via changeFocus(). In the third case, we don't want to move focus to a real item. We differentiate between cases two and three - // by checking if the flag _keyboardFocusInbound is true. It'll be set to true when the tab manager notifies us about the user pressing tab - // to move focus into the listview. - if (event.srcElement === this._keyboardEventsHelper) { - if (!this._keyboardEventsHelper._shouldHaveFocus && this._keyboardFocusInbound) { - moveFocusToItem(true); - } else { - this._keyboardEventsHelper._shouldHaveFocus = false; - } - } else if (event.srcElement === this._element) { - // If someone explicitly calls .focus() on the listview element, we need to route focus to the item that should be focused - moveFocusToItem(); - } else { - if (this._mode.inboundFocusHandled) { - this._mode.inboundFocusHandled = false; - return - }; - - this._tabEventsHelper.childFocus = null; - // In the event that .focus() is explicitly called on an element, we need to figure out what item got focus and set our state appropriately. - var items = this._view.items, - entity = {}, - element = this._groups.headerFrom(event.srcElement), - winItem = null; - if (element) { - entity.type = WinJS.UI.ObjectType.groupHeader; - entity.index = this._groups.index(element); - } else { - entity.index = items.index(event.srcElement); - entity.type = WinJS.UI.ObjectType.item; - element = items.itemBoxAt(entity.index); - winItem = items.itemAt(entity.index); - } - - // In the old layouts, index will be -1 if a group header got focus - if (entity.index !== WinJS.UI._INVALID_INDEX) { - if (this._keyboardFocusInbound || this._selection._keyboardFocused()) { - if ((entity.type === WinJS.UI.ObjectType.groupHeader && event.srcElement === element) || - (entity.type === WinJS.UI.ObjectType.item && event.srcElement.parentNode === element)) { - // For items we check the parentNode because the srcElement is win-item and element is win-itembox, - // for header, they should both be the win-groupheader - this._drawFocusRectangle(element); - } - } - if (this._tabManager.childFocus !== element && this._tabManager.childFocus !== winItem) { - //#DBG _ASSERT(entity.index !== WinJS.UI._INVALID_INDEX); - this._selection._setFocused(entity, this._keyboardFocusInbound || this._selection._keyboardFocused()); - this._keyboardFocusInbound = false; - element = entity.type === WinJS.UI.ObjectType.groupHeader ? element : items.itemAt(entity.index); - this._tabManager.childFocus = element; - - if (that._updater) { - var elementInfo = that._updater.elements[element.uniqueID], - focusIndex = entity.index; - if (elementInfo && elementInfo.newIndex) { - focusIndex = elementInfo.newIndex; - } - - // Note to not set old and new focus to the same object - that._updater.oldFocus = { type: entity.type, index: focusIndex }; - that._updater.newFocus = { type: entity.type, index: focusIndex }; - } - } - } - } - }, - - _onBlur: function ListView_onBlur(event) { - this._hasKeyboardFocus = false; - this._itemFocused = false; - var element = this._view.items.itemBoxFrom(event.srcElement) || this._groups.headerFrom(event.srcElement); - if (element) { - this._clearFocusRectangle(element); - } - if (this._focusRequest) { - // If we're losing focus and we had an outstanding focus request, that means the focused item isn't realized. To enable the user to tab back - // into the listview, we'll make the keyboardEventsHelper tabbable for this scenario. - this._tabEventsHelper.childFocus = this._keyboardEventsHelper; - } - }, - - _onMSManipulationStateChanged: function ListView_onMSManipulationStateChanged(ev) { - var that = this; - function done() { - that._manipulationEndSignal = null; - } - - this._manipulationState = ev.currentState; - that._writeProfilerMark("_onMSManipulationStateChanged state(" + ev.currentState + "),info"); - - if (this._manipulationState !== MSManipulationEvent.MS_MANIPULATION_STATE_STOPPED && !this._manipulationEndSignal) { - this._manipulationEndSignal = new WinJS._Signal(); - this._manipulationEndSignal.promise.done(done, done); - } - - if (this._manipulationState === MSManipulationEvent.MS_MANIPULATION_STATE_STOPPED) { - this._manipulationEndSignal.complete(); - } - }, - - _pendingScroll: false, - - _onScroll: function ListView_onScroll() { - if (!this._zooming && !this._pendingScroll) { - this._checkScroller(); - } - }, - - _checkScroller: function ListView_checkScroller() { - if (this._isZombie()) { return; } - - var currentScrollPosition = this._viewportScrollPosition; - if (currentScrollPosition !== this._lastScrollPosition) { - this._pendingScroll = requestAnimationFrame(this._checkScroller.bind(this)); - - var direction = (currentScrollPosition < this._lastScrollPosition) ? "left" : "right"; - currentScrollPosition = Math.max(0, currentScrollPosition); - this._lastScrollPosition = currentScrollPosition; - this._raiseViewLoading(true); - var that = this; - this._view.onScroll(function () { - return { - position: that._lastScrollPosition, - direction: direction - }; - }, - this._manipulationEndSignal ? this._manipulationEndSignal.promise : Promise.timeout(WinJS.UI._DEFERRED_SCROLL_END)); - } else { - this._pendingScroll = null; - } - }, - - _onTabEnter: function ListView_onTabEnter() { - this._keyboardFocusInbound = true; - }, - - _onTabExit: function ListView_onTabExit() { - this._keyboardFocusInbound = false; - }, - - _onPropertyChange: function ListView_onPropertyChange(list) { - var that = this; - list.forEach(function (record) { - var dirChanged = false; - if (record.attributeName === "dir") { - dirChanged = true; - } else if (record.attributeName === "style") { - dirChanged = (that._cachedStyleDir != record.target.style.direction); - } - if (dirChanged) { - that._cachedStyleDir = record.target.style.direction; - that._cachedRTL = null; - utilities[that._rtl() ? "addClass" : "removeClass"](that._element, WinJS.UI._rtlListViewClass); - - that._lastScrollPosition = 0; - that._viewportScrollPosition = 0; - - that.forceLayout(); - } - - if (record.attributeName === "tabIndex") { - var newTabIndex = that._element.tabIndex; - if (newTabIndex >= 0) { - that._view.items.each(function (index, item, itemData) { - item.tabIndex = newTabIndex; - }); - that._tabIndex = newTabIndex; - that._tabManager.tabIndex = newTabIndex; - that._tabEventsHelper.tabIndex = newTabIndex; - that._element.tabIndex = -1; - } - } - }); - }, - - _getCanvasMargins: function ListView_getCanvasMargins() { - if (!this._canvasMargins) { - this._canvasMargins = WinJS.UI._getMargins(this._canvas); - } - return this._canvasMargins; - }, - - // Convert between canvas coordinates and viewport coordinates - _convertCoordinatesByCanvasMargins: function ListView_convertCoordinatesByCanvasMargins(coordinates, conversionCallback) { - function fix(field, offset) { - if (coordinates[field] !== undefined) { - coordinates[field] = conversionCallback(coordinates[field], offset); - } - } - - var offset; - if (this._horizontal()) { - offset = this._getCanvasMargins()[this._rtl() ? "right" : "left"]; - fix("left", offset); - } else { - offset = this._getCanvasMargins().top; - fix("top", offset); - } - fix("begin", offset); - fix("end", offset); - - return coordinates; - }, - _convertFromCanvasCoordinates: function ListView_convertFromCanvasCoordinates(coordinates) { - return this._convertCoordinatesByCanvasMargins(coordinates, function (coordinate, canvasMargin) { - return coordinate + canvasMargin; - }); - }, - _convertToCanvasCoordinates: function ListView_convertToCanvasCoordinates(coordinates) { - return this._convertCoordinatesByCanvasMargins(coordinates, function (coordinate, canvasMargin) { - return coordinate - canvasMargin; - }); - }, - - // Methods in the site interface used by ScrollView - _getViewportSize: function ListView_getViewportSize() { - if (this._viewportWidth === WinJS.UI._UNINITIALIZED || this._viewportHeight === WinJS.UI._UNINITIALIZED) { - this._viewportWidth = Math.max(0, utilities.getContentWidth(this._element)); - this._viewportHeight = Math.max(0, utilities.getContentHeight(this._element)); - this._writeProfilerMark("viewportSizeDetected width:" + this._viewportWidth + " height:" + this._viewportHeight); - - this._previousWidth = this._element.offsetWidth; - this._previousHeight = this._element.offsetHeight; - } - return { - width: this._viewportWidth, - height: this._viewportHeight - }; - }, - - _itemsCount: function ListView_itemsCount() { - var that = this; - function cleanUp() { - that._itemsCountPromise = null; - } - - if (this._cachedCount !== WinJS.UI._UNINITIALIZED) { - return Promise.wrap(this._cachedCount); - } else { - var retVal; - if (!this._itemsCountPromise) { - retVal = this._itemsCountPromise = this._itemsManager.dataSource.getCount().then( - function (count) { - if (count === thisWinUI.CountResult.unknown) { - count = 0; - } - that._cachedCount = count; - that._selection._updateCount(that._cachedCount); - return count; - }, - function () { - return WinJS.Promise.cancel; - } - ); - - this._itemsCountPromise.then(cleanUp, cleanUp); - } else { - retVal = this._itemsCountPromise; - } - - return retVal; - } - }, - - _isSelected: function ListView_isSelected(index) { - return this._selection._isIncluded(index); - }, - - _LoadingState: { - itemsLoading: "itemsLoading", - viewPortLoaded: "viewPortLoaded", - itemsLoaded: "itemsLoaded", - complete: "complete" - }, - - _raiseViewLoading: function ListView_raiseViewLoading(scrolling) { - if (this._loadingState !== this._LoadingState.itemsLoading) { - this._scrolling = !!scrolling; - } - this._setViewState(this._LoadingState.itemsLoading); - }, - - _raiseViewComplete: function ListView_raiseViewComplete() { - if (!this._disposed && !this._view.animating) { - this._setViewState(this._LoadingState.complete); - } - }, - - _setViewState: function ListView_setViewState(state) { - if (state !== this._loadingState) { - var detail = null; - // We can go from any state to itemsLoading but the rest of the states transitions must follow this - // order: itemsLoading -> viewPortLoaded -> itemsLoaded -> complete. - // Recursively set the previous state until you hit the current state or itemsLoading. - switch (state) { - case this._LoadingState.viewPortLoaded: - if (!this._scheduledForDispose) { - scheduleForDispose(this); - this._scheduledForDispose = true; - } - this._setViewState(this._LoadingState.itemsLoading); - break; - - case this._LoadingState.itemsLoaded: - detail = { - scrolling: this._scrolling - }; - this._setViewState(this._LoadingState.viewPortLoaded); - break; - - case this._LoadingState.complete: - this._setViewState(this._LoadingState.itemsLoaded); - this._updateDeleteWrapperSize(true); - break; - } - - this._writeProfilerMark("loadingStateChanged:" + state + ",info"); - this._loadingState = state; - var eventObject = document.createEvent("CustomEvent"); - eventObject.initCustomEvent("loadingstatechanged", true, false, detail); - this._element.dispatchEvent(eventObject); - } - }, - - _createTemplates: function ListView_createTemplates() { - - function createNodeWithClass(className, skipAriaHidden) { - var element = document.createElement("div"); - element.className = className; - if (!skipAriaHidden) { - element.setAttribute("aria-hidden", true); - } - return element; - } - - this._itemBoxTemplate = createNodeWithClass(WinJS.UI._itemBoxClass, true); - }, - - // Methods used by SelectionManager - _updateSelection: function ListView_updateSelection() { - var indices = this._selection.getIndices(), - selectAll = this._selection.isEverything(), - selectionMap = {}; - - if (!selectAll) { - for (var i = 0, len = indices.length ; i < len; i++) { - var index = indices[i]; - selectionMap[index] = true; - } - } - - var that = this; - this._view.items.each(function (index, element, itemData) { - if (itemData.itemBox && !utilities.hasClass(itemData.itemBox, thisWinUI._swipeClass)) { - var selected = selectAll || !!selectionMap[index]; - WinJS.UI._ItemEventsHandler.renderSelection(itemData.itemBox, element, selected, true); - if (itemData.container) { - utilities[selected ? "addClass" : "removeClass"](itemData.container, WinJS.UI._selectedClass); - } - } - }); - }, - - _getViewportLength: function ListView_getViewportLength() { - return this._getViewportSize()[this._horizontal() ? "width" : "height"]; - }, - - _horizontal: function ListView_horizontal() { - return this._horizontalLayout; - }, - - _rtl: function ListView_rtl() { - if (typeof this._cachedRTL !== "boolean") { - this._cachedRTL = window.getComputedStyle(this._element, null).direction === "rtl"; - } - return this._cachedRTL; - }, - - _showProgressBar: function ListView_showProgressBar(parent, x, y) { - var progressBar = this._progressBar, - progressStyle = progressBar.style; - - if (!progressBar.parentNode) { - this._fadingProgressBar = false; - if (this._progressIndicatorDelayTimer) { - this._progressIndicatorDelayTimer.cancel(); - } - var that = this; - this._progressIndicatorDelayTimer = Promise.timeout(WinJS.UI._LISTVIEW_PROGRESS_DELAY).then(function () { - if (!that._isZombie()) { - parent.appendChild(progressBar); - AnimationHelper.fadeInElement(progressBar); - that._progressIndicatorDelayTimer = null; - } - }); - } - progressStyle[this._rtl() ? "right" : "left"] = x; - progressStyle.top = y; - }, - - _hideProgressBar: function ListView_hideProgressBar() { - if (this._progressIndicatorDelayTimer) { - this._progressIndicatorDelayTimer.cancel(); - this._progressIndicatorDelayTimer = null; - } - - var progressBar = this._progressBar; - if (progressBar.parentNode && !this._fadingProgressBar) { - this._fadingProgressBar = true; - var that = this; - AnimationHelper.fadeOutElement(progressBar).then(function () { - if (progressBar.parentNode) { - progressBar.parentNode.removeChild(progressBar); - } - that._fadingProgressBar = false; - }); - } - }, - - _getPanAxis: function () { - return this._horizontal() ? "horizontal" : "vertical"; - }, - - _configureForZoom: function (isZoomedOut, isCurrentView, triggerZoom, pagesToPrefetch) { - if (WinJS.validation) { - if (!this._view.realizePage || typeof this._view.begin !== "number") { - throw new WinJS.ErrorFromName("WinJS.UI.ListView.NotCompatibleWithSemanticZoom", strings.notCompatibleWithSemanticZoom); - } - } - - this._isZoomedOut = isZoomedOut; - this._disableEntranceAnimation = !isCurrentView; - - this._isCurrentZoomView = isCurrentView; - - this._triggerZoom = triggerZoom; - }, - - _setCurrentItem: function (x, y) { - // First, convert the position into canvas coordinates - if (this._rtl()) { - x = this._viewportWidth - x; - } - if (this._horizontal()) { - x += this.scrollPosition; - } else { - y += this.scrollPosition; - } - - var result = this._view.hitTest(x, y), - entity = { type: result.type ? result.type : WinJS.UI.ObjectType.item, index: result.index }; - if (entity.index >= 0) { - if (this._hasKeyboardFocus) { - this._changeFocus(entity, true, false, true); - } else { - this._changeFocusPassively(entity); - } - } - }, - - _getCurrentItem: function () { - var focused = this._selection._getFocused(); - - if (focused.type === WinJS.UI.ObjectType.groupHeader) { - focused = { type: WinJS.UI.ObjectType.item, index: this._groups.group(focused.index).startIndex }; - } - - if (typeof focused.index !== "number") { - // Do a hit-test in the viewport center - this._setCurrentItem(0.5 * this._viewportWidth, 0.5 * this._viewportHeight); - - focused = this._selection._getFocused(); - } - - var that = this; - var promisePosition = this._getItemOffsetPosition(focused.index). - then(function (posCanvas) { - var scrollOffset = that._canvasStart; - - posCanvas[that._startProperty] += scrollOffset; - - return posCanvas; - }); - - return Promise.join({ - item: this._dataSource.itemFromIndex(focused.index), - position: promisePosition - }); - }, - - _beginZoom: function () { - this._zooming = true; - - // Hide the scrollbar and extend the content beyond the ListView viewport - - var horizontal = this._horizontal(), - scrollOffset = -this.scrollPosition; - - utilities.addClass(this._viewport, horizontal ? WinJS.UI._zoomingXClass : WinJS.UI._zoomingYClass); - this._canvasStart = scrollOffset; - utilities.addClass(this._viewport, horizontal ? WinJS.UI._zoomingYClass : WinJS.UI._zoomingXClass); - }, - - _positionItem: function (item, position) { - var that = this; - function positionItemAtIndex(index) { - return that._getItemOffsetPosition(index).then(function positionItemAtIndex_then_ItemOffsetPosition(posCanvas) { - var horizontal = that._horizontal(), - canvasMargins = that._getCanvasMargins(), - canvasSize = that._canvas[horizontal ? "offsetWidth" : "offsetHeight"] + canvasMargins[(horizontal ? (that._rtl() ? "right" : "left") : "top")], - viewportSize = (horizontal ? that._viewportWidth : that._viewportHeight), - scrollPosition; - - // Align the leading edge - var start = position[that._startProperty], - startMax = viewportSize - (horizontal ? posCanvas.width : posCanvas.height); - - // Ensure the item ends up within the viewport - start = Math.max(0, Math.min(startMax, start)); - - scrollPosition = posCanvas[that._startProperty] - start; - - - // Ensure the scroll position is valid - var adjustedScrollPosition = Math.max(0, Math.min(canvasSize - viewportSize, scrollPosition)), - scrollAdjustment = adjustedScrollPosition - scrollPosition; - - scrollPosition = adjustedScrollPosition; - - // Since a zoom is in progress, adjust the div position - var scrollOffset = -scrollPosition; - that._canvasStart = scrollOffset; - - var entity = { type: WinJS.UI.ObjectType.item, index: index } - if (that._hasKeyboardFocus) { - that._changeFocus(entity, true); - } else { - that._changeFocusPassively(entity); - } - - that._raiseViewLoading(true); - that._view.realizePage(scrollPosition, true); - - return ( - horizontal ? - { x: scrollAdjustment, y: 0 } : - { x: 0, y: scrollAdjustment } - ); - }); - } - - var itemIndex = 0; - if (item) { - itemIndex = (this._isZoomedOut ? item.groupIndexHint : item.firstItemIndexHint); - } - - if (typeof itemIndex === "number") { - return positionItemAtIndex(itemIndex); - } else { - // We'll need to obtain the index from the data source - var itemPromise; - - var key = (this._isZoomedOut ? item.groupKey : item.firstItemKey); - if (typeof key === "string" && this._dataSource.itemFromKey) { - itemPromise = this._dataSource.itemFromKey(key, (this._isZoomedOut ? { - groupMemberKey: item.key, - groupMemberIndex: item.index - } : null)); - } else { - var description = (this._isZoomedOut ? item.groupDescription : item.firstItemDescription); - - if (WinJS.validation) { - if (description === undefined) { - throw new WinJS.ErrorFromName("WinJS.UI.ListView.InvalidItem", strings.listViewInvalidItem); - } - } - - itemPromise = this._dataSource.itemFromDescription(description); - } - - return itemPromise.then(function (item) { - return positionItemAtIndex(item.index); - }); - } - }, - - _endZoom: function (isCurrentView) { - if (this._isZombie()) { - return; - } - - // Crop the content again and re-enable the scrollbar - - var horizontal = this._horizontal(), - scrollOffset = this._canvasStart; - - utilities.removeClass(this._viewport, WinJS.UI._zoomingYClass); - utilities.removeClass(this._viewport, WinJS.UI._zoomingXClass); - - this._canvasStart = 0; - - this._viewportScrollPosition = -scrollOffset; - - this._disableEntranceAnimation = !isCurrentView; - - this._isCurrentZoomView = isCurrentView; - this._zooming = false; - - this._view.realizePage(this.scrollPosition, false); - }, - - _getItemOffsetPosition: function (index) { - var that = this; - return this._getItemOffset({ type: WinJS.UI.ObjectType.item, index: index }).then(function (position) { - return that._ensureFirstColumnRange(WinJS.UI.ObjectType.item).then(function () { - position = that._correctRangeInFirstColumn(position, WinJS.UI.ObjectType.item); - position = that._convertFromCanvasCoordinates(position); - if (that._horizontal()) { - position.left = position.begin; - position.width = position.end - position.begin; - position.height = position.totalHeight; - } else { - position.top = position.begin; - position.height = position.end - position.begin; - position.width = position.totalWidth; - } - return position; - }); - }); - }, - - _groupRemoved: function (key) { - this._groupFocusCache.deleteGroup(key); - }, - - _updateFocusCache: function (itemIndex) { - if (this._updateFocusCacheItemRequest) { - this._updateFocusCacheItemRequest.cancel(); - } - - var that = this; - this._updateFocusCacheItemRequest = this._view.items.requestItem(itemIndex).then(function (item) { - that._updateFocusCacheItemRequest = null; - var itemData = that._view.items.itemDataAt(itemIndex); - var groupIndex = that._groups.groupFromItem(itemIndex); - var groupKey = that._groups.group(groupIndex).key; - if (itemData.itemsManagerRecord.item) { - that._groupFocusCache.updateCache(groupKey, itemData.itemsManagerRecord.item.key, itemIndex); - } - }); - }, - - _changeFocus: function (newFocus, skipSelection, ctrlKeyDown, skipEnsureVisible, keyboardFocused) { - //#DBG _ASSERT(newFocus.index !== -1); - if (this._isZombie()) { - return; - } - var targetItem; - if (newFocus.type !== WinJS.UI.ObjectType.groupHeader) { - targetItem = this._view.items.itemAt(newFocus.index); - if (!skipSelection && targetItem && utilities.hasClass(targetItem, WinJS.UI._nonSelectableClass)) { - skipSelection = true; - } - this._updateFocusCache(newFocus.index); - } else { - var group = this._groups.group(newFocus.index); - targetItem = group && group.header; - } - this._unsetFocusOnItem(!!targetItem); - this._hasKeyboardFocus = true; - this._selection._setFocused(newFocus, keyboardFocused); - if (!skipEnsureVisible) { - this.ensureVisible(newFocus); - } - - // _selection.set() needs to know which item has focus so we - // must call it after _selection._setFocused() has been called. - if (!skipSelection && this._selectFocused(ctrlKeyDown)) { - this._selection.set(newFocus.index); - } - this._setFocusOnItem(newFocus); - }, - - // Updates ListView's internal focus state and, if ListView currently has focus, moves - // Trident's focus to the item at index newFocus. - // Similar to _changeFocus except _changeFocusPassively doesn't: - // - ensure the item is selected or visible - // - set Trident's focus to newFocus when ListView doesn't have focus - _changeFocusPassively: function (newFocus) { - //#DBG _ASSERT(newFocus.index !== -1); - - var targetItem; - if (newFocus.type !== WinJS.UI.ObjectType.groupHeader) { - targetItem = this._view.items.itemAt(newFocus.index); - this._updateFocusCache(newFocus.index); - } else { - var group = this._groups.group(newFocus.index); - targetItem = group && group.header; - } - this._unsetFocusOnItem(!!targetItem); - this._selection._setFocused(newFocus); - this._setFocusOnItem(newFocus); - }, - - _drawFocusRectangle: function (item) { - if (WinJS.Utilities.hasClass(item, thisWinUI._headerClass)) { - WinJS.Utilities.addClass(item, thisWinUI._itemFocusClass); - } else { - var itemBox = this._view.items.itemBoxFrom(item); - //#DBG _ASSERT(utilities.hasClass(itemBox, WinJS.UI._itemBoxClass)); - if (itemBox.querySelector("." + thisWinUI._itemFocusOutlineClass)) { - return; - } - utilities.addClass(itemBox, thisWinUI._itemFocusClass); - var outline = document.createElement("div"); - outline.className = thisWinUI._itemFocusOutlineClass; - itemBox.appendChild(outline); - } - }, - - _clearFocusRectangle: function (item) { - if (!item || this._isZombie()) { - return; - } - - var itemBox = this._view.items.itemBoxFrom(item); - if (itemBox) { - utilities.removeClass(itemBox, thisWinUI._itemFocusClass); - //#DBG _ASSERT(utilities.hasClass(itemBox, WinJS.UI._itemBoxClass)); - var outline = itemBox.querySelector("." + thisWinUI._itemFocusOutlineClass); - if (outline) { - outline.parentNode.removeChild(outline); - } - } else { - var header = this._groups.headerFrom(item); - if (header) { - utilities.removeClass(header, thisWinUI._itemFocusClass); - } - } - }, - - _defaultInvoke: function (entity) { - if (this._isZoomedOut) { - this._changeFocusPassively(entity); - this._triggerZoom(); - } - }, - - _selectionAllowed: function ListView_selectionAllowed(itemIndex) { - var item = (itemIndex !== undefined ? this.elementFromIndex(itemIndex) : null), - itemSelectable = !(item && utilities.hasClass(item, WinJS.UI._nonSelectableClass)); - return itemSelectable && this._selectionMode !== WinJS.UI.SelectionMode.none; - }, - - _multiSelection: function ListView_multiSelection() { - return this._selectionMode === WinJS.UI.SelectionMode.multi; - }, - - _selectOnTap: function ListView_selectOnTap() { - return this._tap === WinJS.UI.TapBehavior.toggleSelect || this._tap === WinJS.UI.TapBehavior.directSelect; - }, - - _selectFocused: function ListView_selectFocused(ctrlKeyDown) { - return this._tap === WinJS.UI.TapBehavior.directSelect && this._selectionMode === WinJS.UI.SelectionMode.multi && !ctrlKeyDown; - }, - - _dispose: function () { - if (!this._disposed) { - this._disposed = true; - var clear = function clear(e) { - e && (e.innerText = ""); - } - - this._batchingViewUpdates && this._batchingViewUpdates.cancel(); - - this._view && this._view._dispose && this._view._dispose(); - this._mode && this._mode._dispose && this._mode._dispose(); - this._groups && this._groups._dispose && this._groups._dispose(); - this._selection && this._selection._dispose && this._selection._dispose(); - this._layout && this._layout.uninitialize && this._layout.uninitialize(); - - this._itemsCountPromise && this._itemsCountPromise.cancel(); - this._versionManager && this._versionManager._dispose(); - this._clearInsertedItems(); - this._itemsManager && this._itemsManager.release(); - - clear(this._viewport); - clear(this._canvas); - clear(this._canvasProxy); - - this._versionManager = null; - this._view = null; - this._mode = null; - this._element = null; - this._viewport = null; - this._itemsManager = null; - this._canvas = null; - this._canvasProxy = null; - this._itemsCountPromise = null; - this._scrollToFunctor = null; - - var index = controlsToDispose.indexOf(this); - if (index >= 0) { - controlsToDispose.splice(index, 1); - } - } - }, - - _isZombie: function () { - // determines if this ListView is no longer in the DOM or has been cleared - // - return this._disposed || !(this.element.firstElementChild && document.body.contains(this.element)); - }, - - _ifZombieDispose: function () { - var zombie = this._isZombie(); - if (zombie && !this._disposed) { - scheduleForDispose(this); - } - return zombie; - }, - - _animationsDisabled: function () { - if (this._viewportWidth === 0 || this._viewportHeight === 0) { - return true; - } - - return !WinJS.UI.isAnimationEnabled(); - }, - - _fadeOutViewport: function ListView_fadeOutViewport() { - var that = this; - return new Promise(function (complete) { - if (that._animationsDisabled()) { - complete(); - return; - } - - if (!that._fadingViewportOut) { - if (that._waitingEntranceAnimationPromise) { - that._waitingEntranceAnimationPromise.cancel(); - that._waitingEntranceAnimationPromise = null; - } - var eventDetails = that._fireAnimationEvent(WinJS.UI.ListViewAnimationType.contentTransition); - that._firedAnimationEvent = true; - if (!eventDetails.prevented) { - that._fadingViewportOut = true; - that._viewport.style["-ms-overflow-style"] = "none"; - AnimationHelper.fadeOutElement(that._viewport).then(function () { - if (that._isZombie()) { return; } - that._fadingViewportOut = false; - that._viewport.style.opacity = 1.0; - complete(); - }); - } else { - that._disableEntranceAnimation = true; - that._viewport.style.opacity = 1.0; - complete(); - } - } - }); - }, - - _animateListEntrance: function (firstTime) { - var eventDetails = { - prevented: false, - animationPromise: Promise.wrap() - }; - var that = this; - function resetViewOpacity() { - that._canvas.style.opacity = 1; - that._viewport.style["-ms-overflow-style"] = ""; - } - - if (this._disableEntranceAnimation || this._animationsDisabled()) { - resetViewOpacity(); - if (this._waitingEntranceAnimationPromise) { - this._waitingEntranceAnimationPromise.cancel(); - this._waitingEntranceAnimationPromise = null; - } - return Promise.wrap(); - } - - if (!this._firedAnimationEvent) { - eventDetails = this._fireAnimationEvent(WinJS.UI.ListViewAnimationType.entrance); - } else { - this._firedAnimationEvent = false; - } - - if (eventDetails.prevented) { - resetViewOpacity(); - return Promise.wrap(); - } else { - if (this._waitingEntranceAnimationPromise) { - this._waitingEntranceAnimationPromise.cancel(); - } - this._canvas.style.opacity = 0; - this._viewport.style["-ms-overflow-style"] = "none"; - this._waitingEntranceAnimationPromise = eventDetails.animationPromise.then(function () { - if (!that._isZombie()) { - that._canvas.style.opacity = 1; - return AnimationHelper.animateEntrance(that._viewport, firstTime).then(function () { - if (!that._isZombie()) { - that._viewport.style["-ms-overflow-style"] = ""; - that._waitingEntranceAnimationPromise = null; - } - }); - } - }); - return this._waitingEntranceAnimationPromise; - } - }, - - _fireAnimationEvent: function (type) { - var animationEvent = document.createEvent("CustomEvent"), - animationPromise = Promise.wrap(); - - animationEvent.initCustomEvent("contentanimating", true, true, { - type: type - }); - if (type === WinJS.UI.ListViewAnimationType.entrance) { - animationEvent.detail.setPromise = function (delayPromise) { - animationPromise = delayPromise; - }; - } - var prevented = !this._element.dispatchEvent(animationEvent); - return { - prevented: prevented, - animationPromise: animationPromise - } - }, - - // If they don't yet exist, create the start and end markers which are required - // by Narrator's aria-flowto/flowfrom implementation. They mark the start and end - // of ListView's set of out-of-order DOM elements and so they must surround the - // headers and groups in the DOM. - _createAriaMarkers: function ListView_createAriaMarkers() { - if (!this._viewport.getAttribute("aria-label")) { - this._viewport.setAttribute("aria-label", strings.listViewViewportAriaLabel); - } - - if (!this._ariaStartMarker) { - this._ariaStartMarker = document.createElement("div"); - this._ariaStartMarker.id = this._ariaStartMarker.uniqueID; - this._viewport.insertBefore(this._ariaStartMarker, this._viewport.firstElementChild); - } - if (!this._ariaEndMarker) { - this._ariaEndMarker = document.createElement("div"); - this._ariaEndMarker.id = this._ariaEndMarker.uniqueID; - this._viewport.appendChild(this._ariaEndMarker); - } - }, - - // If the ListView is in static mode, then the roles of the list and items should be "list" and "listitem", respectively. - // Otherwise, the roles should be "listbox" and "option." If the ARIA roles are out of sync with the ListView's - // static/interactive state, update the role of the ListView and the role of each realized item. - _updateItemsAriaRoles: function ListView_updateItemsAriaRoles() { - var that = this; - var listRole = this._element.getAttribute("role"), - expectedListRole, - expectedItemRole; - - if (this._currentMode().staticMode()) { - expectedListRole = "list"; - expectedItemRole = "listitem"; - } else { - expectedListRole = "listbox"; - expectedItemRole = "option"; - } - - if (listRole !== expectedListRole || this._itemRole !== expectedItemRole) { - this._element.setAttribute("role", expectedListRole); - this._itemRole = expectedItemRole; - this._view.items.each(function (index, itemElement, itemData) { - itemElement.setAttribute("role", that._itemRole); - }); - } - }, - - _updateGroupHeadersAriaRoles: function ListView_updateGroupHeadersAriaRoles() { - var that = this, - headerRole = (this.groupHeaderTapBehavior === WinJS.UI.GroupHeaderTapBehavior.none ? "separator" : "link"); - if (this._headerRole !== headerRole) { - this._headerRole = headerRole; - for (var i = 0, len = this._groups.length() ; i < len; i++) { - var header = this._groups.group(i).header; - if (header) { - header.setAttribute("role", this._headerRole); - } - } - } - }, - - // Avoids unnecessary UIA selection events by only updating aria-selected if it has changed - _setAriaSelected: function ListView_setAriaSelected(itemElement, isSelected) { - var ariaSelected = (itemElement.getAttribute("aria-selected") === "true"); - - if (isSelected !== ariaSelected) { - itemElement.setAttribute("aria-selected", isSelected); - } - }, - - _setupAriaSelectionObserver: function ListView_setupAriaSelectionObserver(item) { - if (!item._mutationObserver) { - this._mutationObserver.observe(item, { attributes: true, attributeFilter: ["aria-selected"] }); - item._mutationObserver = true; - } - }, - - _itemPropertyChange: function ListView_itemPropertyChange(list) { - if (this._isZombie()) { return; } - - var that = this; - var singleSelection = that._selectionMode === WinJS.UI.SelectionMode.single; - var changedItems = []; - var unselectableItems = []; - - function revertAriaSelected(items) { - items.forEach(function (entry) { - entry.item.setAttribute("aria-selected", !entry.selected); - }); - } - - for (var i = 0, len = list.length; i < len; i++) { - var item = list[i].target; - var itemBox = that._view.items.itemBoxFrom(item); - var selected = item.getAttribute("aria-selected") === "true"; - - // Only respond to aria-selected changes coming from UIA. This check - // relies on the fact that, in renderSelection, we update the selection - // visual before aria-selected. - if (itemBox && (selected !== WinJS.UI._isSelectionRendered(itemBox))) { - var index = that._view.items.index(itemBox); - var entry = { index: index, item: item, selected: selected }; - (that._selectionAllowed(index) ? changedItems : unselectableItems).push(entry); - } - } - if (changedItems.length > 0) { - var signal = new WinJS._Signal(); - that.selection._synchronize(signal).then(function () { - var newSelection = that.selection._cloneSelection(); - - changedItems.forEach(function (entry) { - if (entry.selected) { - newSelection[singleSelection ? "set" : "add"](entry.index); - } else { - newSelection.remove(entry.index); - } - }); - - return that.selection._set(newSelection); - }).then(function (approved) { - if (!that._isZombie() && !approved) { - // A selectionchanging event handler rejected the selection change - revertAriaSelected(changedItems); - } - - signal.complete(); - }); - } - - revertAriaSelected(unselectableItems); - }, - - _groupsEnabled: function () { - return !!this._groups.groupDataSource; - }, - - _getItemPosition: function ListView_getItemPosition(entity, preserveItemsBlocks) { - var that = this; - return this._view.waitForEntityPosition(entity).then(function () { - var container = (entity.type === WinJS.UI.ObjectType.groupHeader ? that._view._getHeaderContainer(entity.index) : that._view.getContainer(entity.index)); - if (container) { - that._writeProfilerMark("WinJS.UI.ListView:getItemPosition,info"); - - if (that._view._expandedRange) { - var itemsBlockFrom = that._view._expandedRange.first.index, - itemsBlockTo = that._view._expandedRange.last.index; - } else { - preserveItemsBlocks = false; - } - - if (entity.type === WinJS.UI.ObjectType.item) { - preserveItemsBlocks = !!preserveItemsBlocks; - preserveItemsBlocks &= that._view._ensureContainerInDOM(entity.index); - } else { - preserveItemsBlocks = false; - } - - var margins = that._getItemMargins(entity.type), - position = { - left: (that._rtl() ? getOffsetRight(container) - margins.right : container.offsetLeft - margins.left), - top: container.offsetTop - margins.top, - totalWidth: utilities.getTotalWidth(container), - totalHeight: utilities.getTotalHeight(container), - contentWidth: utilities.getContentWidth(container), - contentHeight: utilities.getContentHeight(container) - }; - - if (preserveItemsBlocks) { - that._view._forceItemsBlocksInDOM(itemsBlockFrom, itemsBlockTo + 1); - } - - // When a translation is applied to the surface during zooming, offsetLeft includes the canvas margins, so the left/top position will already be in canvas coordinates. - // If we're not zooming, we need to convert the position to canvas coordinates before returning. - return (that._zooming && that._canvasStart !== 0 ? position : that._convertToCanvasCoordinates(position)); - } else { - return WinJS.Promise.cancel; - } - }); - }, - - _getItemOffset: function ListView_getItemOffset(entity, preserveItemsBlocks) { - var that = this; - return this._getItemPosition(entity, preserveItemsBlocks).then(function (pos) { - // _getItemOffset also includes the right/bottom margin of the previous row/column of items, so that ensureVisible/indexOfFirstVisible will jump such that - // the previous row/column is directly offscreen of the target item. - var margins = that._getItemMargins(entity.type); - if (that._horizontal()) { - var rtl = that._rtl(); - pos.begin = pos.left - margins[rtl ? "left" : "right"], - pos.end = pos.left + pos.totalWidth + margins[rtl ? "right" : "left"] - } else { - pos.begin = pos.top - margins.bottom, - pos.end = pos.top + pos.totalHeight + margins.top - } - return pos; - }); - }, - - _getItemMargins: function ListView_getItemMargins(type) { - type = type || WinJS.UI.ObjectType.item; - var that = this; - var calculateMargins = function (className) { - var item = that._canvas.querySelector("." + className), - cleanup; - - if (!item) { - item = document.createElement("div"), - utilities.addClass(item, className); - that._viewport.appendChild(item); - - cleanup = true; - } - - var margins = WinJS.UI._getMargins(item); - - if (cleanup) { - that._viewport.removeChild(item); - } - return margins; - }; - - if (type !== WinJS.UI.ObjectType.groupHeader) { - return (this._itemMargins ? this._itemMargins : (this._itemMargins = calculateMargins(WinJS.UI._containerClass))); - } else { - return (this._headerMargins ? this._headerMargins : (this._headerMargins = calculateMargins(WinJS.UI._headerContainerClass))); - } - }, - - _fireAccessibilityAnnotationCompleteEvent: function ListView_fireAccessibilityAnnotationCompleteEvent(firstIndex, lastIndex, firstHeaderIndex, lastHeaderIndex) { - // This event is fired in these cases: - // - When the data source count is 0, it is fired after the aria markers have been - // updated. The event detail will be { firstIndex: -1, lastIndex: -1 }. - // - When the data source count is non-zero, it is fired after the aria markers - // have been updated and the deferred work for the aria properties on the items - // has completed. - // - When an item gets focus. The event will be { firstIndex: indexOfItem, lastIndex: indexOfItem }. - var detail = { - firstIndex: firstIndex, - lastIndex: lastIndex, - firstHeaderIndex: (+firstHeaderIndex) || -1, - lastHeaderIndex: (+lastHeaderIndex) || -1 - } - var eventObject = document.createEvent("CustomEvent"); - eventObject.initCustomEvent("accessibilityannotationcomplete", true, false, detail); - this._element.dispatchEvent(eventObject); - }, - - _ensureFirstColumnRange: function ListView_ensureFirstColumnRange(type) { - var propName = (type === WinJS.UI.ObjectType.item ? "_firstItemRange" : "_firstHeaderRange"); - if (!this[propName]) { - var that = this; - return this._getItemOffset({ type: type, index: 0 }, true).then(function (firstRange) { - that[propName] = firstRange; - }); - } else { - return Promise.wrap(); - } - }, - - _correctRangeInFirstColumn: function ListView_correctRangeInFirstColumn(range, type) { - var firstRange = (type === WinJS.UI.ObjectType.groupHeader ? this._firstHeaderRange : this._firstItemRange); - if (firstRange.begin === range.begin) { - if (this._horizontal()) { - range.begin = -this._getCanvasMargins()[this._rtl() ? "right" : "left"]; - } else { - range.begin = -this._getCanvasMargins().top; - } - } - return range; - }, - - _updateContainers: function ListView_updateContainers(groups, count, containersDelta, modifiedElements) { - var that = this; - - var maxContainers = this._view.containers.length + (containersDelta > 0 ? containersDelta : 0); - - var newTree = []; - var newKeyToGroupIndex = {}; - var newContainers = []; - var removedContainers = []; - - function createContainer() { - var element = document.createElement("div"); - element.className = WinJS.UI._containerClass; - return element; - } - - function updateExistingGroupWithBlocks(groupNode, firstItem, newSize) { - if (firstItem + newSize > maxContainers) { - newSize = maxContainers - firstItem; - } - - var itemsContainer = groupNode.itemsContainer, - blocks = itemsContainer.itemsBlocks, - lastBlock = blocks.length ? blocks[blocks.length - 1] : null, - currentSize = blocks.length ? (blocks.length - 1) * that._view._blockSize + lastBlock.items.length : 0, - delta = newSize - currentSize, - oldSize, children; - - if (delta > 0) { - if (lastBlock && lastBlock.items.length < that._view._blockSize) { - var toAdd = Math.min(delta, that._view._blockSize - lastBlock.items.length); - utilities.insertAdjacentHTMLUnsafe(lastBlock.element, "beforeend", WinJS.UI._repeat("
    ", toAdd)); - - oldSize = lastBlock.items.length; - children = lastBlock.element.children; - - for (var j = 0; j < toAdd; j++) { - lastBlock.items.push(children[oldSize + j]); - } - - delta -= toAdd; - } - - var blocksCount = Math.floor(delta / that._view._blockSize), - lastBlockSize = delta % that._view._blockSize; - - var blockMarkup = "
    " + WinJS.UI._repeat("
    ", that._view._blockSize) + "
    ", - markup = WinJS.UI._repeat(blockMarkup, blocksCount); - - if (lastBlockSize) { - markup += "
    " + WinJS.UI._repeat("
    ", lastBlockSize) + "
    "; - blocksCount++; - } - - var blocksTemp = document.createElement("div"); - utilities.setInnerHTMLUnsafe(blocksTemp, markup); - - var children = blocksTemp.children; - for (var j = 0; j < blocksCount; j++) { - var block = children[j], - blockNode = { - element: block, - items: WinJS.UI._nodeListToArray(block.children) - }; - itemsContainer.itemsBlocks.push(blockNode); - } - } else if (delta < 0) { - for (var n = delta; n < 0; n++) { - - var container = lastBlock.items.pop(); - - if (!that._view._requireFocusRestore && container.contains(document.activeElement)) { - that._view._requireFocusRestore = document.activeElement; - that._unsetFocusOnItem(); - } - - lastBlock.element.removeChild(container); - removedContainers.push(container); - - if (!lastBlock.items.length) { - if (itemsContainer.element === lastBlock.element.parentNode) { - itemsContainer.element.removeChild(lastBlock.element); - } - - blocks.pop(); - lastBlock = blocks[blocks.length - 1]; - } - } - } - - for (var j = 0, len = blocks.length; j < len; j++) { - var block = blocks[j]; - for (var n = 0; n < block.items.length; n++) { - newContainers.push(block.items[n]); - } - } - } - - function addInserted(groupNode, firstItemIndex, newSize) { - var added = modifiedElements.filter(function (entry) { - return (entry.oldIndex === -1 && entry.newIndex >= firstItemIndex && entry.newIndex < (firstItemIndex + newSize)); - }).sort(function (left, right) { - return left.newIndex - right.newIndex; - }); - - var itemsContainer = groupNode.itemsContainer; - - for (var i = 0, len = added.length; i < len; i++) { - var entry = added[i], - offset = entry.newIndex - firstItemIndex; - - var container = createContainer(), - next = offset < itemsContainer.items.length ? itemsContainer.items[offset] : null; - itemsContainer.items.splice(offset, 0, container); - itemsContainer.element.insertBefore(container, next); - } - } - - function updateExistingGroup(groupNode, firstItem, newSize) { - if (firstItem + newSize > maxContainers) { - newSize = maxContainers - firstItem; - } - - var itemsContainer = groupNode.itemsContainer, - delta = newSize - itemsContainer.items.length; - - if (delta > 0) { - var children = itemsContainer.element.children, - oldSize = children.length; - - utilities.insertAdjacentHTMLUnsafe(itemsContainer.element, "beforeend", WinJS.UI._repeat("
    ", delta)); - - for (var n = 0; n < delta; n++) { - var container = children[oldSize + n]; - itemsContainer.items.push(container); - } - } - - for (var n = delta; n < 0; n++) { - var container = itemsContainer.items.pop(); - itemsContainer.element.removeChild(container); - removedContainers.push(container); - } - - for (var n = 0, len = itemsContainer.items.length; n < len; n++) { - newContainers.push(itemsContainer.items[n]); - } - } - - function addNewGroup(groupInfo, firstItem) { - var header = that._view._createHeaderContainer(prevElement); - - var groupNode = { - header: header, - itemsContainer: { - element: that._view._createItemsContainer(header), - } - }; - - groupNode.itemsContainer[that._view._blockSize ? "itemsBlocks" : "items"] = []; - - if (that._view._blockSize) { - updateExistingGroupWithBlocks(groupNode, firstItem, groupInfo.size); - } else { - updateExistingGroup(groupNode, firstItem, groupInfo.size); - } - - return groupNode; - } - - function shift(groupNode, oldFirstItemIndex, currentFirstItemIndex, newSize) { - var currentLast = currentFirstItemIndex + newSize - 1, - firstShifted, - delta; - - for (var i = 0, len = modifiedElements.length; i < len; i++) { - var entry = modifiedElements[i]; - if (entry.newIndex >= currentFirstItemIndex && entry.newIndex <= currentLast && entry.oldIndex !== -1) { - if (firstShifted !== +firstShifted || entry.newIndex < firstShifted) { - firstShifted = entry.newIndex; - delta = entry.newIndex - entry.oldIndex; - } - } - } - - if (firstShifted === +firstShifted) { - var addedBeforeShift = 0; - for (i = 0, len = modifiedElements.length; i < len; i++) { - var entry = modifiedElements[i]; - if (entry.newIndex >= currentFirstItemIndex && entry.newIndex < firstShifted && entry.oldIndex === -1) { - addedBeforeShift++; - } - } - var removedBeforeShift = 0, - oldFirstShifted = firstShifted - delta; - for (i = 0, len = modifiedElements.length; i < len; i++) { - var entry = modifiedElements[i]; - if (entry.oldIndex >= oldFirstItemIndex && entry.oldIndex < oldFirstShifted && entry.newIndex === -1) { - removedBeforeShift++; - } - } - - delta += removedBeforeShift; - delta -= addedBeforeShift; - delta -= currentFirstItemIndex - oldFirstItemIndex; - - var itemsContainer = groupNode.itemsContainer; - - if (delta > 0) { - var children = itemsContainer.element.children, - oldSize = children.length; - - utilities.insertAdjacentHTMLUnsafe(itemsContainer.element, "afterBegin", WinJS.UI._repeat("
    ", delta)); - - for (var n = 0; n < delta; n++) { - var container = children[n]; - itemsContainer.items.splice(n, 0, container); - } - } - - for (var n = delta; n < 0; n++) { - var container = itemsContainer.items.shift(); - itemsContainer.element.removeChild(container); - } - - if (delta) { - // Invalidate the layout of the entire group because we do not know the exact indices which were added/modified since they were before the realization range. - that._affectedRange.add({ - start: currentFirstItemIndex, - end: currentFirstItemIndex + newSize - }, count); - } - } - } - - function flatIndexToGroupIndex(index) { - var firstItem = 0; - for (var i = 0, len = that._view.tree.length; i < len; i++) { - var group = that._view.tree[i], - size = group.itemsContainer.items.length, - lastItem = firstItem + size - 1; - - if (index >= firstItem && index <= lastItem) { - return { - group: i, - item: index - firstItem - }; - } - - firstItem += size; - } - } - - var oldFirstItem = []; - var firstItem = 0; - if (!that._view._blockSize) { - for (var i = 0, len = this._view.tree.length; i < len; i++) { - oldFirstItem.push(firstItem); - firstItem += this._view.tree[i].itemsContainer.items.length; - } - } - - if (!that._view._blockSize) { - var removed = modifiedElements.filter(function (entry) { - return entry.newIndex === -1 && !entry._removalHandled; - }).sort(function (left, right) { - return right.oldIndex - left.oldIndex; - }); - - for (var i = 0, len = removed.length; i < len; i++) { - var entry = removed[i]; - entry._removalHandled = true; - var itemBox = entry._itemBox; - entry._itemBox = null; - - var groupIndex = flatIndexToGroupIndex(entry.oldIndex); - var group = this._view.tree[groupIndex.group]; - - var container = group.itemsContainer.items[groupIndex.item]; - container.parentNode.removeChild(container); - - if (utilities.hasClass(itemBox, WinJS.UI._selectedClass)) { - utilities.addClass(container, WinJS.UI._selectedClass); - } - - group.itemsContainer.items.splice(groupIndex.item, 1); - - entry.element = container; - } - } - - this._view._modifiedGroups = []; - - var prevElement = this._canvasProxy; - firstItem = 0; - // When groups are disabled, loop thru all of the groups (there's only 1). - // When groups are enabled, loop until either we exhaust all of the groups in the data source - // or we exhaust all of the containers that have been created so far. - for (var i = 0, len = groups.length; i < len && (!this._groupsEnabled() || firstItem < maxContainers) ; i++) { - var groupInfo = groups[i], - existingGroupIndex = this._view.keyToGroupIndex[groupInfo.key], - existingGroup = this._view.tree[existingGroupIndex]; - - if (existingGroup) { - if (that._view._blockSize) { - updateExistingGroupWithBlocks(existingGroup, firstItem, groupInfo.size); - } else { - shift(existingGroup, oldFirstItem[existingGroupIndex], firstItem, groupInfo.size); - addInserted(existingGroup, firstItem, groupInfo.size); - updateExistingGroup(existingGroup, firstItem, groupInfo.size); - } - newTree.push(existingGroup); - newKeyToGroupIndex[groupInfo.key] = newTree.length - 1; - delete this._view.keyToGroupIndex[groupInfo.key]; - - prevElement = existingGroup.itemsContainer.element; - - this._view._modifiedGroups.push({ - oldIndex: existingGroupIndex, - newIndex: newTree.length - 1, - element: existingGroup.header - }); - } else { - var newGroup = addNewGroup(groupInfo, firstItem); - newTree.push(newGroup); - newKeyToGroupIndex[groupInfo.key] = newTree.length - 1; - - this._view._modifiedGroups.push({ - oldIndex: -1, - newIndex: newTree.length - 1, - element: newGroup.header - }); - - prevElement = newGroup.itemsContainer.element; - } - firstItem += groupInfo.size; - } - - var removedBlocks = [], - removedItemsContainers = [], - removedHeaders = [], - removedGroups = this._view.keyToGroupIndex ? Object.keys(this._view.keyToGroupIndex) : []; - - for (var i = 0, len = removedGroups.length; i < len; i++) { - var groupIndex = this._view.keyToGroupIndex[removedGroups[i]], - groupNode = this._view.tree[groupIndex]; - - removedHeaders.push(groupNode.header); - removedItemsContainers.push(groupNode.itemsContainer.element); - - if (this._view._blockSize) { - for (var b = 0; b < groupNode.itemsContainer.itemsBlocks.length; b++) { - var block = groupNode.itemsContainer.itemsBlocks[b]; - for (var n = 0; n < block.items.length; n++) { - removedContainers.push(block.items[n]); - } - } - } else { - for (var n = 0; n < groupNode.itemsContainer.items.length; n++) { - removedContainers.push(groupNode.itemsContainer.items[n]); - } - } - - this._view._modifiedGroups.push({ - oldIndex: groupIndex, - newIndex: -1, - element: groupNode.header - }); - } - - for (var i = 0, len = modifiedElements.length; i < len; i++) { - if (modifiedElements[i].newIndex === -1 && !modifiedElements[i]._removalHandled) { - modifiedElements[i]._removalHandled = true; - var itemBox = modifiedElements[i]._itemBox; - modifiedElements[i]._itemBox = null; - var container; - if (removedContainers.length) { - container = removedContainers.pop(); - utilities.empty(container); - } else { - container = createContainer(); - } - if (utilities.hasClass(itemBox, WinJS.UI._selectedClass)) { - utilities.addClass(container, WinJS.UI._selectedClass); - } - container.appendChild(itemBox); - modifiedElements[i].element = container; - } - } - - this._view.tree = newTree; - this._view.keyToGroupIndex = newKeyToGroupIndex; - this._view.containers = newContainers; - - return { - removedHeaders: removedHeaders, - removedItemsContainers: removedItemsContainers - }; - }, - - _writeProfilerMark: function ListView_writeProfilerMark(text) { - var message = "WinJS.UI.ListView:" + this._id + ":" + text; - msWriteProfilerMark(message); - WinJS.log && WinJS.log(message, null, "listviewprofiler"); - } - }, { - // Static members - - triggerDispose: function () { - /// - /// - /// Triggers the ListView disposal service manually. In normal operation this is triggered - /// at ListView instantiation. However in some scenarios it may be appropriate to run - /// the disposal service manually. - /// - /// - WinJS.UI._disposeControls(); - } - - }); - WinJS.Class.mix(ListView, WinJS.Utilities.createEventProperties( - "iteminvoked", - "groupheaderinvoked", - "selectionchanging", - "selectionchanged", - "loadingstatechanged", - "keyboardnavigating", - "contentanimating", - "itemdragstart", - "itemdragenter", - "itemdragend", - "itemdragbetween", - "itemdragleave", - "itemdragchanged", - "itemdragdrop", - "accessibilityannotationcomplete")); - WinJS.Class.mix(ListView, WinJS.UI.DOMEventMixin); - return ListView; - }), - - _isSelectionRendered: function ListView_isSelectionRendered(itemBox) { - // The tree is changed at pointerDown but _selectedClass is added only when the user drags an item below the selection threshold so checking for _selectedClass is not reliable. - return itemBox.querySelectorAll(WinJS.UI._selectionPartsSelector).length > 0; - } - }); - -})(this, WinJS); - - -(function repeaterInit(WinJS) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// Uses templates to generate HTML from a set of data. - /// - /// - /// - /// ]]> - /// The Repeater control itself - /// - /// - /// - Repeater: WinJS.Namespace._lazy(function () { - var UI = WinJS.UI; - var Utilities = WinJS.Utilities; - - // Constants - var ITEMSLOADED = "itemsloaded", - ITEMCHANGING = "itemchanging", - ITEMCHANGED = "itemchanged", - ITEMINSERTING = "iteminserting", - ITEMINSERTED = "iteminserted", - ITEMMOVING = "itemmoving", - ITEMMOVED = "itemmoved", - ITEMREMOVING = "itemremoving", - ITEMREMOVED = "itemremoved", - ITEMSRELOADING = "itemsreloading", - ITEMSRELOADED = "itemsreloaded"; - - var createEvent = Utilities._createEventProperty; - - // Class Names - var repeaterClass = "win-repeater"; - - function stringifyItem(dataItem) { - // Repeater uses this as its default renderer when no template is provided. - var itemElement = document.createElement("div"); - itemElement.innerText = JSON.stringify(dataItem); - return itemElement; - } - - // Statics - var strings = { - get duplicateConstruction() { return WinJS.Resources._getWinJSString("ui/duplicateConstruction").value; }, - get asynchronousRender() { return WinJS.Resources._getWinJSString("ui/asynchronousRender").value; }, - get repeaterReentrancy() { return WinJS.Resources._getWinJSString("ui/repeaterReentrancy").value; }, - }; - - var Repeater = WinJS.Class.define(function Repeater_ctor(element, options) { - /// - /// - /// Creates a new Repeater control. - /// - /// - /// The DOM element that will host the new control. The Repeater will create an element if this value is null. - /// - /// - /// An object that contains one or more property/value pairs to apply to the - /// new Repeater. Each property of the options object corresponds to one of the - /// object's properties or events. Event names must begin with "on". - /// - /// - /// The new Repeater control. - /// - /// - - // Check to make sure we weren't duplicated - if (element && element.winControl) { - throw new WinJS.ErrorFromName("WinJS.UI.Repeater.DuplicateConstruction", strings.duplicateConstruction); - } - - this._element = element || document.createElement("div"); - this._id = this._element.id || this._element.uniqueID; - this._writeProfilerMark("constructor,StartTM"); - options = options || {}; - Utilities.addClass(this._element, "win-repeater win-disposable"); - - this._render = null; - this._modifying = false; - this._disposed = false; - this._element.winControl = this; - this._dataListeners = { - itemchanged: this._dataItemChangedHandler.bind(this), - iteminserted: this._dataItemInsertedHandler.bind(this), - itemmoved: this._dataItemMovedHandler.bind(this), - itemremoved: this._dataItemRemovedHandler.bind(this), - reload: this._dataReloadHandler.bind(this), - }; - - // Consume Repeater innerHTML and return a template. - var inlineTemplate = this._extractInlineTemplate(); - this._initializing = true; - // Use the inlinetemplate if a parameter was not given. - // Either way, Repeater's innerHTML has now been consumed. - this.template = options.template || inlineTemplate; - - this.data = options.data; - this._initializing = false; - - UI._setOptions(this, options, true); // Events only - - this._repeatedDOM = []; - this._renderAllItems(); - this.dispatchEvent(ITEMSLOADED, {}); - - this._writeProfilerMark("constructor,StopTM"); - }, { - - /// - element: { - get: function () { - return this._element; - } - }, - - /// - /// Gets or sets the WinJS.Binding.List that provides the Repeater control with items to display. - /// - data: { - get: function () { return this._data; }, - set: function (data) { - this._writeProfilerMark("data.set,StartTM"); - if (this._data) { - this._removeDataListeners(); - }; - this._data = data || new WinJS.Binding.List(); - this._addDataListeners(); - if (!this._initializing) { - this._reloadRepeater(true); - this.dispatchEvent(ITEMSLOADED, {}); - } - this._writeProfilerMark("data.set,StopTM"); - } - }, - - /// - /// Gets or sets a Template or custom rendering function that defines the HTML of each item within the Repeater. - /// - template: { - get: function () { return this._template; }, - set: function (template) { - this._writeProfilerMark("template.set,StartTM"); - this._template = (template || stringifyItem); - this._render = WinJS.Utilities._syncRenderer(this._template, this.element.tagName); - if (!this._initializing) { - this._reloadRepeater(true); - this.dispatchEvent(ITEMSLOADED, {}); - } - this._writeProfilerMark("template.set,StopTM"); - } - }, - - /// - length: { - get: function () { return this._repeatedDOM.length; }, - }, - - elementFromIndex: function Repeater_elementFromIndex(index) { - /// - /// - /// Returns the HTML element for the item with the specified index. - /// - /// - /// The index of the item. - /// - /// - /// The DOM element for the specified item. - /// - /// - return this._repeatedDOM[index]; - }, - - dispose: function Repeater_dispose() { - /// - /// - /// Prepare this Repeater for garbage collection. - /// - /// - if (this._disposed) { - return; - } - this._disposed = true; // Mark this control as disposed. - this._removeDataListeners(); - this._data = null; - this._template = null; - for (var i = 0, len = this._repeatedDOM.length; i < len; i++) { - WinJS.Utilities._disposeElement(this._repeatedDOM[i]); - } - }, - - /// - /// Raised when the Repeater has finished loading a new set of data. This event is only fired on construction - /// or when the Repeater control's data source or template is replaced. - /// - onitemsloaded: createEvent(ITEMSLOADED), - - /// - /// Raised after an item in the Repeater control's data source changes but before the corresponding DOM element has been updated. - /// - onitemchanging: createEvent(ITEMCHANGING), - - /// - /// Raised after an item in the Repeater control's data source changes and after the corresponding DOM element has been updated. - /// - onitemchanged: createEvent(ITEMCHANGED), - - /// - /// Raised after an item has been added to the Repeater control's data source but before the corresponding DOM element has been added. - /// - oniteminserting: createEvent(ITEMINSERTING), - - /// - /// Raised after an item has been added to the Repeater control's data source and after the corresponding DOM element has been added. - /// - oniteminserted: createEvent(ITEMINSERTED), - - /// - /// Raised after an item has been moved from one index to another in the Repeater control's data source but before the corresponding DOM element has been moved. - /// - onitemmoving: createEvent(ITEMMOVING), - - /// - /// Raised after an item has been moved from one index to another in the Repeater control's data source and after the corresponding DOM element has been moved. - /// - onitemmoved: createEvent(ITEMMOVED), - - /// - /// Raised after an item has been removed from the Repeater control's data source but before the corresponding DOM element has been removed. - /// - onitemremoving: createEvent(ITEMREMOVING), - - /// - /// Raised after an item has been removed from one index to another in the Repeater control's data source and after the corresponding DOM element has been removed. - /// - onitemremoved: createEvent(ITEMREMOVED), - - /// - /// The list has been refreshed and any references to data in the list may be incorrect. - /// Raised after the Repeater control's underlying data has been updated but before the updated HTML has been reloaded. - /// - onitemsreloading: createEvent(ITEMSRELOADING), - - /// - /// Raised after the Repeater control's underlying data has been updated and after the updated HTML has been reloaded. - /// - onitemsreloaded: createEvent(ITEMSRELOADED), - - _extractInlineTemplate: function Repeater_extractInlineTemplate() { - // Creates and returns a WinJS.BindingTemplate from the Repeater innerHTML. - if (this._element.firstElementChild) { - var templateElement = document.createElement(this._element.tagName); - while (this._element.firstElementChild) { - // Move each child element from the Repeater to the Template Element - templateElement.appendChild(this._element.firstElementChild); - } - return new WinJS.Binding.Template(templateElement, { extractChild: true }); - } - }, - - _renderAllItems: function Repeater_renderAllItems() { - var fragment = document.createDocumentFragment(); - for (var i = 0, len = this._data.length; i < len; i++) { - var renderedItem = this._render(this._data.getAt(i)); - if (!renderedItem) { - throw new WinJS.ErrorFromName("WinJS.UI.Repeater.AsynchronousRender", strings.asynchronousRender); - - } - fragment.appendChild(renderedItem); - this._repeatedDOM.push(renderedItem); - } - this._element.appendChild(fragment); - }, - - _reloadRepeater: function Repeater_reloadRepeater(shouldDisposeElements) { - this._unloadRepeatedDOM(shouldDisposeElements); - this._repeatedDOM = []; - this._renderAllItems(); - }, - - _unloadRepeatedDOM: function Repeater_unloadRepeatedDOM(shouldDisposeElements) { - for (var i = 0, len = this._repeatedDOM.length; i < len; i++) { - if (!!shouldDisposeElements) { - // this_dataReloadHandler uses this to defer disposal until after animations have completed, - // at which point it manually disposes each element. - WinJS.Utilities._disposeElement(this._repeatedDOM[i]); - } - this._element.removeChild(this._repeatedDOM[i]); - } - }, - - _addDataListeners: function Repeater_addDataListeners() { - Object.keys(this._dataListeners).forEach(function (eventName) { - this._data.addEventListener(eventName, this._dataListeners[eventName], false); - }.bind(this)); - }, - - _beginModification: function Repeater_beginModification() { - if (this._modifying) { - throw new WinJS.ErrorFromName("WinJS.UI.Repeater.RepeaterModificationReentrancy", strings.repeaterReentrancy); - } - this._modifying = true; - }, - - _endModification: function Repeater_endModification() { - this._modifying = false; - }, - - _removeDataListeners: function Repeater_removeDataListeners() { - Object.keys(this._dataListeners).forEach(function (eventName) { - this._data.removeEventListener(eventName, this._dataListeners[eventName], false); - }.bind(this)); - }, - - _dataItemChangedHandler: function Repeater_dataItemChangedHandler(eventInfo) { - // Handles the 'itemchanged' event fired by WinJS.Binding.List - - this._beginModification(); - var animationPromise; - - var root = this._element; - var index = eventInfo.detail.index; - var renderedItem = this._render(eventInfo.detail.newValue); - if (!renderedItem) { - throw new WinJS.ErrorFromName("WinJS.UI.Repeater.AsynchronousRender", strings.asynchronousRender); - } - - // Append to the event object - if (this._repeatedDOM[index]) { - eventInfo.detail.oldElement = this._repeatedDOM[index]; - } - eventInfo.detail.newElement = renderedItem; - eventInfo.detail.setPromise = function setPromise(delayPromise) { - animationPromise = delayPromise; - }; - - this._writeProfilerMark(ITEMCHANGING + ",info"); - this.dispatchEvent(ITEMCHANGING, eventInfo.detail); - - // Make the change - var oldItem = null; - if (index < this._repeatedDOM.length) { - oldItem = this._repeatedDOM[index]; - root.replaceChild(renderedItem, oldItem); - this._repeatedDOM[index] = renderedItem; - } else { - root.appendChild(renderedItem); - this._repeatedDOM.push(renderedItem); - } - - this._endModification(); - this._writeProfilerMark(ITEMCHANGED + ",info"); - this.dispatchEvent(ITEMCHANGED, eventInfo.detail); - - if (oldItem) { // Give the option to delay element disposal. - WinJS.Promise.as(animationPromise).done(function () { - WinJS.Utilities._disposeElement(oldItem); - }.bind(this)); - } - }, - - _dataItemInsertedHandler: function Repeater_dataItemInsertedHandler(eventInfo) { - // Handles the 'iteminserted' event fired by WinJS.Binding.List - - this._beginModification(); - var index = eventInfo.detail.index; - var renderedItem = this._render(eventInfo.detail.value); - if (!renderedItem) { - throw new WinJS.ErrorFromName("WinJS.UI.Repeater.AsynchronousRender", strings.asynchronousRender); - } - - var root = this._element; - - eventInfo.detail.affectedElement = renderedItem; - this._writeProfilerMark(ITEMINSERTING + ",info"); - this.dispatchEvent(ITEMINSERTING, eventInfo.detail); - - if (index < this._repeatedDOM.length) { - var nextSibling = this._repeatedDOM[index]; - root.insertBefore(renderedItem, nextSibling); - } else { - root.appendChild(renderedItem); - } - - // Update collection of rendered elements - this._repeatedDOM.splice(index, 0, renderedItem); - - this._endModification(); - this._writeProfilerMark(ITEMINSERTED + ",info"); - this.dispatchEvent(ITEMINSERTED, eventInfo.detail); - - }, - - _dataItemMovedHandler: function Repeater_dataItemMovedHandler(eventInfo) { - // Handles the 'itemmoved' event fired by WinJS.Binding.List - - this._beginModification(); - - var movingItem = this._repeatedDOM[eventInfo.detail.oldIndex]; - - // Fire the event before we start the move. - eventInfo.detail.affectedElement = movingItem; - this._writeProfilerMark(ITEMMOVING + ",info"); - this.dispatchEvent(ITEMMOVING, eventInfo.detail); - - // Remove - this._repeatedDOM.splice(eventInfo.detail.oldIndex, 1)[0]; - movingItem.parentNode.removeChild(movingItem); - - // Insert - if (eventInfo.detail.newIndex < (this._data.length) - 1) { - var nextSibling = this._repeatedDOM[eventInfo.detail.newIndex]; - this._element.insertBefore(movingItem, nextSibling); - this._repeatedDOM.splice(eventInfo.detail.newIndex, 0, movingItem); - } else { - this._repeatedDOM.push(movingItem); - this._element.appendChild(movingItem); - } - - this._endModification(); - this._writeProfilerMark(ITEMMOVED + ",info"); - this.dispatchEvent(ITEMMOVED, eventInfo.detail); - }, - - _dataItemRemovedHandler: function Repeater_dataItemRemoveHandler(eventInfo) { - // Handles the 'itemremoved' event fired by WinJS.Binding.List - - this._beginModification(); - var animationPromise; - var oldItem = this._repeatedDOM[eventInfo.detail.index]; - - // Trim 'value' and 'key' from the eventInfo.details that Binding.List gave for the removal case, - // since both of those properties already exist inside of eventInfo.details.item. - var eventDetail = { affectedElement: oldItem, index: eventInfo.detail.index, item: eventInfo.detail.item }; - eventDetail.setPromise = function setPromise(delayPromise) { - animationPromise = delayPromise; - } - - this._writeProfilerMark(ITEMREMOVING + ",info"); - this.dispatchEvent(ITEMREMOVING, eventDetail); - - oldItem.parentNode.removeChild(oldItem); - this._repeatedDOM.splice(eventInfo.detail.index, 1); - - this._endModification(); - this._writeProfilerMark(ITEMREMOVED + ",info"); - this.dispatchEvent(ITEMREMOVED, eventDetail); - - WinJS.Promise.as(animationPromise).done(function () { - WinJS.Utilities._disposeElement(oldItem); - }.bind(this)); - }, - - _dataReloadHandler: function Repeater_dataReloadHandler(eventInfo) { - // Handles the 'reload' event fired by WinJS.Binding.List whenever it performs operations such as reverse() or sort() - - this._beginModification(); - var animationPromise; - - var shallowCopyBefore = this._repeatedDOM.slice(0); - var eventDetail = { affectedElements: shallowCopyBefore }; - eventDetail.setPromise = function (delayPromise) { - animationPromise = delayPromise; - } - - this._writeProfilerMark(ITEMSRELOADING + ",info"); - this.dispatchEvent(ITEMSRELOADING, eventDetail); - this._reloadRepeater(false /*shouldDisposeElements */); - - var shallowCopyAfter = this._repeatedDOM.slice(0); - this._endModification(); - this._writeProfilerMark(ITEMSRELOADED + ",info"); - this.dispatchEvent(ITEMSRELOADED, { affectedElements: shallowCopyAfter }); - - WinJS.Promise.as(animationPromise).done(function () { // Gives the option to defer disposal. - for (var i = 0, len = shallowCopyBefore.length; i < len; i++) { - WinJS.Utilities._disposeElement(shallowCopyBefore[i]); - } - }.bind(this)); - }, - - _writeProfilerMark: function Repeater_writeProfilerMark(text) { - msWriteProfilerMark("WinJS.UI.Repeater:" + this._id + ":" + text); - } - }, { - isDeclarativeControlContainer: true, - }); - WinJS.Class.mix(Repeater, UI.DOMEventMixin); - return Repeater; - }) - }); - -})(WinJS); - -(function selectionManagerInit(global, WinJS, undefined) { - "use strict"; - - var utilities = WinJS.Utilities, - Promise = WinJS.Promise; - - WinJS.Namespace.define("WinJS.UI", { - _ItemSet: WinJS.Namespace._lazy(function () { - var _ItemSet = WinJS.Class.define(function _ItemSet_ctor(listView, ranges, count) { - this._listView = listView; - this._ranges = ranges; - this._itemsCount = count; - }); - _ItemSet.prototype = { - getRanges: function () { - var ranges = []; - for (var i = 0, len = this._ranges.length; i < len; i++) { - var range = this._ranges[i]; - ranges.push({ - firstIndex: range.firstIndex, - lastIndex: range.lastIndex, - firstKey: range.firstKey, - lastKey: range.lastKey - }); - } - return ranges; - }, - - getItems: function () { - return WinJS.UI.getItemsFromRanges(this._listView._itemsManager.dataSource, this._ranges); - }, - - isEverything: function () { - return this.count() === this._itemsCount; - }, - - count: function () { - var count = 0; - for (var i = 0, len = this._ranges.length; i < len; i++) { - var range = this._ranges[i]; - count += range.lastIndex - range.firstIndex + 1; - } - return count; - }, - - getIndices: function () { - var indices = []; - for (var i = 0, len = this._ranges.length; i < len; i++) { - var range = this._ranges[i]; - for (var n = range.firstIndex; n <= range.lastIndex; n++) { - indices.push(n); - } - } - return indices; - } - }; - return _ItemSet; - }), - - getItemsFromRanges: function (dataSource, ranges) { - var listBinding = dataSource.createListBinding(), - promises = []; - - function getIndices() { - var indices = []; - for (var i = 0, len = ranges.length; i < len; i++) { - var range = ranges[i]; - for (var j = range.firstIndex; j <= range.lastIndex; j++) { - indices.push(j); - } - } - return Promise.wrap(indices); - } - - return getIndices().then(function (indices) { - for (var i = 0; i < indices.length; i++) { - promises.push(listBinding.fromIndex(indices[i])); - } - - return WinJS.Promise.join(promises).then(function (items) { - listBinding.release(); - return items; - }); - }); - }, - - _Selection: WinJS.Namespace._lazy(function () { - function isEverythingRange(ranges) { - return ranges && ranges.firstIndex === 0 && ranges.lastIndex === Number.MAX_VALUE; - } - - return WinJS.Class.derive(WinJS.UI._ItemSet, function (listView, indexesAndRanges) { - this._listView = listView; - this._itemsCount = -1; - this._ranges = []; - if (indexesAndRanges) { - this.set(indexesAndRanges); - } - }, { - clear: function () { - /// - /// - /// Clears the selection. - /// - /// - /// A Promise that is fulfilled when the clear operation completes. - /// - /// - - this._releaseRanges(this._ranges); - this._ranges = []; - return Promise.wrap(); - }, - - set: function (items) { - /// - /// - /// Clears the current selection and replaces it with the specified items. - /// - /// - /// The indexes or keys of the items that make up the selection. - /// You can provide different types of objects for the items parameter: - /// you can specify an index, a key, or a range of indexes. - /// It can also be an array that contains one or more of these objects. - /// - /// - /// A Promise that is fulfilled when the operation completes. - /// - /// - - // A range with lastIndex set to Number.MAX_VALUE used to mean selectAll. Passing such range to set was equivalent to selectAll. This code preserves this behavior. - if (!isEverythingRange(items)) { - this._releaseRanges(this._ranges); - this._ranges = []; - - var that = this; - return this._execute("_set", items).then(function () { - that._ranges.sort(function (left, right) { - return left.firstIndex - right.firstIndex; - }); - return that._ensureKeys(); - }).then(function () { - return that._ensureCount(); - }); - } else { - return this.selectAll(); - } - }, - - add: function (items) { - /// - /// - /// Adds one or more items to the selection. - /// - /// - /// The indexes or keys of the items to add. - /// You can provide different types of objects for the items parameter: - /// you can specify an index, a key, or a range of indexes. - /// It can also be an array that contains one or more of these objects. - /// - /// - /// A Promise that is fulfilled when the operation completes. - /// - /// - - if (!isEverythingRange(items)) { - var that = this; - return this._execute("_add", items).then(function () { - return that._ensureKeys(); - }).then(function () { - return that._ensureCount(); - }); - } else { - return this.selectAll(); - } - }, - - remove: function (items) { - /// - /// - /// Removes the specified items from the selection. - /// - /// - /// The indexes or keys of the items to remove. You can provide different types of objects for the items parameter: - /// you can specify an index, a key, or a range of indexes. - /// It can also be an array that contains one or more of these objects. - /// - /// - /// A Promise that is fulfilled when the operation completes. - /// - /// - - var that = this; - return this._execute("_remove", items).then(function () { - return that._ensureKeys(); - }); - }, - - selectAll: function () { - /// - /// - /// Adds all the items in the ListView to the selection. - /// - /// - /// A Promise that is fulfilled when the operation completes. - /// - /// - - var that = this; - return that._ensureCount().then(function () { - if (that._itemsCount) { - var range = { - firstIndex: 0, - lastIndex: that._itemsCount - 1, - }; - that._retainRange(range); - that._releaseRanges(that._ranges); - that._ranges = [range]; - return that._ensureKeys(); - } - }); - }, - - /*#DBG - _assertValid: function () { - for (var i = 0, len = this._ranges.length; i < len; i++) { - var range = this._ranges[i]; - _ASSERT(range.firstIndex <= range.lastIndex); - _ASSERT(!i || this._ranges[i - 1].lastIndex < range.firstIndex); - } - return true; - }, - #DBG*/ - - _execute: function (operation, items) { - var that = this, - keysSupported = !!that._getListBinding().fromKey, - array = Array.isArray(items) ? items : [items], - promises = [Promise.wrap()]; - - function toRange(type, first, last) { - var retVal = {}; - retVal["first" + type] = first; - retVal["last" + type] = last; - return retVal; - } - - function handleKeys(range) { - var binding = that._getListBinding(); - - var promise = Promise.join([binding.fromKey(range.firstKey), binding.fromKey(range.lastKey)]).then(function (items) { - if (items[0] && items[1]) { - range.firstIndex = items[0].index; - range.lastIndex = items[1].index; - that[operation](range); - } - return range; - }); - promises.push(promise); - } - - for (var i = 0, len = array.length; i < len; i++) { - var item = array[i]; - if (typeof item === "number") { - this[operation](toRange("Index", item, item)); - } else if (item) { - if (keysSupported && item.key !== undefined) { - handleKeys(toRange("Key", item.key, item.key)); - } else if (keysSupported && item.firstKey !== undefined && item.lastKey !== undefined) { - handleKeys(toRange("Key", item.firstKey, item.lastKey)); - } else if (item.index !== undefined && typeof item.index === "number") { - this[operation](toRange("Index", item.index, item.index)); - } else if (item.firstIndex !== undefined && item.lastIndex !== undefined && - typeof item.firstIndex === "number" && typeof item.lastIndex === "number") { - this[operation](toRange("Index", item.firstIndex, item.lastIndex)); - } - } - } - - return Promise.join(promises); - }, - - _set: function (range) { - this._retainRange(range); - this._ranges.push(range); - }, - - _add: function (newRange) { - var that = this, - prev = null, - range, - inserted; - - var merge = function (left, right) { - if (right.lastIndex > left.lastIndex) { - left.lastIndex = right.lastIndex; - left.lastKey = right.lastKey; - if (left.lastPromise) { - left.lastPromise.release(); - } - left.lastPromise = that._getListBinding().fromIndex(left.lastIndex).retain(); - } - } - - for (var i = 0, len = this._ranges.length; i < len; i++) { - range = this._ranges[i]; - if (newRange.firstIndex < range.firstIndex) { - var mergeWithPrev = prev && newRange.firstIndex < (prev.lastIndex + 1); - if (mergeWithPrev) { - inserted = i - 1; - merge(prev, newRange); - } else { - this._insertRange(i, newRange); - inserted = i; - } - break; - } else if (newRange.firstIndex === range.firstIndex) { - merge(range, newRange); - inserted = i; - break; - } - prev = range; - } - - if (inserted === undefined) { - var last = this._ranges.length ? this._ranges[this._ranges.length - 1] : null, - mergeWithLast = last && newRange.firstIndex < (last.lastIndex + 1); - if (mergeWithLast) { - merge(last, newRange); - } else { - this._retainRange(newRange); - this._ranges.push(newRange); - } - } else { - prev = null; - for (i = inserted + 1, len = this._ranges.length; i < len; i++) { - range = this._ranges[i]; - if (newRange.lastIndex < range.firstIndex) { - mergeWithPrev = prev && prev.lastIndex > newRange.lastIndex; - if (mergeWithPrev) { - merge(this._ranges[inserted], prev); - } - this._removeRanges(inserted + 1, i - inserted - 1); - break; - } else if (newRange.lastIndex === range.firstIndex) { - merge(this._ranges[inserted], range); - this._removeRanges(inserted + 1, i - inserted); - break; - } - prev = range; - } - if (i >= len) { - merge(this._ranges[inserted], this._ranges[len - 1]); - this._removeRanges(inserted + 1, len - inserted - 1); - } - } - }, - - _remove: function (toRemove) { - var that = this; - - function retainPromise(index) { - return that._getListBinding().fromIndex(index).retain(); - } - - // This method is called when a range needs to be unselected. It is inspecting every range in the current selection comparing - // it to the range which is being unselected and it is building an array of new selected ranges - var ranges = []; - for (var i = 0, len = this._ranges.length; i < len; i++) { - var range = this._ranges[i]; - if (range.lastIndex < toRemove.firstIndex || range.firstIndex > toRemove.lastIndex) { - // No overlap with the unselected range - ranges.push(range); - } else if (range.firstIndex < toRemove.firstIndex && range.lastIndex >= toRemove.firstIndex && range.lastIndex <= toRemove.lastIndex) { - // The end of this range is being unselected - ranges.push({ - firstIndex: range.firstIndex, - firstKey: range.firstKey, - firstPromise: range.firstPromise, - lastIndex: toRemove.firstIndex - 1, - lastPromise: retainPromise(toRemove.firstIndex - 1) - }); - range.lastPromise.release(); - } else if (range.lastIndex > toRemove.lastIndex && range.firstIndex >= toRemove.firstIndex && range.firstIndex <= toRemove.lastIndex) { - // The beginning of this range is being unselected - ranges.push({ - firstIndex: toRemove.lastIndex + 1, - firstPromise: retainPromise(toRemove.lastIndex + 1), - lastIndex: range.lastIndex, - lastKey: range.lastKey, - lastPromise: range.lastPromise - }); - range.firstPromise.release(); - } else if (range.firstIndex < toRemove.firstIndex && range.lastIndex > toRemove.lastIndex) { - // The middle part of this range is being unselected - ranges.push({ - firstIndex: range.firstIndex, - firstKey: range.firstKey, - firstPromise: range.firstPromise, - lastIndex: toRemove.firstIndex - 1, - lastPromise: retainPromise(toRemove.firstIndex - 1), - }); - ranges.push({ - firstIndex: toRemove.lastIndex + 1, - firstPromise: retainPromise(toRemove.lastIndex + 1), - lastIndex: range.lastIndex, - lastKey: range.lastKey, - lastPromise: range.lastPromise - }); - } else { - // The whole range is being unselected - //#DBG _ASSERT(range.firstIndex >= toRemove.firstIndex && range.lastIndex <= toRemove.lastIndex); - range.firstPromise.release(); - range.lastPromise.release(); - } - } - this._ranges = ranges; - }, - - _ensureKeys: function () { - var promises = [Promise.wrap()]; - var that = this; - - var ensureKey = function (which, range) { - var keyProperty = which + "Key"; - - if (!range[keyProperty]) { - var promise = range[which + "Promise"]; - promise.then(function (item) { - if (item) { - range[keyProperty] = item.key; - } - }); - return promise; - } else { - return Promise.wrap(); - } - } - - for (var i = 0, len = this._ranges.length; i < len; i++) { - var range = this._ranges[i]; - promises.push(ensureKey("first", range)); - promises.push(ensureKey("last", range)); - } - - Promise.join(promises).then(function () { - that._ranges = that._ranges.filter(function (range) { - return range.firstKey && range.lastKey; - }); - }); - return Promise.join(promises); - }, - - _mergeRanges: function (target, source) { - //#DBG _ASSERT(!target.lastPromise && !source.lastPromise); - target.lastIndex = source.lastIndex; - target.lastKey = source.lastKey; - }, - - _isIncluded: function (index) { - if (this.isEverything()) { - return true; - } else { - for (var i = 0, len = this._ranges.length; i < len; i++) { - var range = this._ranges[i]; - if (range.firstIndex <= index && index <= range.lastIndex) { - return true; - } - } - return false; - } - }, - - _ensureCount: function () { - var that = this; - return this._listView._itemsCount().then(function (count) { - that._itemsCount = count; - }); - }, - - _insertRange: function (index, newRange) { - this._retainRange(newRange); - this._ranges.splice(index, 0, newRange); - }, - - _removeRanges: function (index, howMany) { - for (var i = 0; i < howMany; i++) { - this._releaseRange(this._ranges[index + i]); - } - this._ranges.splice(index, howMany); - }, - - _retainRange: function (range) { - if (!range.firstPromise) { - range.firstPromise = this._getListBinding().fromIndex(range.firstIndex).retain(); - } - if (!range.lastPromise) { - range.lastPromise = this._getListBinding().fromIndex(range.lastIndex).retain(); - } - }, - - _retainRanges: function () { - for (var i = 0, len = this._ranges.length; i < len; i++) { - this._retainRange(this._ranges[i]); - } - }, - - _releaseRange: function (range) { - range.firstPromise.release(); - range.lastPromise.release(); - }, - - _releaseRanges: function (ranges) { - for (var i = 0, len = ranges.length; i < len; ++i) { - this._releaseRange(ranges[i]); - } - }, - - _getListBinding: function () { - return this._listView._itemsManager._listBinding; - } - }, { - supportedForProcessing: false, - }); - }), - - // This component is responsible for holding selection state - _SelectionManager: WinJS.Namespace._lazy(function () { - var _SelectionManager = function (listView) { - this._listView = listView; - this._selected = new WinJS.UI._Selection(this._listView); - // Don't rename this member. Some apps reference it. - this._pivot = WinJS.UI._INVALID_INDEX; - this._focused = { type: WinJS.UI.ObjectType.item, index: 0 }; - this._pendingChange = Promise.wrap(); - }; - _SelectionManager.prototype = { - count: function () { - /// - /// - /// Returns the number of items in the selection. - /// - /// - /// The number of items in the selection. - /// - /// - return this._selected.count(); - }, - - getIndices: function () { - /// - /// - /// Returns a list of the indexes for the items in the selection. - /// - /// - /// The list of indexes for the items in the selection as an array of Number objects. - /// - /// - return this._selected.getIndices(); - }, - - getItems: function () { - /// - /// - /// Returns an array that contains the items in the selection. - /// - /// - /// A Promise that contains an array of the requested IItem objects. - /// - /// - - return this._selected.getItems(); - }, - - getRanges: function () { - /// - /// - /// Gets an array of the index ranges for the selected items. - /// - /// - /// An array that contains an ISelectionRange object for each index range in the selection. - /// - /// - return this._selected.getRanges(); - }, - - isEverything: function () { - /// - /// - /// Returns a value that indicates whether the selection contains every item in the data source. - /// - /// - /// true if the selection contains every item in the data source; otherwise, false. - /// - /// - return this._selected.isEverything(); - }, - - set: function (items) { - /// - /// - /// Clears the current selection and replaces it with the specified items. - /// - /// - /// The indexes or keys of the items that make up the selection. - /// You can provide different types of objects for the items parameter: - /// you can specify an index, a key, or a range of indexes. - /// It can also be an array that contains one or more of these objects. - /// - /// - /// A Promise that is fulfilled when the operation completes. - /// - /// - var that = this, - signal = new WinJS._Signal(); - return this._synchronize(signal).then(function () { - var newSelection = new WinJS.UI._Selection(that._listView); - return newSelection.set(items).then( - function () { - that._set(newSelection); - signal.complete(); - }, - function (error) { - newSelection.clear(); - signal.complete(); - return WinJS.Promise.wrapError(error); - } - ); - }); - }, - - clear: function () { - /// - /// - /// Clears the selection. - /// - /// - /// A Promise that is fulfilled when the clear operation completes. - /// - /// - - var that = this, - signal = new WinJS._Signal(); - return this._synchronize(signal).then(function () { - var newSelection = new WinJS.UI._Selection(that._listView); - return newSelection.clear().then( - function () { - that._set(newSelection); - signal.complete(); - }, - function (error) { - newSelection.clear(); - signal.complete(); - return WinJS.Promise.wrapError(error); - } - ); - }); - }, - - add: function (items) { - /// - /// - /// Adds one or more items to the selection. - /// - /// - /// The indexes or keys of the items to add. - /// You can provide different types of objects for the items parameter: - /// you can specify an index, a key, or a range of indexes. - /// It can also be an array that contains one or more of these objects. - /// - /// - /// A Promise that is fulfilled when the operation completes. - /// - /// - var that = this, - signal = new WinJS._Signal(); - return this._synchronize(signal).then(function () { - var newSelection = that._cloneSelection(); - return newSelection.add(items).then( - function () { - that._set(newSelection); - signal.complete(); - }, - function (error) { - newSelection.clear(); - signal.complete(); - return WinJS.Promise.wrapError(error); - } - ); - }); - }, - - remove: function (items) { - /// - /// - /// Removes the specified items from the selection. - /// - /// - /// The indexes or keys of the items to remove. You can provide different types of objects for the items parameter: - /// you can specify an index, a key, or a range of indexes. - /// It can also be an array that contains one or more of these objects. - /// - /// - /// A Promise that is fulfilled when the operation completes. - /// - /// - var that = this, - signal = new WinJS._Signal(); - return this._synchronize(signal).then(function () { - var newSelection = that._cloneSelection(); - return newSelection.remove(items).then( - function () { - that._set(newSelection); - signal.complete(); - }, - function (error) { - newSelection.clear(); - signal.complete(); - return WinJS.Promise.wrapError(error); - } - ); - }); - }, - - selectAll: function () { - /// - /// - /// Adds all the items in the ListView to the selection. - /// - /// - /// A Promise that is fulfilled when the operation completes. - /// - /// - var that = this, - signal = new WinJS._Signal(); - return this._synchronize(signal).then(function () { - var newSelection = new WinJS.UI._Selection(that._listView); - return newSelection.selectAll().then( - function () { - that._set(newSelection); - signal.complete(); - }, - function (error) { - newSelection.clear(); - signal.complete(); - return WinJS.Promise.wrapError(error); - } - ); - }); - }, - - _synchronize: function (signal) { - var that = this; - return this._listView._versionManager.unlocked.then(function () { - var currentPendingChange = that._pendingChange; - that._pendingChange = WinJS.Promise.join([currentPendingChange, signal.promise]).then(function () { }); - return currentPendingChange; - }); - }, - - _reset: function () { - this._pivot = WinJS.UI._INVALID_INDEX; - this._setFocused({ type: WinJS.UI.ObjectType.item, index: 0 }, this._keyboardFocused()); - this._pendingChange.cancel(); - this._pendingChange = Promise.wrap(); - this._selected.clear(); - this._selected = new WinJS.UI._Selection(this._listView); - }, - - _dispose: function () { - this._selected.clear(); - this._selected = null; - this._listView = null; - }, - - _set: function (newSelection) { - var that = this; - return this._fireSelectionChanging(newSelection).then(function (approved) { - if (approved) { - that._selected.clear(); - that._selected = newSelection; - that._listView._updateSelection(); - that._fireSelectionChanged(); - } else { - newSelection.clear(); - } - return approved; - }); - }, - - _fireSelectionChanging: function (newSelection) { - var eventObject = document.createEvent("CustomEvent"), - newSelectionUpdated = Promise.wrap(); - - eventObject.initCustomEvent("selectionchanging", true, true, { - newSelection: newSelection, - preventTapBehavior: function () { - }, - setPromise: function (promise) { - /// - /// - /// Used to inform the ListView that asynchronous work is being performed, and that this - /// event handler should not be considered complete until the promise completes. - /// - /// - /// The promise to wait for. - /// - /// - - newSelectionUpdated = promise; - } - }); - - var approved = this._listView._element.dispatchEvent(eventObject); - return newSelectionUpdated.then(function () { - return approved; - }); - }, - - _fireSelectionChanged: function () { - var eventObject = document.createEvent("CustomEvent"); - eventObject.initCustomEvent("selectionchanged", true, false, null); - this._listView._element.dispatchEvent(eventObject); - }, - - _getFocused: function () { - return { type: this._focused.type, index: this._focused.index }; - }, - - _setFocused: function (entity, keyboardFocused) { - this._focused = { type: entity.type, index: entity.index }; - this._focusedByKeyboard = keyboardFocused; - }, - - _keyboardFocused: function () { - return this._focusedByKeyboard; - }, - - _updateCount: function (count) { - this._selected._itemsCount = count; - }, - - _isIncluded: function (index) { - return this._selected._isIncluded(index); - }, - - _cloneSelection: function () { - var newSelection = new WinJS.UI._Selection(this._listView); - newSelection._ranges = this._selected.getRanges(); - newSelection._itemsCount = this._selected._itemsCount; - newSelection._retainRanges(); - return newSelection; - } - }; - _SelectionManager.supportedForProcessing = false; - return _SelectionManager; - }) - }); - -})(this, WinJS); - -(function virtualizeContentsViewInit(global, WinJS, undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - _VirtualizeContentsView: WinJS.Namespace._lazy(function () { - var utilities = WinJS.Utilities, - Promise = WinJS.Promise, - Scheduler = WinJS.Utilities.Scheduler; - - function cooperativeQueueWorker(info) { - var workItems = info.job._workItems; - var work; - while (workItems.length && !info.shouldYield) { - work = workItems.shift(); - work(); - } - - info.setWork(cooperativeQueueWorker); - - if (!workItems.length) { - info.job.pause(); - } - } - - function scheduleQueueJob(priority, name) { - - var job = Scheduler.schedule(cooperativeQueueWorker, priority, null, name); - - job._workItems = []; - - job.addWork = function (work, head) { - if (head) { - this._workItems.unshift(work); - } else { - this._workItems.push(work); - } - this.resume(); - }; - - job.clearWork = function () { - this._workItems.length = 0; - }; - - job.dispose = function () { - this.cancel(); - this._workItems.length = 0; - } - - return job; - } - - function shouldWaitForSeZo(listView) { - return listView._zooming || listView._pinching; - } - - function waitForSeZo(listView, timeout) { - // waitForSeZo will block until sezo calls endZoom on listview, or a timeout duration has elapsed to - // unblock a potential deadlock between the sezo waiting on container creation, and container creation - // waiting on endZoom. - - if (listView._isZombie()) { return Promise.wrap(); } - if (shouldWaitForSeZo(listView)) { - if (+timeout !== timeout) { - timeout = WinJS.UI._VirtualizeContentsView._waitForSeZoTimeoutDuration; - } - //To improve SeZo's zoom animation and pinch detection perf, we want to ensure unimportant task - //is only run while zooming or pinching is not in progress. - return Promise.timeout(WinJS.UI._VirtualizeContentsView._waitForSeZoIntervalDuration).then(function () { - timeout -= WinJS.UI._VirtualizeContentsView._waitForSeZoIntervalDuration; - if (timeout <= 0) { - return true; - } - return waitForSeZo(listView, timeout); - }); - } else { - return Promise.wrap(); - } - } - - function makeFunctor(scrollToFunctor) { - if (typeof scrollToFunctor === "number") { - var pos = scrollToFunctor; - - scrollToFunctor = function () { - return { - position: pos, - direction: "right" - }; - }; - } - return scrollToFunctor; - } - - var _VirtualizeContentsView = function VirtualizeContentsView_ctor(listView) { - this._listView = listView; - this._forceRelayout = false; - this.items = new WinJS.UI._ItemsContainer(listView); - this.firstIndexDisplayed = -1; - this.lastIndexDisplayed = -1; - this.begin = 0; - this.end = 0; - this._realizePass = 1; - this._firstLayoutPass = true; - this._runningAnimations = null; - this._renderCompletePromise = Promise.wrap(); - this._state = new CreatedState(this); - this._createLayoutSignal(); - this._createTreeBuildingSignal(); - this._layoutWork = null; - this._onscreenJob = scheduleQueueJob(Scheduler.Priority.aboveNormal, "on-screen items"); - this._frontOffscreenJob = scheduleQueueJob(Scheduler.Priority.normal, "front off-screen items"); - this._backOffscreenJob = scheduleQueueJob(Scheduler.Priority.belowNormal, "back off-screen items"); - this._scrollbarPos = 0; - this._direction = "right"; - this._scrollToFunctor = makeFunctor(0); - }; - - _VirtualizeContentsView._pagesToPrefetch = 2; - _VirtualizeContentsView._waitForSeZoIntervalDuration = 100; - _VirtualizeContentsView._waitForSeZoTimeoutDuration = 500; - _VirtualizeContentsView._chunkSize = 500; - _VirtualizeContentsView._startupChunkSize = 100; - _VirtualizeContentsView._maxTimePerCreateContainers = 5; - _VirtualizeContentsView._createContainersJobTimeslice = 15; - _VirtualizeContentsView._blocksToRelease = 10; - _VirtualizeContentsView._realizationLevel = { - skip: "skip", - realize: "realize", - normal: "normal" - }; - - _VirtualizeContentsView.prototype = { - - _dispose: function VirtualizeContentsView_dispose() { - this.cleanUp(); - this.items = null; - this._renderCompletePromise && this._renderCompletePromise.cancel(); - this._renderCompletePromise = null; - this._onscreenJob.dispose(); - this._frontOffscreenJob.dispose(); - this._backOffscreenJob.dispose(); - }, - - _createItem: function VirtualizeContentsView_createItem(itemIndex, itemPromise, available, unavailable) { - this._listView._writeProfilerMark("createItem(" + itemIndex + ") " + this._getBoundingRectString(itemIndex) + ",info"); - - var that = this; - that._listView._itemsManager._itemFromItemPromiseThrottled(itemPromise).done( - function (element) { - if (element) { - available(itemIndex, element, that._listView._itemsManager._recordFromElement(element)); - } else { - unavailable(itemIndex); - } - }, - function (err) { - unavailable(itemIndex); - return WinJS.Promise.wrapError(err); - } - ); - }, - - _addItem: function VirtualizeContentsView_addItem(fragment, itemIndex, element, currentPass) { - /*#DBG - if (!WinJS.Utilities.data(element).itemsManagerRecord || WinJS.Utilities.data(element).removeElementMapRecord) { - throw "ACK! Attempt to add an item to the scrollview which hasn't yet been realized"; - } - #DBG*/ - - if (this._realizePass === currentPass) { - var record = this._listView._itemsManager._recordFromElement(element); - - delete this._pendingItemPromises[record.itemPromise.handle]; - - this.items.setItemAt(itemIndex, { - itemBox: null, - container: null, - element: element, - detached: true, - itemsManagerRecord: record - }); - } - }, - - finalItem: function VirtualizeContentsView_finalItem() { - return this.containers ? Promise.wrap(this.containers.length - 1) : Promise.cancel; - }, - - _setSkipRealizationForChange: function (skip) { - if (skip) { - if (this._realizationLevel !== WinJS.UI._VirtualizeContentsView._realizationLevel.realize) { - this._realizationLevel = WinJS.UI._VirtualizeContentsView._realizationLevel.skip; - } - } else { - this._realizationLevel = WinJS.UI._VirtualizeContentsView._realizationLevel.realize; - } - }, - - _realizeItems: function VirtualizeContentsView_realizeItems(fragment, begin, end, count, currentPass, scrollbarPos, direction, firstInView, lastInView, ignoreGaps) { - var perfId = "_realizeItems(" + begin + "-" + (end - 1) + ") visible(" + firstInView + "-" + lastInView + ")"; - - this._listView._writeProfilerMark(perfId + ",StartTM"); - - direction = direction || "right"; - - var counter = end - begin; - var inView = lastInView - firstInView + 1, - inViewCounter = inView, - rightOffscreenCount = end - lastInView - 1, - leftOffscreenCount = firstInView - begin; - var renderCompletePromises = []; - var entranceAnimationSignal = new WinJS._Signal(); - var viewportItemsRealized = new WinJS._Signal(); - var frontItemsRealized = new WinJS._Signal(); - - var that = this; - - function itemIsReady(itemIndex, itemsManagerRecord) { - renderCompletePromises.push(WinJS.Promise._cancelBlocker(itemsManagerRecord.renderComplete)); - - delivered(itemIndex); - } - - function appendItemsToDom(startIndex, endIndex) { - that._listView._writeProfilerMark("_realizeItems_appendedItemsToDom,StartTM"); - if (that._listView._isZombie()) { return; } - - function updateSwipeable(itemData, element, itemBox) { - if (!itemData.updatedSwipeableAttribute && (that._listView.itemsDraggable || that._listView.itemsReorderable || that._listView._swipeable)) { - itemData.itemsManagerRecord.renderComplete.done(function () { - if (that._realizePass === currentPass) { - var dragDisabledOnItem = utilities.hasClass(element, WinJS.UI._nonDraggableClass), - selectionDisabledOnItem = utilities.hasClass(element, WinJS.UI._nonSelectableClass), - dragEnabled = (that._listView.itemsDraggable || that._listView.itemsReorderable), - swipeSelectEnabled = (that._listView._selectionAllowed() && that._listView._swipeBehavior === WinJS.UI.SwipeBehavior.select); - if (dragEnabled && !dragDisabledOnItem) { - itemData.itemBox.draggable = true; - } - - if (that._listView._swipeable && ((dragEnabled && !swipeSelectEnabled && dragDisabledOnItem) || - (swipeSelectEnabled && !dragEnabled && selectionDisabledOnItem) || - (dragDisabledOnItem && selectionDisabledOnItem))) { - utilities.addClass(itemData.itemBox, WinJS.UI._nonSwipeableClass); - } - itemData.updatedSwipeableAttribute = true; - } - }); - } - } - - var itemIndex; - var appendItemsCount = 0; - var firstIndex = -1; - var lastIndex = -1; - for (itemIndex = startIndex; itemIndex <= endIndex; itemIndex++) { - var itemData = that.items.itemDataAt(itemIndex); - if (itemData) { - var element = itemData.element, - itemBox = itemData.itemBox; - - if (!itemBox) { - itemBox = that._listView._itemBoxTemplate.cloneNode(true); - itemData.itemBox = itemBox; - - itemBox.appendChild(element); - utilities.addClass(element, WinJS.UI._itemClass); - - that._listView._setupAriaSelectionObserver(element); - - if (that._listView._isSelected(itemIndex)) { - WinJS.UI._ItemEventsHandler.renderSelection(itemBox, element, true, true); - } - - that._listView._currentMode().renderDragSourceOnRealizedItem(itemIndex, itemBox); - } - - updateSwipeable(itemData, element, itemBox); - - var container = that.getContainer(itemIndex); - if (itemBox.parentNode !== container) { - that._appendAndRestoreFocus(container, itemBox); - - appendItemsCount++; - if (firstIndex < 0) { - firstIndex = itemIndex; - } - lastIndex = itemIndex; - - itemData.container = container; - if (that._listView._isSelected(itemIndex)) { - utilities.addClass(container, WinJS.UI._selectedClass); - } - - utilities.removeClass(container, WinJS.UI._backdropClass); - - // elementAvailable needs to be called after fragment.appendChild. elementAvailable fulfills a promise for items requested - // by the keyboard focus handler. That handler will explicitly call .focus() on the element, so in order for - // the focus handler to work, the element needs to be in a tree prior to focusing. - - that.items.elementAvailable(itemIndex); - } - } - } - - that._listView._writeProfilerMark("_realizeItems_appendedItemsToDom,StopTM"); - if (appendItemsCount > 0) { - that._listView._writeProfilerMark("_realizeItems_appendedItemsToDom:" + appendItemsCount + " (" + firstIndex + "-" + lastIndex + "),info"); - that._reportElementsLevel(direction); - } - } - - function removeGaps(first, last, begin, end) { - if (ignoreGaps) { - return; - } - // If we realized items 0 through 20 and then scrolled so that items 25 - 30 are on screen when we - // append them to the dom we should remove items 0 - 20 from the dom so there are no gaps between the - // two realized spots. - - // Walk backwards from the beginning and if we find an item which is missing remove the rest - var foundMissing = false; - while (first >= begin) { - foundMissing = testGap(first, foundMissing); - first--; - } - - // Walk forwards from the end and if we find an item which is missing remove the rest - foundMissing = false; - while (last <= end) { - foundMissing = testGap(last, foundMissing); - last++; - } - - function testGap(itemIndex, foundMissing) { - // This helper method is called for each index and once an item is missing from the dom - // it removes any future one it encounters. - var itemData = that.items.itemDataAt(itemIndex); - if (itemData) { - var itemBox = itemData.itemBox; - if (!itemBox || !itemBox.parentNode) { - return true; - } else if (foundMissing) { - utilities.addClass(itemBox.parentNode, WinJS.UI._backdropClass); - itemBox.parentNode.removeChild(itemBox); - return true; - } else { - return false; - } - } else { - return true; - } - } - } - - function scheduleReadySignal(first, last, job, dir, head) { - var promises = []; - - for (var i = first; i <= last; i++) { - var itemData = that.items.itemDataAt(i); - if (itemData) { - promises.push(itemData.itemsManagerRecord.itemPromise); - } - } - - function schedule(itemIndex) { - var itemData = that.items.itemDataAt(itemIndex); - if (itemData) { - var record = itemData.itemsManagerRecord; - if (!record.readyComplete && that._realizePass === currentPass) { - job.addWork(function () { - if (that._listView._isZombie()) { - return; - } - if (record.pendingReady && that._realizePass === currentPass) { - that._listView._writeProfilerMark("pendingReady(" + itemIndex + "),info"); - record.pendingReady(); - } - }, head); - } - } - } - - Promise.join(promises).then(function () { - if (dir === "right") { - for (var i = first; i <= last; i++) { - schedule(i); - } - } else { - for (var i = last; i >= first; i--) { - schedule(i); - } - } - }); - } - - function delivered(index) { - if (that._realizePass !== currentPass) { - return; - } - - if (index >= firstInView && index <= lastInView) { - if (--inViewCounter === 0) { - appendItemsToDom(firstInView, lastInView); - removeGaps(firstInView, lastInView, begin, end); - - if (that._firstLayoutPass) { - scheduleReadySignal(firstInView, lastInView, that._frontOffscreenJob, direction === "right" ? "left" : "right", true); - - var entranceAnimation = Scheduler.schedulePromiseHigh(null, "WinJS.UI.ListView.entranceAnimation").then(function () { - if (that._listView._isZombie()) { return; } - that._listView._writeProfilerMark("entranceAnimation,StartTM"); - var promise = that._listView._animateListEntrance(!that._firstEntranceAnimated); - that._firstEntranceAnimated = true; - return promise; - }); - - that._runningAnimations = Promise.join([that._runningAnimations, entranceAnimation]); - that._runningAnimations.done(function () { - that._listView._writeProfilerMark("entranceAnimation,StopTM"); - if (that._realizePass === currentPass) { - that._runningAnimations = null; - entranceAnimationSignal.complete(); - } - }); - that._firstLayoutPass = false; - - if (that._listView._isCurrentZoomView) { - Scheduler.requestDrain(that._onscreenJob.priority); - } - } else { - // during scrolling ready for onscreen items after front off screen items - scheduleReadySignal(firstInView, lastInView, that._frontOffscreenJob, direction); - entranceAnimationSignal.complete(); - } - - that._updateHeaders(that._listView._canvas, firstInView, lastInView + 1).done(function () { - viewportItemsRealized.complete(); - }); - } - } else if (index < firstInView) { - --leftOffscreenCount; - if (leftOffscreenCount % inView === 0) { - appendItemsToDom(begin, firstInView - 1); - } - if (!leftOffscreenCount) { - that._updateHeaders(that._listView._canvas, begin, firstInView).done(function () { - if (direction !== "right") { - frontItemsRealized.complete(); - } - }); - scheduleReadySignal(begin, firstInView - 1, direction !== "right" ? that._frontOffscreenJob : that._backOffscreenJob, "left"); - } - } else if (index > lastInView) { - --rightOffscreenCount; - if (rightOffscreenCount % inView === 0) { - appendItemsToDom(lastInView + 1, end - 1); - } - if (!rightOffscreenCount) { - that._updateHeaders(that._listView._canvas, lastInView + 1, end).then(function () { - if (direction === "right") { - frontItemsRealized.complete(); - } - }); - scheduleReadySignal(lastInView + 1, end - 1, direction === "right" ? that._frontOffscreenJob : that._backOffscreenJob, "right"); - } - } - counter--; - - if (counter === 0) { - that._renderCompletePromise = Promise.join(renderCompletePromises).then(null, function (e) { - var error = Array.isArray(e) && e.some(function (item) { return item && !(item instanceof Error && item.name === "Canceled"); }); - if (error) { - // rethrow - return Promise.wrapError(e); - } - }); - - (that._headerRenderPromises || Promise.wrap()).done(function () { - Scheduler.schedule(function () { - if (that._listView._isZombie()) { - workCompleteSignal.cancel(); - } else { - workCompleteSignal.complete(); - } - }, Math.min(that._onscreenJob.priority, that._backOffscreenJob.priority), null, "WinJS.UI.ListView._allItemsRealized"); - }); - } - } - - function newItemIsReady(itemIndex, element, itemsManagerRecord) { - if (that._realizePass === currentPass) { - //#DBG _ASSERT(!itemsManagerRecord.released); - var element = itemsManagerRecord.element; - that._addItem(fragment, itemIndex, element, currentPass); - itemIsReady(itemIndex, itemsManagerRecord); - } - } - - if (counter > 0) { - var createCount = 0; - var updateCount = 0; - var cleanCount = 0; - //#DBG _ASSERT(lastInView < end); - that.firstIndexDisplayed = firstInView; - that.lastIndexDisplayed = lastInView; - - var isCurrentZoomView = that._listView._isCurrentZoomView; - if (that._highPriorityRealize && (that._firstLayoutPass || that._hasAnimationInViewportPending)) { - // startup or edits that will animate items in the viewport - that._highPriorityRealize = false; - that._onscreenJob.priority = Scheduler.Priority.high; - that._frontOffscreenJob.priority = Scheduler.Priority.normal; - that._backOffscreenJob.priority = Scheduler.Priority.belowNormal; - } else if (that._highPriorityRealize) { - // edits that won't animate items in the viewport - that._highPriorityRealize = false; - that._onscreenJob.priority = Scheduler.Priority.high; - that._frontOffscreenJob.priority = Scheduler.Priority.high - 1; - that._backOffscreenJob.priority = Scheduler.Priority.high - 1; - } else if (isCurrentZoomView) { - // scrolling - that._onscreenJob.priority = Scheduler.Priority.aboveNormal; - that._frontOffscreenJob.priority = Scheduler.Priority.normal; - that._backOffscreenJob.priority = Scheduler.Priority.belowNormal; - } else { - // hidden ListView in SeZo - that._onscreenJob.priority = Scheduler.Priority.belowNormal; - that._frontOffscreenJob.priority = Scheduler.Priority.idle; - that._backOffscreenJob.priority = Scheduler.Priority.idle; - } - - // Create a promise to wrap the work in the queue. When the queue gets to the last item we can mark - // the work promise complete and if the work promise is canceled we cancel the queue. - // - var workCompleteSignal = new WinJS._Signal(); - - // If the version manager recieves a notification we clear the work in the work queues - // - var cancelToken = that._listView._versionManager.cancelOnNotification(workCompleteSignal.promise); - - var queueStage1AfterStage0 = function (job, record) { - if (record.startStage1) { - record.stage0.then(function () { - if (that._realizePass === currentPass && record.startStage1) { - job.addWork(record.startStage1); - } - }); - } - }; - - var queueWork = function (job, itemIndex) { - var itemData = that.items.itemDataAt(itemIndex); - if (!itemData) { - var itemPromise = that._listView._itemsManager._itemPromiseAtIndex(itemIndex); - - // Remember this pending item promise and avoid canceling it from the previous realization pass. - that._pendingItemPromises[itemPromise.handle] = itemPromise; - delete that._previousRealizationPendingItemPromises[itemPromise.handle]; - - job.addWork(function VirtualizeContentsView_realizeItemsWork() { - if (that._listView._isZombie()) { - return; - } - - createCount++; - that._createItem(itemIndex, itemPromise, newItemIsReady, delivered); - - // _createItem runs user code - if (that._listView._isZombie() || that._realizePass !== currentPass) { - return; - } - - if (itemPromise.handle) { - var record = that._listView._itemsManager._recordFromHandle(itemPromise.handle); - queueStage1AfterStage0(job, record); - } - }); - } - - }; - - var queueRight = function (job, first, last) { - for (var itemIndex = first; itemIndex <= last; itemIndex++) { - queueWork(job, itemIndex); - } - }; - - var queueLeft = function (job, first, last) { - // Always build the left side in the direction away from the center. - for (var itemIndex = last; itemIndex >= first; itemIndex--) { - queueWork(job, itemIndex); - } - }; - - var handleExistingRange = function (job, first, last) { - for (var itemIndex = first; itemIndex <= last; itemIndex++) { - var itemData = that.items.itemDataAt(itemIndex); - if (itemData) { - var record = itemData.itemsManagerRecord; - itemIsReady(itemIndex, record); - updateCount++; - queueStage1AfterStage0(job, record); - } - } - }; - - // PendingItemPromises are the item promises which we have requested from the ItemsManager - // which have not returned an element (placeholder or real). Since we only clean up items - // which have an element in _unrealizeItems we need to remember these item promises. We cancel - // the item promises from the previous realization iteration if those item promises are not - // used for the current realization. - this._previousRealizationPendingItemPromises = this._pendingItemPromises || {}; - this._pendingItemPromises = {}; - - var emptyFront; - if (direction === "left") { - queueLeft(that._onscreenJob, firstInView, lastInView); - queueLeft(that._frontOffscreenJob, begin, firstInView - 1); - emptyFront = begin > (firstInView - 1); - } else { - queueRight(that._onscreenJob, firstInView, lastInView); - queueRight(that._frontOffscreenJob, lastInView + 1, end - 1); - emptyFront = lastInView + 1 > (end - 1); - } - - // Anything left in _previousRealizationPendingItemPromises can be canceled here. - // Note: we are doing this synchronously. If we didn't do it synchronously we would have had to merge - // _previousRealizationPendingItemPromises and _pendingItemPromises together. This also has the great - // benefit to cancel item promises in the backOffScreenArea which are much less important. - for (var i = 0, handles = Object.keys(this._previousRealizationPendingItemPromises), len = handles.length; i < len; i++) { - var handle = handles[i]; - that._listView._itemsManager.releaseItemPromise(this._previousRealizationPendingItemPromises[handle]); - } - this._previousRealizationPendingItemPromises = {}; - - - // Handle existing items in the second pass to make sure that raising ready signal is added to the queues after creating items - handleExistingRange(that._onscreenJob, firstInView, lastInView); - if (direction === "left") { - handleExistingRange(that._frontOffscreenJob, begin, firstInView - 1); - } else { - handleExistingRange(that._frontOffscreenJob, lastInView + 1, end - 1); - } - - var showProgress = (inViewCounter === lastInView - firstInView + 1); - - if (that._firstLayoutPass) { - that._listView._canvas.style.opacity = 0; - } else { - if (showProgress) { - that._listView._showProgressBar(that._listView._element, "50%", "50%"); - } else { - that._listView._hideProgressBar(); - } - } - - that._frontOffscreenJob.pause(); - that._backOffscreenJob.pause(); - - viewportItemsRealized.promise.done( - function () { - that._frontOffscreenJob.resume(); - - if (emptyFront) { - frontItemsRealized.complete(); - } - }, - function () { - workCompleteSignal.cancel(); - } - ); - - frontItemsRealized.promise.done(function () { - that._listView._writeProfilerMark("frontItemsRealized,info"); - - if (direction === "left") { - queueRight(that._backOffscreenJob, lastInView + 1, end - 1); - handleExistingRange(that._backOffscreenJob, lastInView + 1, end - 1); - } else { - queueLeft(that._backOffscreenJob, begin, firstInView - 1); - handleExistingRange(that._backOffscreenJob, begin, firstInView - 1); - } - - that._backOffscreenJob.resume(); - }); - - workCompleteSignal.promise.done( - function () { - that._listView._versionManager.clearCancelOnNotification(cancelToken); - - that._listView._writeProfilerMark(perfId + " complete(created:" + createCount + " updated:" + updateCount + "),info"); - }, - function (err) { - that._listView._versionManager.clearCancelOnNotification(cancelToken); - that._onscreenJob.clearWork(); - that._frontOffscreenJob.clearWork(); - that._backOffscreenJob.clearWork(); - - entranceAnimationSignal.cancel(); - viewportItemsRealized.cancel(); - - that._listView._writeProfilerMark(perfId + " canceled(created:" + createCount + " updated:" + updateCount + " clean:" + cleanCount + "),info"); - return WinJS.Promise.wrapError(err); - } - ); - - that._listView._writeProfilerMark(perfId + ",StopTM"); - return { - viewportItemsRealized: viewportItemsRealized.promise, - allItemsRealized: workCompleteSignal.promise, - loadingCompleted: Promise.join([workCompleteSignal.promise, entranceAnimationSignal.promise]).then(function () { - var promises = []; - - for (var i = begin; i < end; i++) { - var itemData = that.items.itemDataAt(i); - if (itemData) { - promises.push(itemData.itemsManagerRecord.itemReadyPromise); - } - } - return WinJS.Promise._cancelBlocker(Promise.join(promises)); - }) - }; - } - else { - that._listView._writeProfilerMark(perfId + ",StopTM"); - return { - viewportItemsRealized: Promise.wrap(), - allItemsRealized: Promise.wrap(), - loadingCompleted: Promise.wrap() - }; - } - }, - - _setAnimationInViewportState: function VirtualizeContentsView_setAnimationInViewportState(modifiedElements) { - this._hasAnimationInViewportPending = false; - if (modifiedElements && modifiedElements.length > 0) { - var viewportLength = this._listView._getViewportLength(), - range = this._listView._layout.itemsFromRange(this._scrollbarPos, this._scrollbarPos + viewportLength - 1); - for (var i = 0, len = modifiedElements.length; i < len; i++) { - var modifiedElement = modifiedElements[i]; - if (modifiedElement.newIndex >= range.firstIndex && modifiedElement.newIndex <= range.lastIndex && modifiedElement.newIndex !== modifiedElement.oldIndex) { - this._hasAnimationInViewportPending = true; - break; - } - } - } - }, - - _addHeader: function VirtualizeContentsView_addHeader(fragment, groupIndex) { - var that = this; - return this._listView._groups.renderGroup(groupIndex).then(function (header) { - if (header) { - var placeholder = that._getHeaderContainer(groupIndex); - if (header.element.parentNode !== placeholder) { - placeholder.appendChild(header.element); - utilities.addClass(header.element, WinJS.UI._headerClass); - } - - that._listView._groups.setDomElement(groupIndex, header.element); - } - }); - }, - - _updateHeaders: function VirtualizeContentsView_updateHeaders(fragment, begin, end) { - var that = this; - - function updateGroup(index) { - var group = that._listView._groups.group(index); - if (group && !group.header) { - var headerPromise = group.headerPromise; - if (!headerPromise) { - headerPromise = group.headerPromise = that._addHeader(fragment, index); - headerPromise.done(function () { - group.headerPromise = null; - }, function () { - group.headerPromise = null; - }); - } - return headerPromise; - } - return Promise.wrap(); - } - - this._listView._groups.removeElements(); - - var groupStart = this._listView._groups.groupFromItem(begin), - groupIndex = groupStart, - groupEnd = this._listView._groups.groupFromItem(end - 1), - realizationPromises = []; - - if (groupIndex !== null) { - //#DBG _ASSERT(groupEnd !== null); - for (; groupIndex <= groupEnd; groupIndex++) { - realizationPromises.push(updateGroup(groupIndex)); - } - } - - function done() { - that._headerRenderPromises = null; - } - this._headerRenderPromises = Promise.join(realizationPromises, this._headerRenderPromises).then(done, done); - return this._headerRenderPromises || Promise.wrap(); - }, - - _unrealizeItem: function VirtualizeContentsView_unrealizeItem(itemIndex) { - var listView = this._listView, - focusedItemPurged; - - this._listView._writeProfilerMark("_unrealizeItem(" + itemIndex + "),info"); - - var focused = listView._selection._getFocused(); - if (focused.type !== WinJS.UI.ObjectType.groupHeader && focused.index === itemIndex) { - listView._unsetFocusOnItem(); - focusedItemPurged = true; - } - var itemData = this.items.itemDataAt(itemIndex), - item = itemData.element, - itemBox = itemData.itemBox; - - if (itemBox && itemBox.parentNode) { - utilities.removeClass(itemBox.parentNode, WinJS.UI._selectedClass); - utilities.removeClass(itemBox.parentNode, WinJS.UI._footprintClass); - utilities.addClass(itemBox.parentNode, WinJS.UI._backdropClass); - itemBox.parentNode.removeChild(itemBox); - } - itemData.container = null; - - if (listView._currentMode().itemUnrealized) { - listView._currentMode().itemUnrealized(itemIndex, itemBox); - } - - this.items.removeItem(itemIndex); - - // If this wasn't released by the itemsManager already, then - // we remove it. This handles the special case of delete - // occuring on an item that is outside of the current view, but - // has not been cleaned up yet. - // - if (!itemData.removed) { - listView._itemsManager.releaseItem(item); - } - - - WinJS.Utilities._disposeElement(item); - - if (focusedItemPurged) { - // If the focused item was purged, we'll still want to focus on it if it comes into view sometime in the future. - // calling _setFocusOnItem once the item is removed from this.items will set up a promise that will be fulfilled - // if the item ever gets reloaded - listView._setFocusOnItem(listView._selection._getFocused()); - } - }, - - _unrealizeGroup: function VirtualizeContentsView_unrealizeGroup(group) { - var headerElement = group.header, - focusedItemPurged; - - var focused = this._listView._selection._getFocused(); - if (focused.type === WinJS.UI.ObjectType.groupHeader && this._listView._groups.group(focused.index) === group) { - this._listView._unsetFocusOnItem(); - focusedItemPurged = true; - } - - if (headerElement.parentNode) { - headerElement.parentNode.removeChild(headerElement); - } - - WinJS.Utilities._disposeElement(headerElement); - - group.header = null; - group.left = -1; - group.top = -1; - - if (focusedItemPurged) { - this._listView._setFocusOnItem(this._listView._selection._getFocused()); - } - }, - - _unrealizeItems: function VirtualizeContentsView_unrealizeItems(remove) { - var that = this, - removedCount = 0; - - this.items.eachIndex(function (index) { - if (index < that.begin || index >= that.end) { - that._unrealizeItem(index); - return remove && ++removedCount >= remove; - } - }); - - var groups = this._listView._groups, - beginGroup = groups.groupFromItem(this.begin); - - if (beginGroup !== null) { - var endGroup = groups.groupFromItem(this.end - 1); - for (var i = 0, len = groups.length() ; i < len; i++) { - var group = groups.group(i); - if ((i < beginGroup || i > endGroup) && group.header) { - this._unrealizeGroup(group); - } - } - } - }, - - _unrealizeExcessiveItems: function VirtualizeContentsView_unrealizeExcessiveItems() { - var realized = this.items.count(), - needed = this.end - this.begin, - approved = needed + this._listView._maxDeferredItemCleanup; - - this._listView._writeProfilerMark("_unrealizeExcessiveItems realized(" + realized + ") approved(" + approved + "),info"); - if (realized > approved) { - this._unrealizeItems(realized - approved); - } - }, - - _lazilyUnrealizeItems: function VirtualizeContentsView_lazilyUnrealizeItems() { - this._listView._writeProfilerMark("_lazilyUnrealizeItems,StartTM"); - var that = this; - return waitForSeZo(this._listView).then(function () { - - function done() { - that._listView._writeProfilerMark("_lazilyUnrealizeItems,StopTM"); - } - - if (that._listView._isZombie()) { - done(); - return; - } - - var itemsToUnrealize = []; - that.items.eachIndex(function (index) { - if (index < that.begin || index >= that.end) { - itemsToUnrealize.push(index); - } - }); - - that._listView._writeProfilerMark("_lazilyUnrealizeItems itemsToUnrealize(" + itemsToUnrealize.length + "),info"); - - var groupsToUnrealize = [], - groups = that._listView._groups, - beginGroup = groups.groupFromItem(that.begin); - - if (beginGroup !== null) { - var endGroup = groups.groupFromItem(that.end - 1); - for (var i = 0, len = groups.length() ; i < len; i++) { - var group = groups.group(i); - if ((i < beginGroup || i > endGroup) && group.header) { - groupsToUnrealize.push(group); - } - } - } - - if (itemsToUnrealize.length || groupsToUnrealize.length) { - var job; - - var promise = new Promise(function (complete) { - - function unrealizeWorker(info) { - if (that._listView._isZombie()) { return; } - - var firstIndex = -1, - lastIndex = -1, - removeCount = 0, - zooming = shouldWaitForSeZo(that._listView); - - while (itemsToUnrealize.length && !zooming && !info.shouldYield) { - var itemIndex = itemsToUnrealize.shift(); - that._unrealizeItem(itemIndex); - - removeCount++; - if (firstIndex < 0) { - firstIndex = itemIndex; - } - lastIndex = itemIndex; - } - that._listView._writeProfilerMark("unrealizeWorker removeItems:" + removeCount + " (" + firstIndex + "-" + lastIndex + "),info"); - - while (groupsToUnrealize.length && !zooming && !info.shouldYield) { - that._unrealizeGroup(groupsToUnrealize.shift()); - } - - if (itemsToUnrealize.length || groupsToUnrealize.length) { - if (zooming) { - info.setPromise(waitForSeZo(that._listView).then(function () { - return unrealizeWorker; - })); - } else { - info.setWork(unrealizeWorker); - } - } else { - complete(); - } - } - - job = Scheduler.schedule(unrealizeWorker, Scheduler.Priority.belowNormal, null, "WinJS.UI.ListView._lazilyUnrealizeItems"); - }); - - return promise.then(done, function (error) { - job.cancel(); - that._listView._writeProfilerMark("_lazilyUnrealizeItems canceled,info"); - that._listView._writeProfilerMark("_lazilyUnrealizeItems,StopTM"); - return Promise.wrapError(error); - }); - - } else { - done(); - return Promise.wrap(); - } - }); - }, - - _getBoundingRectString: function VirtualizeContentsView_getBoundingRectString(itemIndex) { - var result; - if (itemIndex >= 0 && itemIndex < this.containers.length) { - var itemPos = this._listView._layout._getItemPosition(itemIndex); - if (itemPos) { - result = "[" + itemPos.left + "; " + itemPos.top + "; " + itemPos.width + "; " + itemPos.height + " ]"; - } - } - return result || ""; - }, - - _clearDeferTimeout: function VirtualizeContentsView_clearDeferTimeout() { - if (this.deferTimeout) { - this.deferTimeout.cancel(); - this.deferTimeout = null; - } - if (this.deferredActionCancelToken !== -1) { - this._listView._versionManager.clearCancelOnNotification(this.deferredActionCancelToken); - this.deferredActionCancelToken = -1; - } - }, - - _setupAria: function VirtualizeContentsView_setupAria(timedOut) { - if (this._listView._isZombie()) { return; } - var that = this; - - function done() { - that._listView._writeProfilerMark("aria work,StopTM"); - } - - function calcLastRealizedIndexInGroup(groupIndex) { - var groups = that._listView._groups, - nextGroup = groups.group(groupIndex + 1); - return (nextGroup ? Math.min(nextGroup.startIndex - 1, that.end - 1) : that.end - 1); - } - - this._listView._createAriaMarkers(); - return this._listView._itemsCount().then(function (count) { - if (count > 0 && that.firstIndexDisplayed !== -1 && that.lastIndexDisplayed !== -1) { - that._listView._writeProfilerMark("aria work,StartTM"); - var startMarker = that._listView._ariaStartMarker, - endMarker = that._listView._ariaEndMarker, - index = that.begin, - item = that.items.itemAt(that.begin), - job, - // These are only used when the ListView is using groups - groups, - startGroup, - currentGroup, - group, - lastRealizedIndexInGroup; - - if (item) { - WinJS.UI._ensureId(item); - if (that._listView._groupsEnabled()) { - groups = that._listView._groups; - startGroup = currentGroup = groups.groupFromItem(that.begin); - group = groups.group(currentGroup); - lastRealizedIndexInGroup = calcLastRealizedIndexInGroup(currentGroup); - WinJS.UI._ensureId(group.header); - WinJS.UI._setAttribute(group.header, "role", that._listView._headerRole); - WinJS.UI._setAttribute(group.header, "x-ms-aria-flowfrom", startMarker.id); - WinJS.UI._setFlow(group.header, item); - WinJS.UI._setAttribute(group.header, "tabindex", that._listView._tabIndex); - } else { - WinJS.UI._setAttribute(item, "x-ms-aria-flowfrom", startMarker.id); - } - - return new Promise(function (completeJobPromise) { - var skipWait = timedOut; - job = Scheduler.schedule(function ariaWorker(jobInfo) { - if (that._listView._isZombie()) { - done(); - return; - } - - for (; index < that.end; index++) { - if (!skipWait && shouldWaitForSeZo(that._listView)) { - jobInfo.setPromise(waitForSeZo(that._listView).then(function (timedOut) { - skipWait = timedOut; - return ariaWorker; - })); - return; - } else if (jobInfo.shouldYield) { - jobInfo.setWork(ariaWorker); - return; - } - - item = that.items.itemAt(index); - var nextItem = that.items.itemAt(index + 1); - - if (nextItem) { - WinJS.UI._ensureId(nextItem); - } - - WinJS.UI._setAttribute(item, "role", that._listView._itemRole); - WinJS.UI._setAttribute(item, "aria-setsize", count); - WinJS.UI._setAttribute(item, "aria-posinset", index + 1); - WinJS.UI._setAttribute(item, "tabindex", that._listView._tabIndex); - - if (that._listView._groupsEnabled()) { - if (index === lastRealizedIndexInGroup || !nextItem) { - var nextGroup = groups.group(currentGroup + 1); - - // If group is the last realized group, then nextGroup won't exist in the DOM. - // When this is the case, nextItem shouldn't exist. - //#DBG _ASSERT(nextGroup && nextGroup.header || !nextItem); - if (nextGroup && nextGroup.header && nextItem) { - WinJS.UI._setAttribute(nextGroup.header, "tabindex", that._listView._tabIndex); - WinJS.UI._setAttribute(nextGroup.header, "role", that._listView._headerRole); - WinJS.UI._ensureId(nextGroup.header); - WinJS.UI._setFlow(item, nextGroup.header); - WinJS.UI._setFlow(nextGroup.header, nextItem); - } else { - // We're at the last group so flow to the end marker - WinJS.UI._setAttribute(item, "aria-flowto", endMarker.id); - } - - currentGroup++; - group = nextGroup; - lastRealizedIndexInGroup = calcLastRealizedIndexInGroup(currentGroup); - } else { - // This is not the last item in the group so flow to the next item - //#DBG _ASSERT(nextItem); - WinJS.UI._setFlow(item, nextItem); - } - } else if (nextItem) { - // Groups are disabled so as long as we aren't at the last item, flow to the next one - WinJS.UI._setFlow(item, nextItem); - } else { - // Groups are disabled and we're at the last item, so flow to the end marker - WinJS.UI._setAttribute(item, "aria-flowto", endMarker.id); - } - if (!nextItem) { - break; - } - } - - that._listView._fireAccessibilityAnnotationCompleteEvent(that.begin, index, startGroup, currentGroup - 1); - - done(); - completeJobPromise(); - }, Scheduler.Priority.belowNormal, null, "WinJS.UI.ListView._setupAria"); - }, function () { - // Cancellation handler for promise returned by setupAria - job.cancel(); - done(); - }); - } else { - // the first item is null - done(); - } - } else { - // The count is 0 - return Promise.wrap(); - } - }); - }, - - _setupDeferredActions: function VirtualizeContentsView_setupDeferredActions() { - this._listView._writeProfilerMark("_setupDeferredActions,StartTM"); - var that = this; - - this._clearDeferTimeout(); - - function cleanUp() { - if (that._listView._isZombie()) { return; } - that.deferTimeout = null; - that._listView._versionManager.clearCancelOnNotification(that.deferredActionCancelToken); - that.deferredActionCancelToken = -1; - } - - this.deferTimeout = this._lazilyRemoveRedundantItemsBlocks().then(function() { - return WinJS.Promise.timeout(WinJS.UI._DEFERRED_ACTION); - }). - then(function () { - return waitForSeZo(that._listView); - }). - then(function (timedOut) { - return that._setupAria(timedOut); - }). - then(cleanUp, function (error) { - cleanUp(); - return Promise.wrapError(error); - }); - - this.deferredActionCancelToken = this._listView._versionManager.cancelOnNotification(this.deferTimeout); - this._listView._writeProfilerMark("_setupDeferredActions,StopTM"); - }, - - // Sets aria-flowto on _ariaStartMarker and x-ms-aria-flowfrom on _ariaEndMarker. The former - // points to either the first visible group header or the first visible item. The latter points - // to the last visible item. - _updateAriaMarkers: function VirtualizeContentsView_updateAriaMarkers(listViewIsEmpty, firstIndexDisplayed, lastIndexDisplayed) { - var that = this; - if (this._listView._isZombie()) { - return; - } - - function getFirstVisibleItem() { - return that.items.itemAt(firstIndexDisplayed); - } - - // At a certain index, the VDS may return null for all items at that index and - // higher. When this is the case, the end marker should point to the last - // non-null item in the visible range. - function getLastVisibleItem() { - for (var i = lastIndexDisplayed; i >= firstIndexDisplayed; i--) { - if (that.items.itemAt(i)) { - return that.items.itemAt(i); - } - } - return null; - } - - this._listView._createAriaMarkers(); - var startMarker = this._listView._ariaStartMarker, - endMarker = this._listView._ariaEndMarker, - firstVisibleItem, - lastVisibleItem; - - if (firstIndexDisplayed !== -1 && lastIndexDisplayed !== -1 && firstIndexDisplayed <= lastIndexDisplayed) { - firstVisibleItem = getFirstVisibleItem(); - lastVisibleItem = getLastVisibleItem(); - } - - if (listViewIsEmpty || !firstVisibleItem || !lastVisibleItem) { - WinJS.UI._setFlow(startMarker, endMarker); - this._listView._fireAccessibilityAnnotationCompleteEvent(-1, -1); - } else { - WinJS.UI._ensureId(firstVisibleItem); - WinJS.UI._ensureId(lastVisibleItem); - - // Set startMarker's flowto - if (this._listView._groupsEnabled()) { - var groups = this._listView._groups, - firstVisibleGroup = groups.group(groups.groupFromItem(firstIndexDisplayed)); - - if (firstVisibleGroup.header) { - WinJS.UI._ensureId(firstVisibleGroup.header); - - if (firstIndexDisplayed === firstVisibleGroup.startIndex) { - WinJS.UI._setAttribute(startMarker, "aria-flowto", firstVisibleGroup.header.id); - } else { - WinJS.UI._setAttribute(startMarker, "aria-flowto", firstVisibleItem.id); - } - } - } else { - WinJS.UI._setAttribute(startMarker, "aria-flowto", firstVisibleItem.id); - } - - // Set endMarker's flowfrom - WinJS.UI._setAttribute(endMarker, "x-ms-aria-flowfrom", lastVisibleItem.id); - } - }, - - // Update the ARIA attributes on item that are needed so that Narrator can announce it. - // item must be in the items container. - updateAriaForAnnouncement: function VirtualizeContentsView_updateAriaForAnnouncement(item, count) { - var index = -1; - var type = WinJS.UI.ObjectType.item; - if (WinJS.Utilities.hasClass(item, WinJS.UI._headerClass)) { - index = this._listView._groups.index(item); - //#DBG _ASSERT(index !== WinJS.UI._INVALID_INDEX); - type = WinJS.UI.ObjectType.groupHeader; - WinJS.UI._setAttribute(item, "role", this._listView._headerRole); - } else { - index = this.items.index(item); - //#DBG _ASSERT(index !== WinJS.UI._INVALID_INDEX); - WinJS.UI._setAttribute(item, "aria-setsize", count); - WinJS.UI._setAttribute(item, "aria-posinset", index + 1); - WinJS.UI._setAttribute(item, "role", this._listView._itemRole); - } - - if (type === WinJS.UI.ObjectType.groupHeader) { - this._listView._fireAccessibilityAnnotationCompleteEvent(-1, -1, index, index); - } else { - this._listView._fireAccessibilityAnnotationCompleteEvent(index, index, -1, -1); - } - }, - - _reportElementsLevel: function VirtualizeContentsView_reportElementsLevel(direction) { - var items = this.items; - - function elementsCount(first, last) { - var count = 0; - for (var itemIndex = first; itemIndex <= last; itemIndex++) { - var itemData = items.itemDataAt(itemIndex); - if (itemData && itemData.container) { - count++; - } - } - return count; - } - - var level; - if (direction === "right") { - level = Math.floor(100 * elementsCount(this.firstIndexDisplayed, this.end - 1) / (this.end - this.firstIndexDisplayed)); - } else { - level = Math.floor(100 * elementsCount(this.begin, this.lastIndexDisplayed) / (this.lastIndexDisplayed - this.begin + 1)); - } - - this._listView._writeProfilerMark("elementsLevel level(" + level + "),info"); - }, - - _createHeaderContainer: function VirtualizeContentsView_createHeaderContainer(insertAfter) { - return this._createSurfaceChild(WinJS.UI._headerContainerClass, insertAfter); - }, - - _createItemsContainer: function VirtualizeContentsView_createItemsContainer(insertAfter) { - var itemsContainer = this._createSurfaceChild(WinJS.UI._itemsContainerClass, insertAfter); - var padder = document.createElement("div"); - padder.className = WinJS.UI._padderClass; - itemsContainer.appendChild(padder); - return itemsContainer; - }, - - _ensureContainerInDOM: function VirtualizeContentsView_ensureContainerInDOM(index) { - var container = this.containers[index]; - if (container && !this._listView._canvas.contains(container)) { - this._forceItemsBlocksInDOM(index, index + 1); - return true; - } - return false; - }, - - _ensureItemsBlocksInDOM: function VirtualizeContentsView_ensureItemsBlocksInDOM(begin, end) { - if (this._expandedRange) { - var oldBegin = this._expandedRange.first.index, - oldEnd = this._expandedRange.last.index + 1; - - if (begin <= oldBegin && end > oldBegin) { - end = Math.max(end, oldEnd); - } else if (begin < oldEnd && end >= oldEnd) { - begin = Math.min(begin, oldBegin); - } - } - this._forceItemsBlocksInDOM(begin, end); - }, - - _removeRedundantItemsBlocks: function VirtualizeContentsView_removeRedundantItemsBlocks() { - if (this.begin !== -1 && this.end !== -1) { - this._forceItemsBlocksInDOM(this.begin, this.end); - } - }, - - _lazilyRemoveRedundantItemsBlocks: function VirtualizeContentsView_lazilyRemoveRedundantItemsBlocks() { - this._listView._writeProfilerMark("_lazilyRemoveRedundantItemsBlocks,StartTM"); - var that = this; - return waitForSeZo(this._listView).then(function () { - - function done() { - that._listView._writeProfilerMark("_lazilyRemoveRedundantItemsBlocks,StopTM"); - } - - if (that._listView._isZombie()) { - done(); - return; - } - - if (that._expandedRange && that.begin !== -1 && that.end !== -1 && (that._expandedRange.first.index < that.begin || that._expandedRange.last.index + 1 > that.end)) { - var job; - - var promise = new Promise(function (complete) { - - function blocksCleanupWorker(info) { - if (that._listView._isZombie()) { return; } - - var zooming = shouldWaitForSeZo(that._listView); - - while (that._expandedRange.first.index < that.begin && !zooming && !info.shouldYield) { - var begin = Math.min(that.begin, that._expandedRange.first.index + that._blockSize * WinJS.UI._VirtualizeContentsView._blocksToRelease); - that._forceItemsBlocksInDOM(begin, that.end); - } - - while (that._expandedRange.last.index + 1 > that.end && !zooming && !info.shouldYield) { - var end = Math.max(that.end, that._expandedRange.last.index - that._blockSize * WinJS.UI._VirtualizeContentsView._blocksToRelease); - that._forceItemsBlocksInDOM(that.begin, end); - } - - if (that._expandedRange.first.index < that.begin || that._expandedRange.last.index + 1 > that.end) { - if (zooming) { - info.setPromise(waitForSeZo(that._listView).then(function () { - return blocksCleanupWorker; - })); - } else { - info.setWork(blocksCleanupWorker); - } - } else { - complete(); - } - } - - job = Scheduler.schedule(blocksCleanupWorker, Scheduler.Priority.belowNormal, null, "WinJS.UI.ListView._lazilyRemoveRedundantItemsBlocks"); - }); - - return promise.then(done, function (error) { - job.cancel(); - that._listView._writeProfilerMark("_lazilyRemoveRedundantItemsBlocks canceled,info"); - that._listView._writeProfilerMark("_lazilyRemoveRedundantItemsBlocks,StopTM"); - return Promise.wrapError(error); - }); - - } else { - done(); - return Promise.wrap(); - } - }); - }, - - _forceItemsBlocksInDOM: function VirtualizeContentsView_forceItemsBlocksInDOM(begin, end) { - if (!this._blockSize) { - return; - } - var perfId = "_forceItemsBlocksInDOM begin(" + begin + ") end(" + end + "),"; - this._listView._writeProfilerMark(perfId + "StartTM"); - - var that = this, - added = 0, - removed = 0, - paddingProperty = "padding" + (this._listView._horizontal() ? "Left" : "Top"); - - function setPadder(itemsContainer, padding) { - var padder = itemsContainer.element.firstElementChild; - padder.style[paddingProperty] = padding; - } - - function forEachBlock(callback) { - for (var g = 0; g < that.tree.length; g++) { - var itemsContainer = that.tree[g].itemsContainer; - for (var b = 0, len = itemsContainer.itemsBlocks.length; b < len; b++) { - if (callback(itemsContainer, itemsContainer.itemsBlocks[b])) { - return; - } - } - } - } - - function measureItemsBlock(itemsBlock) { - that._listView._writeProfilerMark("_itemsBlockExtent,StartTM"); - that._listView._itemsBlockExtent = utilities[that._listView._horizontal() ? "getTotalWidth" : "getTotalHeight"](itemsBlock.element); - that._listView._writeProfilerMark("_itemsBlockExtent(" + that._listView._itemsBlockExtent + "),info"); - that._listView._writeProfilerMark("_itemsBlockExtent,StopTM"); - } - - function getItemsBlockExtent() { - if (that._listView._itemsBlockExtent === -1) { - // first try blocks already added to the DOM - forEachBlock(function (itemsContainer, itemsBlock) { - if (itemsBlock.items.length === that._blockSize && itemsBlock.element.parentNode === itemsContainer.element) { - measureItemsBlock(itemsBlock); - return true; - } - return false; - }); - } - - if (that._listView._itemsBlockExtent === -1) { - forEachBlock(function (itemsContainer, itemsBlock) { - if (itemsBlock.items.length === that._blockSize) { - itemsContainer.element.appendChild(itemsBlock.element); - measureItemsBlock(itemsBlock); - itemsContainer.element.removeChild(itemsBlock.element); - return true; - } - return false; - }); - } - return that._listView._itemsBlockExtent; - } - - function removeBlocks(itemsContainer, begin, end) { - - function remove(blockIndex) { - var block = itemsContainer.itemsBlocks[blockIndex]; - if (block && block.element.parentNode === itemsContainer.element) { - itemsContainer.element.removeChild(block.element); - removed++; - } - } - - if (Array.isArray(begin)) { - begin.forEach(remove); - } else { - for (var i = begin; i < end; i++) { - remove(i); - } - } - } - - function addBlocks(itemsContainer, begin, end) { - var padder = itemsContainer.element.firstElementChild, - previous = padder; - - for (var i = begin; i < end; i++) { - var block = itemsContainer.itemsBlocks[i]; - if (block) { - if (block.element.parentNode !== itemsContainer.element) { - itemsContainer.element.insertBefore(block.element, previous.nextElementSibling); - added++; - } - previous = block.element; - } - } - } - - function collapseGroup(groupIndex) { - if (groupIndex < that.tree.length) { - that._listView._writeProfilerMark("collapseGroup(" + groupIndex + "),info"); - var itemsContainer = that.tree[groupIndex].itemsContainer; - removeBlocks(itemsContainer, 0, itemsContainer.itemsBlocks.length); - setPadder(itemsContainer, ""); - } - } - - function expandGroup(groupIndex) { - if (groupIndex < that.tree.length) { - that._listView._writeProfilerMark("expandGroup(" + groupIndex + "),info"); - var itemsContainer = that.tree[groupIndex].itemsContainer; - addBlocks(itemsContainer, 0, itemsContainer.itemsBlocks.length); - setPadder(itemsContainer, ""); - } - } - - function removedFromRange(oldRange, newRange) { - function expand(first, last) { - var array = []; - for (var i = first; i <= last; i++) { - array.push(i); - } - return array; - } - - var newL = newRange[0]; - var newR = newRange[1]; - var oldL = oldRange[0]; - var oldR = oldRange[1]; - - if (newR < oldL || newL > oldR) { - return expand(oldL, oldR); - } else if (newL > oldL && newR < oldR) { - return expand(oldL, newL - 1).concat(expand(newR + 1, oldR)); - } else if (oldL < newL) { - return expand(oldL, newL - 1); - } else if (oldR > newR) { - return expand(newR + 1, oldR); - } else { - return null; - } - } - - var firstGroupIndex = this._listView._groups.groupFromItem(begin), - lastGroupIndex = this._listView._groups.groupFromItem(end - 1); - - var firstGroup = this._listView._groups.group(firstGroupIndex), - firstItemsContainer = that.tree[firstGroupIndex].itemsContainer; - - var firstBlock = Math.floor((begin - firstGroup.startIndex) / this._blockSize); - - var lastGroup = this._listView._groups.group(lastGroupIndex), - lastItemsContainer = that.tree[lastGroupIndex].itemsContainer; - - var lastBlock = Math.floor((end - 1 - lastGroup.startIndex) / this._blockSize); - - // if size of structure block is needed try to obtain it before modifying the tree to avoid a layout pass - if (firstBlock && that._listView._itemsBlockExtent === -1) { - forEachBlock(function (itemsContainer, itemsBlock) { - if (itemsBlock.items.length === that._blockSize && itemsBlock.element.parentNode === itemsContainer.element) { - measureItemsBlock(itemsBlock); - return true; - } - return false; - }); - } - - var groupsToCollapse = this._expandedRange ? removedFromRange([this._expandedRange.first.groupIndex, this._expandedRange.last.groupIndex], [firstGroupIndex, lastGroupIndex]) : null; - if (groupsToCollapse) { - groupsToCollapse.forEach(collapseGroup); - } - - if (this._expandedRange && this._expandedRange.first.groupKey === firstGroup.key) { - var blocksToRemove = removedFromRange([this._expandedRange.first.block, Number.MAX_VALUE], [firstBlock, Number.MAX_VALUE]); - if (blocksToRemove) { - removeBlocks(firstItemsContainer, blocksToRemove); - } - } else if (this._expandedRange && firstGroupIndex >= this._expandedRange.first.groupIndex && firstGroupIndex <= this._expandedRange.last.groupIndex) { - removeBlocks(firstItemsContainer, 0, firstBlock); - } - - if (firstGroupIndex !== lastGroupIndex) { - addBlocks(firstItemsContainer, firstBlock, firstItemsContainer.itemsBlocks.length); - addBlocks(lastItemsContainer, 0, lastBlock + 1); - } else { - addBlocks(firstItemsContainer, firstBlock, lastBlock + 1); - } - - if (this._expandedRange && this._expandedRange.last.groupKey === lastGroup.key) { - var blocksToRemove = removedFromRange([0, this._expandedRange.last.block], [0, lastBlock]); - if (blocksToRemove) { - removeBlocks(lastItemsContainer, blocksToRemove); - } - } else if (this._expandedRange && lastGroupIndex >= this._expandedRange.first.groupIndex && lastGroupIndex <= this._expandedRange.last.groupIndex) { - removeBlocks(lastItemsContainer, lastBlock + 1, lastItemsContainer.itemsBlocks.length); - } - - setPadder(firstItemsContainer, firstBlock ? firstBlock * getItemsBlockExtent() + "px" : ""); - - if (firstGroupIndex !== lastGroupIndex) { - setPadder(lastItemsContainer, ""); - } - - // groups between first and last - for (var i = firstGroupIndex + 1; i < lastGroupIndex; i++) { - expandGroup(i); - } - - this._expandedRange = { - first: { - index: begin, - groupIndex: firstGroupIndex, - groupKey: firstGroup.key, - block: firstBlock - }, - last: { - index: end - 1, - groupIndex: lastGroupIndex, - groupKey: lastGroup.key, - block: lastBlock - }, - }; - this._listView._writeProfilerMark("_forceItemsBlocksInDOM groups(" + firstGroupIndex + "-" + lastGroupIndex + ") blocks(" + firstBlock + "-" + lastBlock + ") added(" + added + ") removed(" + removed + "),info"); - this._listView._writeProfilerMark(perfId + "StopTM"); - }, - - _realizePageImpl: function VirtualizeContentsView_realizePageImpl() { - var that = this; - - var perfId = "realizePage(scrollPosition:" + this._scrollbarPos + " forceLayout:" + this._forceRelayout + ")"; - this._listView._writeProfilerMark(perfId + ",StartTM"); - - // It's safe to skip realizePage, so we just queue up the last request to run when the version manager - // get unlocked. - // - if (this._listView._versionManager.locked) { - this._listView._versionManager.unlocked.done(function () { - if (!that._listView._isZombie()) { - that._listView._batchViewUpdates(WinJS.UI._ViewChange.realize, WinJS.UI._ScrollToPriority.low, that._listView.scrollPosition); - } - }); - this._listView._writeProfilerMark(perfId + ",StopTM"); - return Promise.cancel; - } - - return new Promise(function (c) { - var renderingCompleteSignal = new WinJS._Signal(); - - function complete() { - c(); - renderingCompleteSignal.complete(); - } - - function viewPortPageRealized() { - that._listView._hideProgressBar(); - that._state.setLoadingState(that._listView._LoadingState.viewPortLoaded); - if (that._executeAnimations) { - that._setState(RealizingAnimatingState, renderingCompleteSignal.promise); - } - } - - function pageRealized(count) { - that._updateAriaMarkers(count === 0, that.firstIndexDisplayed, that.lastIndexDisplayed); - that._state.setLoadingState && that._state.setLoadingState(that._listView._LoadingState.itemsLoaded); - } - - function finish(count) { - that._listView._clearInsertedItems(); - that._listView._groups.removeElements(); - viewPortPageRealized(); - pageRealized(count); - complete(); - } - - that._state.setLoadingState(that._listView._LoadingState.itemsLoading); - if (that._firstLayoutPass) { - that._listView._showProgressBar(that._listView._element, "50%", "50%"); - } - - var count = that.containers.length; - - if (count) { - // While the zoom animation is played we want to minimize the # of pages - // being fetched to improve TtFF for SeZo scenarios - var pagesToPrefetch = WinJS.UI._VirtualizeContentsView._pagesToPrefetch; - if (that._listView._zooming) { - pagesToPrefetch = 0; - } - - var viewportLength = that._listView._getViewportLength(), - beginningOffset = Math.max(0, that._scrollbarPos - pagesToPrefetch * viewportLength), - endingOffset = that._scrollbarPos + (1 + pagesToPrefetch) * viewportLength; - - var range = that._listView._layout.itemsFromRange(beginningOffset, endingOffset - 1); - if ((range.firstIndex < 0 || range.firstIndex >= count) && (range.lastIndex < 0 || range.lastIndex >= count)) { - that.begin = -1; - that.end = -1; - that.firstIndexDisplayed = -1; - that.lastIndexDisplayed = -1; - finish(count); - } else { - var begin = utilities._clamp(range.firstIndex, 0, count - 1), - end = utilities._clamp(range.lastIndex + 1, 0, count); - - var inView = that._listView._layout.itemsFromRange(that._scrollbarPos, that._scrollbarPos + viewportLength - 1), - firstInView = utilities._clamp(inView.firstIndex, 0, count - 1), - lastInView = utilities._clamp(inView.lastIndex, 0, count - 1); - - if (that._realizationLevel === WinJS.UI._VirtualizeContentsView._realizationLevel.skip && !that.lastRealizePass && firstInView === that.firstIndexDisplayed && lastInView === that.lastIndexDisplayed) { - that.begin = begin; - that.end = begin + Object.keys(that.items._itemData).length; - that._updateHeaders(that._listView._canvas, that.begin, that.end).done(function () { - that.lastRealizePass = null; - finish(count); - }); - } else if ((that._forceRelayout || begin !== that.begin || end !== that.end || firstInView !== that.firstIndexDisplayed || lastInView !== that.lastIndexDisplayed) && (begin < end) && (beginningOffset < endingOffset)) { - that._listView._writeProfilerMark("realizePage currentInView(" + firstInView + "-" + lastInView + ") previousInView(" + that.firstIndexDisplayed + "-" + that.lastIndexDisplayed + ") change(" + (firstInView - that.firstIndexDisplayed) + "),info"); - that._cancelRealize(); - // cancelRealize changes the realizePass and resets begin/end - var currentPass = that._realizePass; - that.begin = begin; - that.end = end; - that.firstIndexDisplayed = firstInView; - that.lastIndexDisplayed = lastInView; - that.deletesWithoutRealize = 0; - - that._ensureItemsBlocksInDOM(that.begin, that.end); - - var realizeWork = that._realizeItems( - that._listView._itemCanvas, - that.begin, - that.end, - count, - currentPass, - that._scrollbarPos, - that._direction, - firstInView, - lastInView, - that._forceRelayout); - - that._forceRelayout = false; - - var realizePassWork = realizeWork.viewportItemsRealized.then(function () { - viewPortPageRealized(); - return realizeWork.allItemsRealized; - }).then(function () { - if (that._realizePass === currentPass) { - return that._updateHeaders(that._listView._canvas, that.begin, that.end).then(function () { - pageRealized(count); - }); - } - }).then(function () { - return realizeWork.loadingCompleted; - }).then( - function () { - that._unrealizeExcessiveItems(); - that.lastRealizePass = null; - complete(); - }, - function (e) { - if (that._realizePass === currentPass) { - that.lastRealizePass = null; - that.begin = -1; - that.end = -1; - } - return WinJS.Promise.wrapError(e); - } - ); - - that.lastRealizePass = Promise.join([realizeWork.viewportItemsRealized, realizeWork.allItemsRealized, realizeWork.loadingCompleted, realizePassWork]); - - that._unrealizeExcessiveItems(); - - } else if (!that.lastRealizePass) { - // We are currently in the "itemsLoading" state and need to get back to "complete". The - // previous realize pass has been completed so proceed to the other states. - finish(count); - } else { - that.lastRealizePass.then(complete); - } - } - } else { - that.begin = -1; - that.end = -1; - that.firstIndexDisplayed = -1; - that.lastIndexDisplayed = -1; - - finish(count); - } - - that._reportElementsLevel(that._direction); - - that._listView._writeProfilerMark(perfId + ",StopTM"); - }); - }, - - realizePage: function VirtualizeContentsView_realizePage(scrollToFunctor, forceRelayout, scrollEndPromise, StateType) { - this._scrollToFunctor = makeFunctor(scrollToFunctor); - this._forceRelayout = this._forceRelayout || forceRelayout; - this._scrollEndPromise = scrollEndPromise; - - this._listView._writeProfilerMark(this._state.name + "_realizePage,info"); - this._state.realizePage(StateType || RealizingState); - }, - - onScroll: function VirtualizeContentsView_onScroll(scrollToFunctor, scrollEndPromise) { - this.realizePage(scrollToFunctor, false, scrollEndPromise, ScrollingState); - }, - - reload: function VirtualizeContentsView_reload(scrollToFunctor, highPriority) { - if (this._listView._isZombie()) { return; } - - this._scrollToFunctor = makeFunctor(scrollToFunctor); - this._forceRelayout = true; - this._highPriorityRealize = !!highPriority; - - this.stopWork(true); - - this._listView._writeProfilerMark(this._state.name + "_rebuildTree,info"); - this._state.rebuildTree(); - }, - - refresh: function VirtualizeContentsView_refresh(scrollToFunctor) { - if (this._listView._isZombie()) { return; } - - this._scrollToFunctor = makeFunctor(scrollToFunctor); - this._forceRelayout = true; - this._highPriorityRealize = true; - - this.stopWork(); - - this._listView._writeProfilerMark(this._state.name + "_relayout,info"); - this._state.relayout(); - }, - - waitForValidScrollPosition: function VirtualizeContentsView_waitForValidScrollPosition(newPosition) { - var that = this; - var currentMaxScroll = this._listView._viewport[this._listView._scrollLength] - this._listView._getViewportLength(); - if (newPosition > currentMaxScroll) { - return that._listView._itemsCount().then(function (count) { - // Wait until we have laid out enough containers to be able to set the scroll position to newPosition - if (that.containers.length < count) { - return Promise._cancelBlocker(that._creatingContainersWork && that._creatingContainersWork.promise).then(function () { - return that._getLayoutCompleted(); - }).then(function () { - return newPosition; - }); - } else { - return newPosition; - } - }); - } else { - return WinJS.Promise.wrap(newPosition); - } - }, - - waitForEntityPosition: function VirtualizeContentsView_waitForEntityPosition(entity) { - var that = this; - this._listView._writeProfilerMark(this._state.name + "_waitForEntityPosition" + "(" + entity.type + ": " + entity.index + ")" + ",info"); - return Promise._cancelBlocker(this._state.waitForEntityPosition(entity).then(function () { - if ((entity.type !== WinJS.UI.ObjectType.groupHeader && entity.index >= that.containers.length) || - (entity.type === WinJS.UI.ObjectType.groupHeader && that._listView._groups.group(entity.index).startIndex >= that.containers.length)) { - return that._creatingContainersWork && that._creatingContainersWork.promise; - } - }).then(function () { - return that._getLayoutCompleted(); - })); - }, - - stopWork: function VirtualizeContentsView_stopWork(stopTreeCreation) { - this._listView._writeProfilerMark(this._state.name + "_stop,info"); - this._state.stop(stopTreeCreation); - - if (this._layoutWork) { - this._layoutWork.cancel(); - } - - if (stopTreeCreation && this._creatingContainersWork) { - this._creatingContainersWork.cancel(); - } - - if (stopTreeCreation) { - this._state = new CreatedState(this); - } - }, - - _cancelRealize: function VirtualizeContentsView_cancelRealize() { - this._listView._writeProfilerMark("_cancelRealize,StartTM"); - - if (this.lastRealizePass || this.deferTimeout) { - this._forceRelayout = true; - } - - this._clearDeferTimeout(); - this._realizePass++; - - if (this._headerRenderPromises) { - this._headerRenderPromises.cancel(); - this._headerRenderPromises = null; - } - - var last = this.lastRealizePass; - if (last) { - this.lastRealizePass = null; - this.begin = -1; - this.end = -1; - last.cancel(); - } - this._listView._writeProfilerMark("_cancelRealize,StopTM"); - }, - - resetItems: function VirtualizeContentsView_resetItems(unparent) { - if (!this._listView._isZombie()) { - this.firstIndexDisplayed = -1; - this.lastIndexDisplayed = -1; - this._runningAnimations = null; - this._executeAnimations = false; - - var listView = this._listView; - this._firstLayoutPass = true; - listView._unsetFocusOnItem(); - if (listView._currentMode().onDataChanged) { - listView._currentMode().onDataChanged(); - } - - this.items.each(function (index, item) { - if (unparent && item.parentNode && item.parentNode.parentNode) { - item.parentNode.parentNode.removeChild(item.parentNode); - } - listView._itemsManager.releaseItem(item); - WinJS.Utilities._disposeElement(item); - }); - - this.items.removeItems(); - this._deferredReparenting = []; - - if (unparent) { - listView._groups.removeElements(); - } - - listView._clearInsertedItems(); - } - }, - - reset: function VirtualizeContentsView_reset() { - this.stopWork(true); - this._state = new CreatedState(this); - - this.resetItems(); - - // when in the zombie state, we let disposal cleanup the ScrollView state - // - if (!this._listView._isZombie()) { - var listView = this._listView; - listView._groups.resetGroups(); - listView._resetCanvas(); - - this.tree = null; - this.keyToGroupIndex = null; - this.containers = null; - this._expandedRange = null; - } - }, - - cleanUp: function VirtualizeContentsView_cleanUp() { - this.stopWork(true); - - this._runningAnimations && this._runningAnimations.cancel(); - var itemsManager = this._listView._itemsManager; - this.items.each(function (index, item) { - itemsManager.releaseItem(item); - WinJS.Utilities._disposeElement(item); - }); - this._listView._unsetFocusOnItem(); - this.items.removeItems(); - this._deferredReparenting = []; - this._listView._groups.resetGroups(); - this._listView._resetCanvas(); - - this.tree = null; - this.keyToGroupIndex = null; - this.containers = null; - this._expandedRange = null; - - this.destroyed = true; - }, - - getContainer: function VirtualizeContentsView_getContainer(itemIndex) { - return this.containers[itemIndex]; - }, - - _getHeaderContainer: function VirtualizeContentsView_getHeaderContainer(groupIndex) { - return this.tree[groupIndex].header; - }, - - _getGroups: function VirtualizeContentsView_getGroups(count) { - if (this._listView._groupDataSource) { - var groupsContainer = this._listView._groups.groups, - groups = []; - if (count) { - for (var i = 0, len = groupsContainer.length; i < len; i++) { - var group = groupsContainer[i], - nextStartIndex = i + 1 < len ? groupsContainer[i + 1].startIndex : count; - groups.push({ - key: group.key, - size: nextStartIndex - group.startIndex - }); - } - } - return groups; - } else { - return [{ key: "-1", size: count }]; - } - }, - - _createChunk: function VirtualizeContentsView_createChunk(groups, count, chunkSize) { - var that = this; - - this._listView._writeProfilerMark("createChunk,StartTM"); - - function addToGroup(itemsContainer, groupSize) { - var children = itemsContainer.element.children, - oldSize = children.length, - toAdd = Math.min(groupSize - itemsContainer.items.length, chunkSize); - - utilities.insertAdjacentHTMLUnsafe(itemsContainer.element, "beforeend", WinJS.UI._repeat("
    ", toAdd)); - - for (var i = 0; i < toAdd; i++) { - var container = children[oldSize + i]; - itemsContainer.items.push(container); - that.containers.push(container); - } - } - - function newGroup(group) { - var node = { - header: that._listView._groupDataSource ? that._createHeaderContainer() : null, - itemsContainer: { - element: that._createItemsContainer(), - items: [] - } - }; - - - that.tree.push(node); - that.keyToGroupIndex[group.key] = that.tree.length - 1; - addToGroup(node.itemsContainer, group.size); - } - - if (this.tree.length && this.tree.length <= groups.length) { - var last = this.tree[this.tree.length - 1], - finalSize = groups[this.tree.length - 1].size; - - // check if the last group in the tree already has all items. If not add items to this group - if (last.itemsContainer.items.length < finalSize) { - addToGroup(last.itemsContainer, finalSize); - this._listView._writeProfilerMark("createChunk,StopTM"); - return; - } - } - - if (this.tree.length < groups.length) { - newGroup(groups[this.tree.length]); - } - - this._listView._writeProfilerMark("createChunk,StopTM"); - }, - - _createChunkWithBlocks: function VirtualizeContentsView_createChunkWithBlocks(groups, count, blockSize, chunkSize) { - var that = this; - this._listView._writeProfilerMark("createChunk,StartTM"); - - function addToGroup(itemsContainer, toAdd) { - var lastExistingBlock = itemsContainer.itemsBlocks.length ? itemsContainer.itemsBlocks[itemsContainer.itemsBlocks.length - 1] : null; - - if (lastExistingBlock && lastExistingBlock.items.length < blockSize) { - var fix = Math.min(toAdd, blockSize - lastExistingBlock.items.length); - utilities.insertAdjacentHTMLUnsafe(lastExistingBlock.element, "beforeend", WinJS.UI._repeat("
    ", fix)); - - var oldSize = lastExistingBlock.items.length; - children = lastExistingBlock.element.children; - - for (var j = 0; j < fix; j++) { - var child = children[oldSize + j]; - lastExistingBlock.items.push(child); - that.containers.push(child); - } - - toAdd -= fix; - } - - if (toAdd > chunkSize) { - toAdd = Math.min(toAdd, Math.max(1, Math.floor(chunkSize / blockSize)) * blockSize); - } - - var blocks = Math.floor(toAdd / blockSize), - lastBlockSize = toAdd % blockSize; - - var blockMarkup = "
    " + WinJS.UI._repeat("
    ", blockSize) + "
    ", - markup = WinJS.UI._repeat(blockMarkup, blocks); - - if (lastBlockSize) { - markup += "
    " + WinJS.UI._repeat("
    ", lastBlockSize) + "
    "; - blocks++; - } - - var blocksTemp = document.createElement("div"); - utilities.setInnerHTMLUnsafe(blocksTemp, markup); - var children = blocksTemp.children; - - for (var i = 0; i < blocks; i++) { - var block = children[i], - blockNode = { - element: block, - items: WinJS.UI._nodeListToArray(block.children) - }; - itemsContainer.itemsBlocks.push(blockNode); - for (var n = 0; n < blockNode.items.length; n++) { - that.containers.push(blockNode.items[n]); - } - } - } - - function newGroup(group) { - var node = { - header: that._listView._groupDataSource ? that._createHeaderContainer() : null, - itemsContainer: { - element: that._createItemsContainer(), - itemsBlocks: [] - } - }; - - that.tree.push(node); - that.keyToGroupIndex[group.key] = that.tree.length - 1; - - addToGroup(node.itemsContainer, group.size); - } - - if (this.tree.length && this.tree.length <= groups.length) { - var lastContainer = this.tree[this.tree.length - 1].itemsContainer, - finalSize = groups[this.tree.length - 1].size, - currentSize = 0; - - if (lastContainer.itemsBlocks.length) { - currentSize = (lastContainer.itemsBlocks.length - 1) * blockSize + lastContainer.itemsBlocks[lastContainer.itemsBlocks.length - 1].items.length; - } - - if (currentSize < finalSize) { - addToGroup(lastContainer, finalSize - currentSize); - this._listView._writeProfilerMark("createChunk,StopTM"); - return; - } - } - - if (this.tree.length < groups.length) { - newGroup(groups[this.tree.length]); - } - - this._listView._writeProfilerMark("createChunk,StopTM"); - }, - - _generateCreateContainersWorker: function VirtualizeContentsView_generateCreateContainersWorker() { - var that = this, - counter = 0, - skipWait = false; - - return function work(info) { - if (!that._listView._versionManager.locked) { - that._listView._itemsCount().then(function (count) { - var zooming = !skipWait && shouldWaitForSeZo(that._listView); - - if (!zooming) { - if (that._listView._isZombie()) { return; } - - skipWait = false; - - var end = performance.now() + _VirtualizeContentsView._createContainersJobTimeslice, - groups = that._getGroups(count), - startLength = that.containers.length, - realizedToEnd = that.end === that.containers.length, - chunkSize = WinJS.UI._VirtualizeContentsView._chunkSize; - - do { - that._blockSize ? that._createChunkWithBlocks(groups, count, that._blockSize, chunkSize) : that._createChunk(groups, count, chunkSize); - counter++; - } while (that.containers.length < count && performance.now() < end); - - that._listView._writeProfilerMark("createContainers yields containers(" + that.containers.length + "),info"); - - that._listView._affectedRange.add({ start: startLength, end: that.containers.length }, count); - - if (realizedToEnd) { - that.stopWork(); - that._listView._writeProfilerMark(that._state.name + "_relayout,info"); - that._state.relayout(); - } else { - that._listView._writeProfilerMark(that._state.name + "_layoutNewContainers,info"); - that._state.layoutNewContainers(); - } - - if (that.containers.length < count) { - info.setWork(work); - } else { - that._listView._writeProfilerMark("createContainers completed steps(" + counter + "),info"); - that._creatingContainersWork.complete(); - } - } else { - // Waiting on zooming - info.setPromise(waitForSeZo(that._listView).then(function (timedOut) { - skipWait = timedOut; - return work; - })); - } - }); - } else { - // Version manager locked - info.setPromise(that._listView._versionManager.unlocked.then(function () { - return work; - })); - } - }; - }, - - _scheduleLazyTreeCreation: function VirtualizeContentsView_scheduleLazyTreeCreation() { - return utilities.Scheduler.schedule(this._generateCreateContainersWorker(), utilities.Scheduler.Priority.idle, this, "WinJS.UI.ListView.LazyTreeCreation"); - }, - - _createContainers: function VirtualizeContentsView_createContainers() { - this.tree = null; - this.keyToGroupIndex = null; - this.containers = null; - this._expandedRange = null; - - var that = this, - count; - - return this._listView._itemsCount().then(function (c) { - if (c === 0) { - that._listView._hideProgressBar(); - } - count = c; - that._listView._writeProfilerMark("createContainers(" + count + "),StartTM"); - if (that._listView._groupDataSource) { - return that._listView._groups.initialize(); - } - }).then(function () { - that._listView._writeProfilerMark("numberOfItemsPerItemsBlock,StartTM"); - return (count && that._listView._groups.length() ? that._listView._layout.numberOfItemsPerItemsBlock : null); - }).then(function (blockSize) { - that._listView._writeProfilerMark("numberOfItemsPerItemsBlock(" + blockSize + "),info"); - that._listView._writeProfilerMark("numberOfItemsPerItemsBlock,StopTM"); - - that._listView._resetCanvas(); - - that.tree = []; - that.keyToGroupIndex = {}; - that.containers = []; - that._blockSize = blockSize; - - var groups = that._getGroups(count); - - var end = performance.now() + WinJS.UI._VirtualizeContentsView._maxTimePerCreateContainers, - chunkSize = Math.min(WinJS.UI._VirtualizeContentsView._startupChunkSize, WinJS.UI._VirtualizeContentsView._chunkSize); - do { - var stop = blockSize ? that._createChunkWithBlocks(groups, count, blockSize, chunkSize) : that._createChunk(groups, count, chunkSize); - } while (performance.now() < end && that.containers.length < count && !stop); - - that._listView._writeProfilerMark("createContainers created(" + that.containers.length + "),info"); - - that._listView._affectedRange.add({ start: 0, end: that.containers.length }, count); - - if (that.containers.length < count) { - var jobNode = that._scheduleLazyTreeCreation(); - - that._creatingContainersWork.promise.done(null, function () { - jobNode.cancel(); - }); - } else { - that._listView._writeProfilerMark("createContainers completed synchronously,info"); - that._creatingContainersWork.complete(); - } - - that._listView._writeProfilerMark("createContainers(" + count + "),StopTM"); - }); - }, - - _updateItemsBlocks: function VirtualizeContentsView_updateItemsBlocks(blockSize) { - var that = this; - var usingStructuralNodes = !!blockSize; - - function createNewBlock() { - var element = document.createElement("div"); - element.className = WinJS.UI._itemsBlockClass; - return element; - } - - function updateGroup(itemsContainer, startIndex) { - var blockElements = [], - itemsCount = 0, - blocks = itemsContainer.itemsBlocks, - b; - - function rebuildItemsContainer() { - itemsContainer.itemsBlocks = null; - itemsContainer.items = []; - for (var i = 0; i < itemsCount; i++) { - var container = that.containers[startIndex + i]; - itemsContainer.element.appendChild(container); - itemsContainer.items.push(container); - } - } - - function rebuildItemsContainerWithBlocks() { - itemsContainer.itemsBlocks = [{ - element: blockElements.length ? blockElements.shift() : createNewBlock(), - items: [] - }]; - var currentBlock = itemsContainer.itemsBlocks[0]; - for (var i = 0; i < itemsCount; i++) { - if (currentBlock.items.length === blockSize) { - var nextBlock = blockElements.length ? blockElements.shift() : createNewBlock(); - itemsContainer.itemsBlocks.push({ - element: nextBlock, - items: [] - }); - currentBlock = itemsContainer.itemsBlocks[itemsContainer.itemsBlocks.length - 1]; - } - - var container = that.containers[startIndex + i]; - currentBlock.element.appendChild(container); - currentBlock.items.push(container); - } - itemsContainer.items = null; - } - - if (blocks) { - for (b = 0; b < blocks.length; b++) { - itemsCount += blocks[b].items.length; - blockElements.push(blocks[b].element); - } - } else { - itemsCount = itemsContainer.items.length; - } - - if (usingStructuralNodes) { - rebuildItemsContainerWithBlocks(); - } else { - rebuildItemsContainer(); - } - - for (b = 0; b < blockElements.length; b++) { - var block = blockElements[b]; - if (block.parentNode === itemsContainer.element) { - itemsContainer.element.removeChild(block); - } - } - - return itemsCount; - } - - for (var g = 0, startIndex = 0; g < this.tree.length; g++) { - startIndex += updateGroup(this.tree[g].itemsContainer, startIndex); - } - - that._blockSize = blockSize; - }, - - _layoutItems: function VirtualizeContentsView_layoutItems() { - var that = this; - return this._listView._itemsCount().then(function (count) { - return Promise.as(that._listView._layout.numberOfItemsPerItemsBlock).then(function (blockSize) { - that._listView._writeProfilerMark("numberOfItemsPerItemsBlock(" + blockSize + "),info"); - if (blockSize !== that._blockSize) { - that._updateItemsBlocks(blockSize); - that._listView._itemsBlockExtent = -1; - } - - var affectedRange = that._listView._affectedRange.get(); - var changedRange; - - // We accumulate all changes that occur between layouts in _affectedRange. If layout is interrupted due to additional - // modifications, _affectedRange will become the union of the previous range of changes and the new range of changes - // and will be passed to layout again. _affectedRange is reset whenever layout completes. - if (affectedRange) { - changedRange = { - // _affectedRange is stored in the format [start, end), layout expects a range in the form of [firstIndex , lastIndex] - // To ensure that layout can successfully use the expected range to find all of the groups which need to be re-laid out - // we will pad an extra index at the front end such that layout receives [start - 1, end] in form of [lastIndex, firstIndex]. - firstIndex: Math.max(affectedRange.start - 1, 0), - lastIndex: Math.min(that.containers.length - 1, affectedRange.end) // Account for any constrained upper limits from lazily loaded win-container's. - }; - if (changedRange.firstIndex < that.containers.length || that.containers.length === 0) { - return that._listView._layout.layout(that.tree, changedRange, - that._modifiedElements || [], that._modifiedGroups || []); - } - } - - // There is nothing to layout. - that._listView._affectedRange.clear(); - return { - realizedRangeComplete: Promise.wrap(), - layoutComplete: Promise.wrap() - }; - }); - }); - }, - - updateTree: function VirtualizeContentsView_updateTree(count, delta, modifiedElements) { - this._listView._writeProfilerMark(this._state.name + "_updateTree,info"); - return this._state.updateTree(count, delta, modifiedElements); - }, - - _updateTreeImpl: function VirtualizeContentsView_updateTreeImpl(count, delta, modifiedElements, skipUnrealizeItems) { - this._executeAnimations = true; - this._modifiedElements = modifiedElements; - - if (modifiedElements.handled) { - return; - } - modifiedElements.handled = true; - - this._listView._writeProfilerMark("_updateTreeImpl,StartTM"); - - var that = this, - i; - - if (!skipUnrealizeItems) { - // If we skip unrealize items, this work will eventually happen when we reach the UnrealizingState. Sometimes, - // it is appropriate to defer the unrealize work in order to optimize scenarios (e.g, edits that happen when we are - // in the CompletedState, that way the animation can start sooner). - this._unrealizeItems(); - } - - function removeElements(array) { - for (var i = 0, len = array.length; i < len; i++) { - var itemBox = array[i]; - itemBox.parentNode.removeChild(itemBox); - } - } - - for (var i = 0, len = modifiedElements.length; i < len; i++) { - if (modifiedElements[i]._itemBox && modifiedElements[i]._itemBox.parentNode) { - utilities.removeClass(modifiedElements[i]._itemBox.parentNode, WinJS.UI._selectedClass); - } - } - - this.items.each(function (index, item, itemData) { - itemData.container && utilities.removeClass(itemData.container, WinJS.UI._selectedClass); - itemData.container && utilities.addClass(itemData.container, WinJS.UI._backdropClass); - }); - - var removedGroups = this._listView._updateContainers(this._getGroups(count), count, delta, modifiedElements); - - removeElements(removedGroups.removedHeaders); - removeElements(removedGroups.removedItemsContainers); - - for (var i = 0, len = modifiedElements.length; i < len; i++) { - var modifiedElement = modifiedElements[i]; - if (modifiedElement.newIndex !== -1) { - modifiedElement.element = this.getContainer(modifiedElement.newIndex); - if (!modifiedElement.element) { - throw "Container missing after updateContainers."; - } - } else { - utilities.removeClass(modifiedElement.element, WinJS.UI._backdropClass); - } - } - - // We only need to restore focus if the current focus is within surface - var activeElement = document.activeElement; - if (this._listView._canvas.contains(activeElement)) { - this._requireFocusRestore = activeElement - } - - this._deferredReparenting = []; - this.items.each(function (index, item, itemData) { - var container = that.getContainer(index), - itemBox = itemData.itemBox; - - if (itemBox && container) { - if (itemBox.parentNode !== container) { - if (index >= that.firstIndexDisplayed && index <= that.lastIndexDisplayed) { - that._appendAndRestoreFocus(container, itemBox); - } else { - that._deferredReparenting.push({ itemBox: itemBox, container: container }); - } - } - utilities.removeClass(container, WinJS.UI._backdropClass); - itemData.container = container; - - utilities[that._listView.selection._isIncluded(index) ? "addClass" : "removeClass"](container, WinJS.UI._selectedClass); - if (!that._listView.selection._isIncluded(index) && utilities.hasClass(itemBox, WinJS.UI._selectedClass)) { - WinJS.UI._ItemEventsHandler.renderSelection(itemBox, itemData.element, false, true); - } - } - }); - - this._listView._writeProfilerMark("_updateTreeImpl,StopTM"); - }, - - _completeUpdateTree: function () { - if (this._deferredReparenting) { - var deferredCount = this._deferredReparenting.length; - if (deferredCount > 0) { - var perfId = "_completeReparenting(" + deferredCount + ")"; - this._listView._writeProfilerMark(perfId + ",StartTM"); - var deferredItem; - for (var i = 0; i < deferredCount; i++) { - deferredItem = this._deferredReparenting[i]; - this._appendAndRestoreFocus(deferredItem.container, deferredItem.itemBox); - } - this._deferredReparenting = []; - this._listView._writeProfilerMark(perfId + ",StopTM"); - } - } - this._requireFocusRestore = null; - }, - - _appendAndRestoreFocus: function VirtualizeContentsView_appendAndRestoreFocus(container, itemBox) { - if (itemBox.parentNode !== container) { - var activeElement; - if (this._requireFocusRestore) { - activeElement = document.activeElement; - } - - if (this._requireFocusRestore && this._requireFocusRestore === activeElement && (container.contains(activeElement) || itemBox.contains(activeElement))) { - this._listView._unsetFocusOnItem(); - activeElement = document.activeElement; - } - - utilities.empty(container); - container.appendChild(itemBox); - - if (this._requireFocusRestore && activeElement === this._listView._keyboardEventsHelper) { - var focused = this._listView._selection._getFocused(); - if (focused.type === WinJS.UI.ObjectType.item && this.items.itemBoxAt(focused.index) === itemBox) { - try { - this._requireFocusRestore.setActive(); - } catch (e) { - } - this._requireFocusRestore = null; - } - } - } - }, - - _startAnimations: function VirtualizeContentsView_startAnimations() { - this._listView._writeProfilerMark("startAnimations,StartTM"); - - var that = this; - this._hasAnimationInViewportPending = false; - var animationPromise = Promise.as(this._listView._layout.executeAnimations()).then(function () { - that._listView._writeProfilerMark("startAnimations,StopTM"); - }); - return animationPromise; - }, - - _setState: function VirtualizeContentsView_setState(NewStateType, arg) { - if (!this._listView._isZombie()) { - var prevStateName = this._state.name; - this._state = new NewStateType(this, arg); - this._listView._writeProfilerMark(this._state.name + "_enter from(" + prevStateName + "),info"); - this._state.enter(); - } - }, - - getAdjacent: function VirtualizeContentsView_getAdjacent(currentFocus, direction) { - var that = this; - return this.waitForEntityPosition(currentFocus).then(function () { - return that._listView._layout.getAdjacent(currentFocus, direction); - }); - }, - - hitTest: function VirtualizeContentsView_hitTest(x, y) { - if (!this._realizedRangeLaidOut) { - var retVal = this._listView._layout.hitTest(x, y); - retVal.index = utilities._clamp(retVal.index, -1, this._listView._cachedCount - 1, 0); - retVal.insertAfterIndex = utilities._clamp(retVal.insertAfterIndex, -1, this._listView._cachedCount - 1, 0); - return retVal; - } else { - return { - index: -1, - insertAfterIndex: -1 - }; - }; - }, - - _createTreeBuildingSignal: function VirtualizeContentsView__createTreeBuildingSignal() { - if (!this._creatingContainersWork) { - this._creatingContainersWork = new WinJS._Signal(); - - var that = this; - this._creatingContainersWork.promise.done( - function () { - that._creatingContainersWork = null; - }, - function (error) { - that._creatingContainersWork = null; - } - ); - } - }, - - _createLayoutSignal: function VirtualizeContentsView_createLayoutSignal() { - var that = this; - - if (!this._layoutCompleted) { - this._layoutCompleted = new WinJS._Signal(); - - this._layoutCompleted.promise.done( - function () { - that._layoutCompleted = null; - }, - function (error) { - that._layoutCompleted = null; - } - ); - } - - if (!this._realizedRangeLaidOut) { - this._realizedRangeLaidOut = new WinJS._Signal(); - this._realizedRangeLaidOut.promise.done( - function () { - that._realizedRangeLaidOut = null; - }, - function (error) { - that._realizedRangeLaidOut = null; - } - ); - } - }, - - _getLayoutCompleted: function VirtualizeContentsView_getLayoutCompleted() { - return this._layoutCompleted ? WinJS.Promise._cancelBlocker(this._layoutCompleted.promise) : Promise.wrap(); - }, - - _createSurfaceChild: function VirtualizeContentsView_createSurfaceChild(className, insertAfter) { - var element = document.createElement("div"); - element.className = className; - this._listView._canvas.insertBefore(element, insertAfter ? insertAfter.nextElementSibling : null); - return element; - }, - - _executeScrollToFunctor: function VirtualizeContentsView_executeScrollToFunctor() { - var that = this; - return Promise.as(this._scrollToFunctor ? this._scrollToFunctor() : null).then(function (scroll) { - that._scrollToFunctor = null; - - scroll = scroll || {}; - // _scrollbarPos is initialized to 0 in the constructor, and we only set it when a valid integer - // value is passed in order to account for cases when there is not a _scrollToFunctor - if (+scroll.position === scroll.position) { - that._scrollbarPos = scroll.position; - } - that._direction = scroll.direction || "right"; - }); - } - }; - - - function nop() { } - - /* - View is in this state before reload is called so during startup, after datasource change etc. - */ - - var CreatedState = WinJS.Class.define(function CreatedState_ctor(view) { - this.view = view; - this.view._createTreeBuildingSignal(); - this.view._createLayoutSignal(); - }, { - name: 'CreatedState', - enter: function CreatedState_enter() { - this.view._createTreeBuildingSignal(); - this.view._createLayoutSignal(); - }, - stop: nop, - realizePage: nop, - rebuildTree: function CreatedState_rebuildTree() { - this.view._setState(BuildingState); - }, - relayout: function CreatedState_relayout() { - this.view._setState(BuildingState); - }, - layoutNewContainers: nop, - waitForEntityPosition: function CreatedState_waitForEntityPosition(entity) { - this.view._setState(BuildingState); - return this.view._getLayoutCompleted(); - }, - updateTree: nop - }); - - /* - In this state View is building its DOM tree with win-container element for each item in the data set. - To build the tree the view needs to know items count or for grouped case the count of groups and the - count of items in each group. The view enters this state when the tree needs to be built during - startup or rebuild after data source change and etc. - - BuildingState => LayingoutState | CreatedState - */ - var BuildingState = WinJS.Class.define(function BuildingState_ctor(view) { - this.view = view; - }, { - name: 'BuildingState', - enter: function BuildingState_enter() { - this.canceling = false; - this.view._createTreeBuildingSignal(); - this.view._createLayoutSignal(); - - var that = this; - - // Use a signal to guarantee that this.promise is set before the promise - // handler is executed. - var promiseStoredSignal = new WinJS._Signal(); - this.promise = promiseStoredSignal.promise.then(function () { - return that.view._createContainers(); - }).then( - function () { - that.view._setState(LayingoutState); - }, - function (error) { - if (!that.canceling) { - // this is coming from layout. ListView is hidden. We need to raise complete and wait in initial state for further actions - that.view._setState(CreatedState); - that.view._listView._raiseViewComplete(); - } - return Promise.wrapError(error); - } - ); - promiseStoredSignal.complete(); - }, - stop: function BuildingState_stop() { - this.canceling = true; - this.promise.cancel(); - this.view._setState(CreatedState); - }, - realizePage: nop, - rebuildTree: function BuildingState_rebuildTree() { - this.canceling = true; - this.promise.cancel(); - this.enter(); - }, - relayout: nop, - layoutNewContainers: nop, - waitForEntityPosition: function BuildingState_waitForEntityPosition(entity) { - return this.view._getLayoutCompleted(); - }, - updateTree: nop - }); - - /* - In this state View waits for the layout to lay out win-container elements. The view enters this state - after edits or resize. - - LayingoutState => RealizingState | BuildingState | CanceledState | CompletedState | LayoutCanceledState - */ - var LayingoutState = WinJS.Class.define(function LayingoutState_ctor(view, NextStateType) { - this.view = view; - this.nextStateType = NextStateType || RealizingState; - }, { - name: 'LayingoutState', - enter: function LayingoutState_enter() { - var that = this; - this.canceling = false; - this.view._createLayoutSignal(); - - this.view._listView._writeProfilerMark(this.name + "_enter_layoutItems,StartTM"); - - // Use a signal to guarantee that this.promise is set before the promise - // handler is executed. - var promiseStoredSignal = new WinJS._Signal(); - this.promise = promiseStoredSignal.promise.then(function () { - return that.view._layoutItems(); - }).then(function (layoutPromises) { - - // View is taking ownership of this promise and it will cancel it in stopWork - that.view._layoutWork = layoutPromises.layoutComplete; - - return layoutPromises.realizedRangeComplete; - }).then( - function () { - that.view._listView._writeProfilerMark(that.name + "_enter_layoutItems,StopTM"); - - that.view._listView._clearInsertedItems(); - that.view._setAnimationInViewportState(that.view._modifiedElements); - that.view._modifiedElements = []; - that.view._modifiedGroups = []; - - that.view._realizedRangeLaidOut.complete(); - - that.view._layoutWork.then(function () { - that.view._listView._writeProfilerMark(that.name + "_enter_layoutCompleted,info"); - that.view._listView._affectedRange.clear(); - that.view._layoutCompleted.complete(); - }); - - if (!that.canceling) { - that.view._setState(that.nextStateType); - } - }, - function (error) { - that.view._listView._writeProfilerMark(that.name + "_enter_layoutCanceled,info"); - - if (!that.canceling) { - // Cancel is coming from layout itself so ListView is hidden or empty. In this case we want to raise loadingStateChanged - that.view.firstIndexDisplayed = that.view.lastIndexDisplayed = -1; - that.view._updateAriaMarkers(true, that.view.firstIndexDisplayed, that.view.lastIndexDisplayed); - that.view._setState(CompletedState); - } - - return Promise.wrapError(error); - } - ); - promiseStoredSignal.complete(); - - if (this.canceling) { - this.promise.cancel(); - } - }, - cancelLayout: function LayingoutState_cancelLayout(switchState) { - this.view._listView._writeProfilerMark(this.name + "_cancelLayout,info"); - this.canceling = true; - if (this.promise) { - this.promise.cancel(); - } - if (switchState) { - this.view._setState(LayoutCanceledState); - } - }, - stop: function LayingoutState_stop() { - this.cancelLayout(true); - }, - realizePage: nop, - rebuildTree: function LayingoutState_rebuildTree() { - this.cancelLayout(false); - this.view._setState(BuildingState); - }, - relayout: function LayingoutState_relayout() { - this.cancelLayout(false); - this.enter(); - }, - layoutNewContainers: function LayingoutState_layoutNewContainers() { - this.relayout(); - }, - waitForEntityPosition: function LayingoutState_waitForEntityPosition(entity) { - return this.view._getLayoutCompleted(); - }, - updateTree: function LayingoutState_updateTree(count, delta, modifiedElements) { - return this.view._updateTreeImpl(count, delta, modifiedElements); - } - }); - - - /* - View enters this state when layout is canceled. - - LayoutCanceledState => LayingoutState | BuildingState - */ - var LayoutCanceledState = WinJS.Class.define(function LayoutCanceledState_ctor(view) { - this.view = view; - }, { - name: 'LayoutCanceledState', - enter: nop, - stop: nop, - realizePage: function LayoutCanceledState_realizePage() { - this.relayout(); - }, - rebuildTree: function LayoutCanceledState_rebuildTree() { - this.view._setState(BuildingState); - }, - relayout: function LayoutCanceledState_relayout() { - this.view._setState(LayingoutState); - }, - layoutNewContainers: function LayoutCanceledState_layoutNewContainers() { - this.relayout(); - }, - waitForEntityPosition: function LayoutCanceledState_waitForEntityPosition(entity) { - return this.view._getLayoutCompleted(); - }, - updateTree: function LayoutCanceledState_updateTree(count, delta, modifiedElements) { - return this.view._updateTreeImpl(count, delta, modifiedElements); - } - }); - - /* - Contents of items in the current viewport and prefetch area is realized during this stage. - The view enters this state when items needs to be realized for instance during initialization, edits and resize. - - RealizingState => RealizingAnimatingState | UnrealizingState | LayingoutState | BuildingState | CanceledState - */ - var RealizingState = WinJS.Class.define(function RealizingState_ctor(view) { - this.view = view; - this.nextState = UnrealizingState; - this.relayoutNewContainers = true; - }, { - name: 'RealizingState', - enter: function RealizingState_enter() { - var that = this; - var promiseStoredSignal = new WinJS._Signal(); - this.promise = promiseStoredSignal.promise.then(function () { - return that.view._executeScrollToFunctor(); - }).then(function () { - that.relayoutNewContainers = false; - return Promise._cancelBlocker(that.view._realizePageImpl()); - }).then( - function () { - if (that.view._state === that) { - that.view._completeUpdateTree(); - that.view._listView._writeProfilerMark("RealizingState_to_UnrealizingState"); - that.view._setState(that.nextState); - } - }, - function (error) { - if (that.view._state === that && !that.canceling) { - that.view._listView._writeProfilerMark("RealizingState_to_CanceledState"); - that.view._setState(CanceledState); - } - return Promise.wrapError(error); - } - ); - promiseStoredSignal.complete(); - }, - stop: function RealizingState_stop() { - this.canceling = true; - this.promise.cancel(); - this.view._cancelRealize(); - this.view._setState(CanceledState); - }, - realizePage: function RealizingState_realizePage() { - this.canceling = true; - this.promise.cancel(); - this.enter(); - }, - rebuildTree: function RealizingState_rebuildTree() { - this.stop(); - this.view._setState(BuildingState); - }, - relayout: function RealizingState_relayout() { - this.stop(); - this.view._setState(LayingoutState); - }, - layoutNewContainers: function RealizingState_layoutNewContainers() { - if (this.relayoutNewContainers) { - this.relayout(); - } else { - this.view._createLayoutSignal(); - this.view._relayoutInComplete = true; - } - }, - waitForEntityPosition: function RealizingState_waitForEntityPosition(entity) { - return this.view._getLayoutCompleted(); - }, - updateTree: function RealizingState_updateTree(count, delta, modifiedElements) { - return this.view._updateTreeImpl(count, delta, modifiedElements); - }, - setLoadingState: function RealizingState_setLoadingState(state) { - this.view._listView._setViewState(state); - } - }); - - /* - The view enters this state when the realize pass, animations or unrealizing was canceled or after newContainers have been laid out. - In this state view waits for the next call from ListViewImpl. It can be scroll, edit etc. - - CanceledState => RealizingState | ScrollingState | LayingoutState | BuildingState - */ - var CanceledState = WinJS.Class.define(function CanceledState_ctor(view) { - this.view = view; - }, { - name: 'CanceledState', - enter: nop, - stop: function CanceledState_stop() { - // cancelRealize cancels ariaSetup which can still be in progress - this.view._cancelRealize(); - }, - realizePage: function CanceledState_realizePage(NewStateType) { - this.stop(); - this.view._setState(NewStateType); - }, - rebuildTree: function CanceledState_rebuildTree() { - this.stop(); - this.view._setState(BuildingState); - }, - relayout: function CanceledState_relayout(NextStateType) { - this.stop(); - this.view._setState(LayingoutState, NextStateType); - }, - layoutNewContainers: function CanceledState_layoutNewContainers() { - this.relayout(CanceledState); - }, - waitForEntityPosition: function CanceledState_waitForEntityPosition(entity) { - return this.view._getLayoutCompleted(); - }, - updateTree: function CanceledState_updateTree(count, delta, modifiedElements) { - return this.view._updateTreeImpl(count, delta, modifiedElements); - } - }); - - /* - This state is almost identical with RealizingState. Currently the difference is that in this state loadingStateChanged events aren’t - raised and after complete the state is switched to ScrollingPausedState to wait until end of scrolling. - - ScrollingState => RealizingAnimatingState | ScrollingPausedState | LayingoutState | BuildingState | CanceledState - */ - var ScrollingState = WinJS.Class.derive(RealizingState, function ScrollingState_ctor(view) { - this.view = view; - this.nextState = ScrollingPausedState; - this.relayoutNewContainers = true; - }, { - name: 'ScrollingState', - setLoadingState: function ScrollingState_setLoadingState(state) { - } - }); - - /* - The view waits in this state for end of scrolling which for touch is signaled by MSManipulationStateChanged event and for mouse it is timeout. - - ScrollingPausedState => RealizingAnimatingState | ScrollingPausedState | LayingoutState | BuildingState | CanceledState - */ - var ScrollingPausedState = WinJS.Class.derive(CanceledState, function ScrollingPausedState_ctor(view) { - this.view = view; - }, { - name: 'ScrollingPausedState', - enter: function ScrollingPausedState_enter() { - var that = this; - this.promise = Promise._cancelBlocker(this.view._scrollEndPromise).then(function () { - that.view._setState(UnrealizingState); - }); - }, - stop: function ScrollingPausedState_stop() { - this.promise.cancel(); - // cancelRealize cancels ariaSetup which can still be in progress - this.view._cancelRealize(); - }, - }); - - /* - In this state, view unrealizes not needed items and then waits for all renderers to complete. - - UnrealizingState => CompletedState | RealizingState | ScrollingState | LayingoutState | BuildingState | CanceledState - */ - var UnrealizingState = WinJS.Class.define(function UnrealizingState_ctor(view) { - this.view = view; - }, { - name: 'UnrealizingState', - enter: function UnrealizingState_enter() { - var that = this; - this.promise = this.view._lazilyUnrealizeItems().then(function () { - that.view._listView._writeProfilerMark("_renderCompletePromise wait starts,info"); - return that.view._renderCompletePromise; - }).then(function () { - that.view._setState(CompletedState); - }); - }, - stop: function UnrealizingState_stop() { - // cancelRealize cancels ariaSetup which can still be in progress - this.view._cancelRealize(); - this.promise.cancel(); - this.view._setState(CanceledState); - }, - realizePage: function UnrealizingState_realizePage(NewStateType) { - this.promise.cancel(); - this.view._setState(NewStateType); - }, - rebuildTree: function UnrealizingState_rebuildTree() { - this.view._setState(BuildingState); - }, - relayout: function UnrealizingState_relayout() { - this.view._setState(LayingoutState); - }, - layoutNewContainers: function UnrealizingState_layoutNewContainers() { - this.view._createLayoutSignal(); - this.view._relayoutInComplete = true; - }, - waitForEntityPosition: function UnrealizingState_waitForEntityPosition(entity) { - return this.view._getLayoutCompleted(); - }, - updateTree: function UnrealizingState_updateTree(count, delta, modifiedElements) { - return this.view._updateTreeImpl(count, delta, modifiedElements); - } - }); - - /* - We enter this state, when there are animations to execute, and we have already fired the viewportloaded event - - RealizingAnimatingState => RealizingState | UnrealizingState | LayingoutState | BuildingState | CanceledState - */ - var RealizingAnimatingState = WinJS.Class.define(function RealizingStateAnimating_ctor(view, realizePromise) { - this.view = view; - this.realizePromise = realizePromise; - this.realizeId = 1; - }, { - name: 'RealizingAnimatingState', - enter: function RealizingAnimatingState_enter() { - var that = this; - - - this.animating = true; - this.animatePromise = this.view._startAnimations(); - this.animateSignal = new WinJS._Signal(); - this.view._executeAnimations = false; - - this.animatePromise.done( - function () { - that.animating = false; - if (that.modifiedElements) { - that.view._updateTreeImpl(that.count, that.delta, that.modifiedElements); - that.modifiedElements = null; - that.view._setState(CanceledState); - } else { - that.animateSignal.complete(); - } - }, function (error) { - that.animating = false; - return Promise.wrapError(error); - } - ); - - this._waitForRealize(); - }, - - _waitForRealize: function RealizingAnimatingState_waitForRealize() { - var that = this; - - this.realizing = true; - this.realizePromise.done(function () { - that.realizing = false; - }); - - var currentRealizeId = ++this.realizeId; - Promise.join([this.realizePromise, this.animateSignal.promise]).done(function () { - if (currentRealizeId === that.realizeId) { - that.view._completeUpdateTree(); - that.view._listView._writeProfilerMark("RealizingAnimatingState_to_UnrealizingState"); - that.view._setState(UnrealizingState); - } - }); - }, - - stop: function RealizingAnimatingState_stop(stopTreeCreation) { - // always cancel realization - this.realizePromise.cancel(); - this.view._cancelRealize(); - - // animations are canceled only when tree needs to be rebuilt - if (stopTreeCreation) { - this.animatePromise.cancel(); - this.view._setState(CanceledState); - } - }, - realizePage: function RealizingAnimatingState_realizePage() { - if (!this.modifiedElements) { - var that = this; - this.realizePromise = this.view._executeScrollToFunctor().then(function () { - return Promise._cancelBlocker(that.view._realizePageImpl()); - }); - this._waitForRealize(); - } - }, - rebuildTree: function RealizingAnimatingState_rebuildTree() { - this.stop(true); - this.view._setState(BuildingState); - }, - relayout: function RealizingAnimatingState_relayout() { - // Relayout caused by edits should be stopped by updateTree but relayout can be caused by resize or containers creation and in these cases we should stop animations - this.stop(true); - // if tree update was waiting for animations we should do it now - if (this.modifiedElements) { - this.view._updateTreeImpl(this.count, this.delta, this.modifiedElements); - this.modifiedElements = null; - } - this.view._setState(LayingoutState); - }, - layoutNewContainers: function RealizingAnimatingState_layoutNewContainers() { - this.view._createLayoutSignal(); - this.view._relayoutInComplete = true; - }, - waitForEntityPosition: function RealizingAnimatingState_waitForEntityPosition(entity) { - return this.view._getLayoutCompleted(); - }, - updateTree: function RealizingAnimatingState_updateTree(count, delta, modifiedElements) { - if (this.animating) { - var previousModifiedElements = this.modifiedElements; - this.count = count; - this.delta = delta; - this.modifiedElements = modifiedElements; - - return previousModifiedElements ? WinJS.Promise.cancel : this.animatePromise; - } else { - return this.view._updateTreeImpl(count, delta, modifiedElements); - } - }, - setLoadingState: function RealizingAnimatingState_setLoadingState(state) { - this.view._listView._setViewState(state); - } - }); - - /* - The view enters this state when the tree is built, layout and realized after animations have - finished. The layout can still laying out items outside of realized view during this stage. - - CompletedState => RealizingState | ScrollingState | LayingoutState | BuildingState | LayingoutNewContainersState - */ - var CompletedState = WinJS.Class.derive(CanceledState, function CompletedState_ctor(view) { - this.view = view; - }, { - name: 'CompletedState', - enter: function CompletedState_enter() { - this._stopped = false; - this.view._setupDeferredActions(); - - this.view._realizationLevel = WinJS.UI._VirtualizeContentsView._realizationLevel.normal; - this.view._listView._raiseViewComplete(); - - // _raiseViewComplete will cause user event listener code to run synchronously. - // If any updates are made to the Listview, this state will be stopped by the updater. - // We don't want to change state to LayingoutNewContainersState if that happens. - if (this.view._state === this && this.view._relayoutInComplete && !this._stopped) { - this.view._setState(LayingoutNewContainersState); - } - }, - stop: function CompletedState_stop() { - this._stopped = true; - // Call base class method. - CanceledState.prototype.stop.call(this); - }, - layoutNewContainers: function CompletedState_layoutNewContainers() { - this.view._createLayoutSignal(); - this.view._setState(LayingoutNewContainersState); - }, - updateTree: function CompletedState_updateTree(count, delta, modifiedElements) { - return this.view._updateTreeImpl(count, delta, modifiedElements, true); - } - }); - - /* - The view waits in this state for previous layout pass to finish. - - LayingoutNewContainersState => RealizingState | ScrollingState | LayingoutState | BuildingState - */ - var LayingoutNewContainersState = WinJS.Class.derive(CanceledState, function LayingoutNewContainersState(view) { - this.view = view; - }, { - name: 'LayingoutNewContainersState', - enter: function LayingoutNewContainersState_enter() { - var that = this; - - // _layoutWork is completed when the previous layout pass is done. _getLayoutCompleted will be completed when these new containers are laid out - this.promise = WinJS.Promise.join([this.view.deferTimeout, this.view._layoutWork]); - this.promise.then(function () { - that.view._relayoutInComplete = false; - that.relayout(CanceledState); - }); - }, - stop: function LayingoutNewContainersState_stop() { - // cancelRealize cancels ariaSetup which can still be in progress - this.promise.cancel(); - this.view._cancelRealize(); - }, - realizePage: function LayingoutNewContainersState_realizePage(NewStateType) { - // in this state realizePage needs to run layout before realizing items - this.stop(); - this.view._setState(LayingoutState, NewStateType); - }, - layoutNewContainers: function LayingoutNewContainersState_layoutNewContainers() { - this.view._createLayoutSignal(); - } - }); - - return _VirtualizeContentsView; - }) - }); - -})(this, WinJS); - -(function datePickerInit(WinJS, undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// Allows users to pick a date value. - /// - /// - /// Date Picker - /// - /// - /// ]]> - /// Occurs when the current date changes. - /// - /// - /// - DatePicker: WinJS.Namespace._lazy(function () { - // Constants definition - var DEFAULT_DAY_PATTERN = 'day', - DEFAULT_MONTH_PATTERN = '{month.full}', - DEFAULT_YEAR_PATTERN = 'year.full'; - - var strings = { - get ariaLabel() { return WinJS.Resources._getWinJSString("ui/datePicker").value; }, - get selectDay() { return WinJS.Resources._getWinJSString("ui/selectDay").value; }, - get selectMonth() { return WinJS.Resources._getWinJSString("ui/selectMonth").value; }, - get selectYear() { return WinJS.Resources._getWinJSString("ui/selectYear").value; }, - }; - - var yearFormatCache = {}; - - function newFormatter(pattern, calendar, defaultPattern) { - var dtf = Windows.Globalization.DateTimeFormatting; - pattern = !pattern ? defaultPattern : pattern; - var c = new dtf.DateTimeFormatter(pattern); - if (calendar) { - return new dtf.DateTimeFormatter(pattern, c.languages, c.geographicRegion, calendar, c.clock); - } - return c; - }; - - function formatCacheLookup(pattern, calendar, defaultPattern) { - var pat = yearFormatCache[pattern]; - if (!pat) { - pat = yearFormatCache[pattern] = {}; - } - var cal = pat[calendar]; - if (!cal) { - cal = pat[calendar] = {}; - } - var def = cal[defaultPattern]; - if (!def) { - def = cal[defaultPattern] = {}; - def.formatter = newFormatter(pattern, calendar, defaultPattern); - def.years = {}; - } - return def; - } - - function formatYear(pattern, calendar, defaultPattern, datePatterns, order, cal) { - var cache = formatCacheLookup(pattern, calendar, defaultPattern); - var y = cache.years[cal.year + "-" + cal.era]; - if (!y) { - y = cache.formatter.format(cal.getDateTime()); - cache.years[cal.year + "-" + cal.era] = y; - } - return y; - } - - function formatMonth(pattern, calendar, defaultPattern, cal) { - var cache = formatCacheLookup(pattern, calendar, defaultPattern); - // can't cache actual month names because the hebrew calendar varies - // the month name depending on religious holidays and leap months. - // - return cache.formatter.format(cal.getDateTime()); - } - - function formatDay(pattern, calendar, defaultPattern, cal) { - var cache = formatCacheLookup(pattern, calendar, defaultPattern); - // can't cache actual day names because the format may include the day of the week, - // which, of course, varies from month to month. - // - return cache.formatter.format(cal.getDateTime()); - } - - function newCal(calendar) { - var glob = Windows.Globalization; - var c = new glob.Calendar(); - if (calendar) { - return new glob.Calendar(c.languages, calendar, c.getClock()); - } - return c; - }; - - function yearDiff(start, end) { - var yearCount = 0; - - if (start.era == end.era) { - yearCount = end.year - start.year; - } - else { - while (start.era !== end.era || start.year !== end.year) { - yearCount++; - start.addYears(1); - } - } - return yearCount; - } - - var DatePicker = WinJS.Class.define(function DatePicker_ctor(element, options) { - /// - /// Creates a new DatePicker control. - /// - /// The DOM element that will host the DatePicker control. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. Each property of the options object corresponds - /// to one of the control's properties or events. - /// - /// A constructed DatePicker control. - /// - /// - - // Default to current date - this._currentDate = new Date(); - - // Default to +/- 100 years - this._minYear = this._currentDate.getFullYear() - 100; - this._maxYear = this._currentDate.getFullYear() + 100; - this._datePatterns = { - date: null, - month: null, - year: null - }; - - element = element || document.createElement("div"); - WinJS.Utilities.addClass(element, "win-disposable"); - element.winControl = this; - - var label = element.getAttribute("aria-label"); - if (!label) { - element.setAttribute("aria-label", strings.ariaLabel); - } - - // Options should be set after the element is initialized which is - // the same order of operation as imperatively setting options. - this._init(element); - WinJS.UI.setOptions(this, options); - }, { - _information: null, - _currentDate: null, - _calendar: null, - _disabled: false, - _dateElement: null, - _dateControl: null, - _monthElement: null, - _monthControl: null, - _minYear: null, - _maxYear: null, - _yearElement: null, - _yearControl: null, - _datePatterns: { - date: null, - month: null, - year: null - }, - - _addAccessibilityAttributes: function () { - //see http://www.w3.org/TR/wai-aria/rdf_model.png for details - this._domElement.setAttribute("role", "group"); - - this._dateElement.setAttribute("aria-label", strings.selectDay); - this._monthElement.setAttribute("aria-label", strings.selectMonth); - this._yearElement.setAttribute("aria-label", strings.selectYear); - }, - - _addControlsInOrder: function () { - var e = this._domElement; - var u = WinJS.Utilities; - var that = this; - var orderIndex = 0; // don't use forEach's index, because "era" is in the list - that._information.order.forEach(function (s) { - switch (s) { - case "month": - e.appendChild(that._monthElement); - u.addClass(that._monthElement, "win-order" + (orderIndex++)); - break; - case "date": - e.appendChild(that._dateElement); - u.addClass(that._dateElement, "win-order" + (orderIndex++)); - break; - case "year": - e.appendChild(that._yearElement); - u.addClass(that._yearElement, "win-order" + (orderIndex++)); - break; - } - }); - }, - - _createControlElements: function () { - this._monthElement = document.createElement("select"); - this._monthElement.className = "win-datepicker-month"; - this._dateElement = document.createElement("select"); - this._dateElement.className = "win-datepicker-date"; - this._yearElement = document.createElement("select"); - this._yearElement.className = "win-datepicker-year"; - }, - - _createControls: function () { - var that = this; - - var info = this._information; - var index = info.getIndex(this.current); - - if (info.forceLanguage) { - this._domElement.setAttribute("lang", info.forceLanguage); - this._domElement.setAttribute("dir", info.isRTL ? "rtl" : "ltr"); - } - - - this._yearControl = new WinJS.UI._Select(this._yearElement, { - dataSource: this._information.years, - disabled: this.disabled, - index: index.year - }); - - this._monthControl = new WinJS.UI._Select(this._monthElement, { - dataSource: this._information.months(index.year), - disabled: this.disabled, - index: index.month - }); - - this._dateControl = new WinJS.UI._Select(this._dateElement, { - dataSource: this._information.dates(index.year, index.month), - disabled: this.disabled, - index: index.date - }); - - this._wireupEvents(); - }, - dispose: function () { - /// - /// - /// Disposes this control. - /// - /// - /// - }, - - /// - /// Gets or sets the calendar to use. - /// - /// - calendar: { - get: function () { - return this._calendar; - }, - set: function (value) { - this._calendar = value; - this._setElement(this._domElement); - } - }, - - /// - /// Gets or sets the current date of the DatePicker. - /// - /// - current: { - get: function () { - var d = this._currentDate; - var y = d.getFullYear(); - return new Date(Math.max(Math.min(this.maxYear, y), this.minYear), d.getMonth(), d.getDate(), 12, 0, 0, 0); - }, - set: function (value) { - var newDate; - if (typeof (value) === "string") { - newDate = new Date(Date.parse(value)); - newDate.setHours(12, 0, 0, 0); - } - else { - newDate = value; - } - - var oldDate = this._currentDate; - if (oldDate != newDate) { - this._currentDate = newDate; - this._updateDisplay(); - } - } - }, - - /// - /// Gets or sets a value that specifies whether the DatePicker is disabled. A value of true indicates that the DatePicker is disabled. - /// - /// - disabled: { - get: function () { return this._disabled; }, - set: function (value) { - if (this._disabled !== value) { - this._disabled = value; - // all controls get populated at the same time, so any check is OK - // - if (this._yearControl) { - this._monthControl.setDisabled(value); - this._dateControl.setDisabled(value); - this._yearControl.setDisabled(value); - } - } - } - }, - - /// - /// Gets or sets the display pattern for the date. - /// - /// - datePattern: { - get: function () { return this._datePatterns.date; }, - set: function (value) { - if (this._datePatterns.date !== value) { - this._datePatterns.date = value; - this._init(); - } - } - }, - - - /// - element: { - get: function () { return this._domElement; } - }, - - _setElement: function (element) { - this._domElement = this._domElement || element; - if (!this._domElement) { return; } - - WinJS.Utilities.empty(this._domElement); - WinJS.Utilities.addClass(this._domElement, "win-datepicker"); - - this._updateInformation(); - - this._createControlElements(); - this._addControlsInOrder(); - this._createControls(); - this._addAccessibilityAttributes(); - }, - - /// - /// Gets or sets the minimum Gregorian year available for picking. - /// - /// - minYear: { - get: function () { - return this._information.getDate({ year: 0, month: 0, date: 0 }).getFullYear(); - }, - set: function (value) { - if (this._minYear !== value) { - this._minYear = value; - if (value > this._maxYear) { - this._maxYear = value; - } - this._updateInformation(); - if (this._yearControl) { - this._yearControl.dataSource = this._information.years; - } - - this._updateDisplay(); - } - } - }, - - /// - /// Gets or sets the maximum Gregorian year available for picking. - /// - /// - maxYear: { - get: function () { - var index = { - year: this._information.years.getLength() - 1 - }; - index.month = this._information.months(index.year).getLength() - 1; - index.date = this._information.dates(index.year, index.month).getLength() - 1; - return this._information.getDate(index).getFullYear(); - }, - set: function (value) { - if (this._maxYear !== value) { - this._maxYear = value; - if (value < this._minYear) { - this._minYear = value; - } - this._updateInformation(); - if (this._yearControl) { - this._yearControl.dataSource = this._information.years; - } - - this._updateDisplay(); - } - } - }, - - /// - /// Gets or sets the display pattern for the month. - /// - /// - monthPattern: { - get: function () { return this._datePatterns.month; }, - set: function (value) { - if (this._datePatterns.month !== value) { - this._datePatterns.month = value; - this._init(); - } - } - }, - - _updateInformation: function () { - // since "year" in the date ctor can be two digit (85 == 1985), we need - // to force "full year" to capture dates < 100 a.d. - // - var min = new Date(this._minYear, 0, 1, 12, 0, 0); - var max = new Date(this._maxYear, 11, 31, 12, 0, 0); - min.setFullYear(this._minYear); - max.setFullYear(this._maxYear); - - this._information = WinJS.UI.DatePicker.getInformation(min, max, this._calendar, this._datePatterns); - }, - - _init: function (element) { - this._setElement(element); - }, - - _updateDisplay: function () { - if (!this._domElement) - return; - - // all controls get populated at the same time, so any check is OK - // - if (this._yearControl) { - //Render display index based on constraints (minYear and maxYear constraints) - //Will not modify current date - var index = this._information.getIndex(this.current); - - this._yearControl.index = index.year; - this._monthControl.dataSource = this._information.months(index.year); - this._monthControl.index = index.month; - this._dateControl.dataSource = this._information.dates(index.year, index.month); - this._dateControl.index = index.date; - } - }, - - _wireupEvents: function () { - var that = this; - function changed() { - that._currentDate = that._information.getDate({ year: that._yearControl.index, month: that._monthControl.index, date: that._dateControl.index }, that._currentDate); - var index = that._information.getIndex(that._currentDate); - - // Changing the month (or year, if the current date is 2/29) changes the day range, and could have made the day selection invalid - that._monthControl.dataSource = that._information.months(index.year) - that._monthControl.index = index.month; - that._dateControl.dataSource = that._information.dates(index.year, index.month); - that._dateControl.index = index.date; - } - - this._dateElement.addEventListener("change", changed, false); - this._monthElement.addEventListener("change", changed, false); - this._yearElement.addEventListener("change", changed, false); - }, - - /// - /// Gets or sets the display pattern for year. - /// - /// - yearPattern: { - get: function () { return this._datePatterns.year; }, - set: function (value) { - if (this._datePatterns.year !== value) { - this._datePatterns.year = value; - this._init(); - } - } - }, - }, { - _getInformationWinRT: function (startDate, endDate, calendar, datePatterns) { - datePatterns = datePatterns || { date: DEFAULT_DAY_PATTERN, month: DEFAULT_MONTH_PATTERN, year: DEFAULT_YEAR_PATTERN }; - - var tempCal = newCal(calendar); - var monthCal = newCal(calendar); - var dayCal = newCal(calendar); - - tempCal.setToMin(); - var minDateTime = tempCal.getDateTime(); - tempCal.setToMax(); - var maxDateTime = tempCal.getDateTime(); - - function clamp(date) { - return new Date(Math.min(new Date(Math.max(minDateTime, date)), maxDateTime));; - } - - tempCal.hour = 12; - - startDate = clamp(startDate); - endDate = clamp(endDate); - - tempCal.setDateTime(endDate); - var end = { year: tempCal.year, era: tempCal.era }; - - tempCal.setDateTime(startDate); - var minYear = tempCal.year; - var yearLen = 0; - - yearLen = yearDiff(tempCal, end) + 1; - - // Explicity use a template that's equivalent to a longdate template - // as longdate/shortdate can be overriden by the user - var dateformat = formatCacheLookup("day month.full year", calendar).formatter; - var localdatepattern = dateformat.patterns[0]; - var isRTL = localdatepattern.charCodeAt(0) === 8207; - var order = ["date", "month", "year"]; - - var indexes = { - month: localdatepattern.indexOf("{month"), - date: localdatepattern.indexOf("{day"), - year: localdatepattern.indexOf("{year") - }; - order.sort(function (a, b) { - if (indexes[a] < indexes[b]) { return -1; } - else if (indexes[a] > indexes[b]) { return 1; } - else { return 0; } - }); - - var yearSource = (function () { - return { - getLength: function () { return yearLen; }, - getValue: function (index) { - tempCal.setDateTime(startDate); - tempCal.addYears(index); - - return formatYear(datePatterns.year, calendar, DEFAULT_YEAR_PATTERN, datePatterns, order, tempCal); - } - } - })(); - - var monthSource = function (yearIndex) { - monthCal.setDateTime(startDate); - monthCal.addYears(yearIndex); - - return { - getLength: function () { return monthCal.numberOfMonthsInThisYear; }, - getValue: function (index) { - monthCal.month = monthCal.firstMonthInThisYear; - monthCal.addMonths(index); - return formatMonth(datePatterns.month, calendar, DEFAULT_MONTH_PATTERN, monthCal); - } - }; - }; - - var dateSource = function (yearIndex, monthIndex) { - dayCal.setDateTime(startDate); - dayCal.addYears(yearIndex); - dayCal.month = dayCal.firstMonthInThisYear; - dayCal.addMonths(monthIndex); - dayCal.day = dayCal.firstDayInThisMonth; - - return { - getLength: function () { return dayCal.numberOfDaysInThisMonth; }, - getValue: function (index) { - dayCal.day = dayCal.firstDayInThisMonth; - dayCal.addDays(index); - return formatDay(datePatterns.date, calendar, DEFAULT_DAY_PATTERN, dayCal); - } - }; - }; - - return { - isRTL: isRTL, - forceLanguage: dateformat.resolvedLanguage, - - order: order, - - getDate: function (index, lastDate) { - var lastCal; - - if (lastDate) { - tempCal.setDateTime(lastDate); - lastCal = { year: tempCal.year, month: tempCal.month, day: tempCal.day }; - } - - var c = tempCal; - c.setDateTime(startDate); - c.addYears(index.year); - - var guessMonth; - if (c.firstMonthInThisYear > c.lastMonthInThisYear) { - if (index.month + c.firstMonthInThisYear > c.numberOfMonthsInThisYear) { - guessMonth = index.month + c.firstMonthInThisYear - c.numberOfMonthsInThisYear; - } else { - guessMonth = index.month + c.firstMonthInThisYear; - } - if (lastCal && lastCal.year !== c.year) { - // Year has changed in some transitions in Thai Calendar, this will change the first month, and last month indices of the year. - guessMonth = Math.max(Math.min(lastCal.month, c.numberOfMonthsInThisYear), 1); - } - } else { - if (lastCal && lastCal.year !== c.year) { - // Year has changed in some transitions in Thai Calendar, this will change the first month, and last month indices of the year. - guessMonth = Math.max(Math.min(lastCal.month, c.firstMonthInThisYear + c.numberOfMonthsInThisYear - 1), c.firstMonthInThisYear); - } else { - guessMonth = Math.max(Math.min(index.month + c.firstMonthInThisYear, c.firstMonthInThisYear + c.numberOfMonthsInThisYear - 1), c.firstMonthInThisYear); - } - } - c.month = guessMonth; - - var guessDay = Math.max(Math.min(index.date + c.firstDayInThisMonth, c.firstDayInThisMonth + c.numberOfDaysInThisMonth - 1), c.firstDayInThisMonth); - if (lastCal && (lastCal.year !== c.year || lastCal.month !== c.month)) { - guessDay = Math.max(Math.min(lastCal.day, c.firstDayInThisMonth + c.numberOfDaysInThisMonth - 1), c.firstDayInThisMonth); - } - c.day = c.firstDayInThisMonth; - c.addDays(guessDay - c.firstDayInThisMonth); - return c.getDateTime(); - }, - getIndex: function (date) { - var curDate = clamp(date); - tempCal.setDateTime(curDate); - var cur = { year: tempCal.year, era: tempCal.era }; - - var yearIndex = 0; - - tempCal.setDateTime(startDate); - tempCal.month = 1; - yearIndex = yearDiff(tempCal, cur); - - tempCal.setDateTime(curDate); - var monthIndex = tempCal.month - tempCal.firstMonthInThisYear; - if (monthIndex < 0) { - // A special case is in some ThaiCalendar years first month - // of the year is April, last month is March and month flow is wrap-around - // style; April, March .... November, December, January, February, March. So the first index - // will be 4 and last index will be 3. We are handling the case to convert this wraparound behavior - // into selected index. - monthIndex = tempCal.month - tempCal.firstMonthInThisYear + tempCal.numberOfMonthsInThisYear; - } - var dateIndex = tempCal.day - tempCal.firstDayInThisMonth; - - var index = { - year: yearIndex, - month: monthIndex, - date: dateIndex - }; - - return index; - }, - years: yearSource, - months: monthSource, - dates: dateSource - }; - - }, - - _getInformationJS: function (startDate, endDate) { - var minYear = startDate.getFullYear(); - var maxYear = endDate.getFullYear(); - var yearSource = { - getLength: function () { return Math.max(0, maxYear - minYear + 1); }, - getValue: function (index) { return minYear + index; } - }; - - var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; - var monthSource = function (yearIndex) { - return { - getLength: function () { return months.length; }, - getValue: function (index) { return months[index]; }, - getMonthNumber: function (index) { return Math.min(index, months.length - 1); } - }; - }; - - var dateSource = function (yearIndex, monthIndex) { - var temp = new Date(); - var year = yearSource.getValue(yearIndex); - // The +1 is needed to make using a day of 0 work correctly - var month = monthIndex + 1; // index is always correct, unlike getMonth which changes when the date is invalid - temp.setFullYear(year, month, 0); - - var maxValue = temp.getDate(); - - return { - getLength: function () { return maxValue; }, - getValue: function (index) { return "" + (index + 1); }, - getDateNumber: function (index) { return Math.min(index + 1, maxValue); } - }; - }; - - return { - order: ["month", "date", "year"], - - getDate: function (index) { - return new Date( - yearSource.getValue(index.year), - monthSource(index.year).getMonthNumber(index.month), - dateSource(index.year, index.month).getDateNumber(index.date), - 12, 0 - ); - }, - getIndex: function (date) { - var yearIndex = 0; - var year = date.getFullYear(); - if (year < minYear) { - yearIndex = 0; - } - else if (year > this.maxYear) { - yearIndex = yearSource.getLength() - 1; - } - else { - yearIndex = date.getFullYear() - minYear; - } - - var monthIndex = Math.min(date.getMonth(), monthSource(yearIndex).getLength()); - - var dateIndex = Math.min(date.getDate() - 1, dateSource(yearIndex, monthIndex).getLength()); - - return { - year: yearIndex, - month: monthIndex, - date: dateIndex - }; - }, - years: yearSource, - months: monthSource, - dates: dateSource - }; - } - }); - if (WinJS.Utilities.hasWinRT) { - DatePicker.getInformation = DatePicker._getInformationWinRT; - } - else { - DatePicker.getInformation = DatePicker._getInformationJS; - } - WinJS.Class.mix(DatePicker, WinJS.Utilities.createEventProperties("change")); - WinJS.Class.mix(DatePicker, WinJS.UI.DOMEventMixin); - return DatePicker; - }) - }); - - -})(WinJS); - - -(function timePickerInit(WinJS, undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// Allows users to select time values. - /// - /// - /// Time Picker - /// - /// - /// ]]> - /// Occurs when the time changes. - /// - /// - /// - TimePicker: WinJS.Namespace._lazy(function () { - // Constants definition - var DEFAULT_MINUTE_PATTERN = "{minute.integer(2)}", - DEFAULT_HOUR_PATTERN = "{hour.integer(1)}", - DEFAULT_PERIOD_PATTERN = "{period.abbreviated(2)}"; - - var strings = { - get ariaLabel() { return WinJS.Resources._getWinJSString("ui/timePicker").value; }, - get selectHour() { return WinJS.Resources._getWinJSString("ui/selectHour").value; }, - get selectMinute() { return WinJS.Resources._getWinJSString("ui/selectMinute").value; }, - get selectAMPM() { return WinJS.Resources._getWinJSString("ui/selectAMPM").value; }, - }; - - // date1 and date2 must be Date objects with their date portions set to the - // sentinel date. - var areTimesEqual = function (date1, date2) { - return date1.getHours() === date2.getHours() && - date1.getMinutes() === date2.getMinutes(); - }; - - var TimePicker = WinJS.Class.define(function TimePicker_ctor(element, options) { - /// - /// Initializes a new instance of the TimePicker control - /// - /// The DOM element associated with the TimePicker control. - /// - /// - /// The set of options to be applied initially to the TimePicker control. - /// - /// A constructed TimePicker control. - /// - /// - - // Default to current time - this._currentTime = WinJS.UI.TimePicker._sentinelDate(); - - element = element || document.createElement("div"); - WinJS.Utilities.addClass(element, "win-disposable"); - element.winControl = this; - - var label = element.getAttribute("aria-label"); - if (!label) { - element.setAttribute("aria-label", strings.ariaLabel); - } - - this._timePatterns = { - minute: null, - hour: null, - period: null - }; - - // Options should be set after the element is initialized which is - // the same order of operation as imperatively setting options. - this._init(element); - WinJS.UI.setOptions(this, options); - }, { - _currentTime: null, - _clock: null, - _disabled: false, - _hourElement: null, - _hourControl: null, - _minuteElement: null, - _minuteControl: null, - _ampmElement: null, - _ampmControl: null, - _minuteIncrement: 1, - _timePatterns: { - minute: null, - hour: null, - period: null - }, - _information: null, - - _addAccessibilityAttributes: function () { - //see http://www.w3.org/TR/wai-aria/rdf_model.png for details - this._domElement.setAttribute("role", "group"); - - this._hourElement.setAttribute("aria-label", strings.selectHour); - this._minuteElement.setAttribute("aria-label", strings.selectMinute); - if (this._ampmElement) { - this._ampmElement.setAttribute("aria-label", strings.selectAMPM); - } - }, - - _addControlsInOrder: function (info) { - var that = this; - var u = WinJS.Utilities; - info.order.forEach(function (s, index) { - switch (s) { - case "hour": - that._domElement.appendChild(that._hourElement); - u.addClass(that._hourElement, "win-order" + index); - break; - case "minute": - that._domElement.appendChild(that._minuteElement); - u.addClass(that._minuteElement, "win-order" + index); - break; - case "period": - if (that._ampmElement) { - that._domElement.appendChild(that._ampmElement); - u.addClass(that._ampmElement, "win-order" + index); - } - break; - } - }); - }, - - dispose: function () { - /// - /// - /// Disposes this TimePicker. - /// - /// - /// - }, - - /// - /// Gets or sets the type of clock to display (12HourClock or 24HourClock). It defaults to the user setting. - /// - /// - clock: { - get: function () { - return this._clock; - }, - set: function (value) { - if (this._clock !== value) { - this._clock = value; - this._init(); - } - } - }, - - /// - /// Gets or sets the current date (and time) of the TimePicker. - /// - /// - current: { - get: function () { - var cur = this._currentTime; - if (cur) { - var time = WinJS.UI.TimePicker._sentinelDate(); - time.setHours(cur.getHours()); // accounts for AM/PM - time.setMinutes(this._getMinutesIndex(cur) * this.minuteIncrement); - time.setSeconds(0); - time.setMilliseconds(0); - return time; - } - else { - return cur; - } - }, - set: function (value) { - var that = this; - var newTime; - if (typeof (value) === "string") { - newTime = WinJS.UI.TimePicker._sentinelDate(); - newTime.setTime(Date.parse(newTime.toDateString() + " " + value)); - } - else { - newTime = WinJS.UI.TimePicker._sentinelDate(); - newTime.setHours(value.getHours()); - newTime.setMinutes(value.getMinutes()); - } - - var oldTime = this._currentTime; - if (!areTimesEqual(oldTime, newTime)) { - this._currentTime = newTime; - - this._updateDisplay(); - } - } - }, - - /// - /// Specifies whether the TimePicker is disabled. - /// - /// - disabled: { - get: function () { return this._disabled; }, - set: function (value) { - if (this._disabled !== value) { - this._disabled = value; - if (this._hourControl) { - this._hourControl.setDisabled(value); - this._minuteControl.setDisabled(value); - } - if (this._ampmControl) { - this._ampmControl.setDisabled(value); - } - } - } - }, - - /// - element: { - get: function () { return this._domElement; } - }, - - - _init: function (element) { - this._setElement(element); - this._updateDisplay(); - }, - - /// - /// Gets or sets the display pattern for the hour. - /// - /// - hourPattern: { - get: function () { return this._timePatterns.hour.pattern; }, - set: function (value) { - if (this._timePatterns.hour !== value) { - this._timePatterns.hour = value; - this._init(); - } - } - - }, - - _getHoursAmpm: function (time) { - var hours24 = time.getHours(); - if (this._ampmElement) { - if (hours24 === 0) { - return { hours: 12, ampm: 0 }; - } - else if (hours24 < 12) { - return { hours: hours24, ampm: 0 }; - } - return { hours: hours24 - 12, ampm: 1 }; - } - - return { hours: hours24 }; - }, - - _getHoursIndex: function (hours) { - if (this._ampmElement && hours === 12) { - return 0; - } - return hours; - }, - - _getMinutesIndex: function (time) { - return parseInt(time.getMinutes() / this.minuteIncrement); - }, - - /// - /// Gets or sets the minute increment. For example, "15" specifies that the TimePicker minute control should display only the choices 00, 15, 30, 45. - /// - /// - minuteIncrement: { - //prevent divide by 0, and leave user's input intact - get: function () { return Math.max(1, Math.abs(this._minuteIncrement | 0) % 60); }, - set: function (value) { - if (this._minuteIncrement != value) { - this._minuteIncrement = value; - this._init(); - } - } - - }, - - /// - /// Gets or sets the display pattern for the minute. - /// - /// - minutePattern: { - get: function () { return this._timePatterns.minute.pattern; }, - set: function (value) { - if (this._timePatterns.minute !== value) { - this._timePatterns.minute = value; - this._init(); - } - } - }, - - /// - /// Gets or sets the display pattern for the period. - /// - /// - periodPattern: { - get: function () { return this._timePatterns.period.pattern; }, - set: function (value) { - - if (this._timePatterns.period !== value) { - this._timePatterns.period = value; - this._init(); - } - } - }, - - _setElement: function (element) { - this._domElement = this._domElement || element; - if (!this._domElement) { return; } - - var info = WinJS.UI.TimePicker.getInformation(this.clock, this.minuteIncrement, this._timePatterns); - this._information = info; - - if (info.forceLanguage) { - this._domElement.setAttribute("lang", info.forceLanguage); - this._domElement.setAttribute("dir", info.isRTL ? "rtl" : "ltr"); - } - - WinJS.Utilities.empty(this._domElement); - WinJS.Utilities.addClass(this._domElement, "win-timepicker"); - - this._hourElement = document.createElement("select"); - WinJS.Utilities.addClass(this._hourElement, "win-timepicker-hour"); - - this._minuteElement = document.createElement("select"); - WinJS.Utilities.addClass(this._minuteElement, "win-timepicker-minute"); - - this._ampmElement = null; - if (info.clock === "12HourClock") { - this._ampmElement = document.createElement("select"); - WinJS.Utilities.addClass(this._ampmElement, "win-timepicker-period"); - } - - this._addControlsInOrder(info); - - var that = this; - - var hoursAmpm = this._getHoursAmpm(this.current); - this._hourControl = new WinJS.UI._Select(this._hourElement, { - dataSource: this._getInfoHours(), - disabled: this.disabled, - index: this._getHoursIndex(hoursAmpm.hours) - }); - this._minuteControl = new WinJS.UI._Select(this._minuteElement, { - dataSource: info.minutes, - disabled: this.disabled, - index: this._getMinutesIndex(this.current) - }); - this._ampmControl = null; - if (this._ampmElement) { - this._ampmControl = new WinJS.UI._Select(this._ampmElement, { - dataSource: info.periods, - disabled: this.disabled, - index: hoursAmpm.ampm - }); - } - - this._wireupEvents(); - this._updateValues(); - this._addAccessibilityAttributes(); - }, - - _getInfoHours: function () { - return this._information.hours; - }, - - _updateLayout: function () { - if (!this._domElement) - return; - this._updateValues(); - }, - - _updateValues: function () { - if (this._hourControl) { - var hoursAmpm = this._getHoursAmpm(this.current); - if (this._ampmControl) { - this._ampmControl.index = hoursAmpm.ampm; - } - this._hourControl.index = this._getHoursIndex(hoursAmpm.hours); - this._minuteControl.index = this._getMinutesIndex(this.current); - } - }, - - _updateDisplay: function () { - //Render display index based on constraints (minuteIncrement) - //Will not modify current time - - var hoursAmpm = this._getHoursAmpm(this.current); - - if (this._ampmControl) { - this._ampmControl.index = hoursAmpm.ampm; - } - - if (this._hourControl) { - this._hourControl.index = this._getHoursIndex(hoursAmpm.hours); - this._minuteControl.index = this._getMinutesIndex(this.current); - } - }, - - _wireupEvents: function () { - var that = this; - - var fixupHour = function () { - var hour = that._hourControl.index; - if (that._ampmElement) { - if (that._ampmControl.index === 1) { - if (hour !== 12) { - hour += 12; - } - } - } - return hour; - }; - - var changed = function () { - var hour = fixupHour(); - that._currentTime.setHours(hour); - - that._currentTime.setMinutes(that._minuteControl.index * that.minuteIncrement); - }; - - this._hourElement.addEventListener("change", changed, false); - this._minuteElement.addEventListener("change", changed, false); - if (this._ampmElement) { - this._ampmElement.addEventListener("change", changed, false); - } - } - }, { - _sentinelDate: function () { - // This is July 15th, 2011 as our sentinel date. There are no known - // daylight savings transitions that happened on that date. - var current = new Date(); - return new Date(2011, 6, 15, current.getHours(), current.getMinutes()); - }, - _getInformationWinRT: function (clock, minuteIncrement, timePatterns) { - var newFormatter = function (pattern, defaultPattern) { - var dtf = Windows.Globalization.DateTimeFormatting; - pattern = !pattern ? defaultPattern : pattern; - var formatter = new dtf.DateTimeFormatter(pattern); - if (clock) { - formatter = dtf.DateTimeFormatter(pattern, formatter.languages, formatter.geographicRegion, formatter.calendar, clock); - } - return formatter; - } - - var glob = Windows.Globalization; - var calendar = new glob.Calendar(); - if (clock) { - calendar = new glob.Calendar(calendar.languages, calendar.getCalendarSystem(), clock); - } - calendar.setDateTime(WinJS.UI.TimePicker._sentinelDate()); - - var computedClock = calendar.getClock(); - var numberOfHours = 24; - numberOfHours = calendar.numberOfHoursInThisPeriod; - - var periods = (function () { - var periodFormatter = newFormatter(timePatterns.period, DEFAULT_PERIOD_PATTERN); - return { - getLength: function () { return 2; }, - getValue: function (index) { - var date = WinJS.UI.TimePicker._sentinelDate(); - if (index == 0) { - date.setHours(1); - var am = periodFormatter.format(date); - return am; - } - if (index == 1) { - date.setHours(13); - var pm = periodFormatter.format(date); - return pm; - } - return null; - } - }; - })(); - - // Determine minute format from the DateTimeFormatter - var minutes = (function (index) { - var minuteFormatter = newFormatter(timePatterns.minute, DEFAULT_MINUTE_PATTERN); - var now = WinJS.UI.TimePicker._sentinelDate(); - return { - getLength: function () { return 60 / minuteIncrement; }, - getValue: function (index) { - var display = index * minuteIncrement; - now.setMinutes(display); - return minuteFormatter.format(now); - } - }; - })(); - - - // Determine hour format from the DateTimeFormatter - var hours = (function (index) { - var hourFormatter = newFormatter(timePatterns.hour, DEFAULT_HOUR_PATTERN); - var now = WinJS.UI.TimePicker._sentinelDate(); - return { - getLength: function () { return numberOfHours }, - getValue: function (index) { - now.setHours(index); - return hourFormatter.format(now); - } - } - })(); - - // Determine the order of the items from the DateTimeFormatter. - // "hour minute" also returns the period (if needed). - // - var hourMinuteFormatter = newFormatter("hour minute"); - var pattern = hourMinuteFormatter.patterns[0]; - var order = ["hour", "minute"]; - - var indexes = { - period: pattern.indexOf("{period"), - hour: pattern.indexOf("{hour"), - minute: pattern.indexOf("{minute") - }; - if (indexes.period > -1) { - order.push("period"); - } - - - var DateTimeFormatter = Windows.Globalization.DateTimeFormatting.DateTimeFormatter; - var dtf = new DateTimeFormatter("month.full", Windows.Globalization.ApplicationLanguages.languages, "ZZ", "GregorianCalendar", "24HourClock"); - var pat = dtf.patterns[0]; - var isRTL = pat.charCodeAt(0) === 8207; - - if (isRTL) { - var temp = indexes.hour; - indexes.hour = indexes.minute; - indexes.minute = temp; - } - - order.sort(function (a, b) { - if (indexes[a] < indexes[b]) { return -1; } - else if (indexes[a] > indexes[b]) { return 1; } - else { return 0; } - }); - - return { minutes: minutes, hours: hours, clock: computedClock, periods: periods, order: order, forceLanguage: hourMinuteFormatter.resolvedLanguage, isRTL: isRTL }; - }, - _getInformationJS: function (clock, minuteIncrement) { - var hours = [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; - - var minutes = new Object(); - minutes.getLength = function () { return 60 / minuteIncrement; } - minutes.getValue = function (index) { - var display = index * minuteIncrement; - if (display < 10) { - return "0" + display.toString(); - } - else { - return display.toString(); - } - }; - - var order = ["hour", "minute", "period"]; - if (clock === "24HourClock") { - hours = ["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]; - order = ["hour", "minute"]; - } - return { minutes: minutes, hours: hours, clock: clock || "12HourClock", periods: ["AM", "PM"], order: order }; - } - }); - if (WinJS.Utilities.hasWinRT) { - TimePicker.getInformation = TimePicker._getInformationWinRT; - } - else { - TimePicker.getInformation = TimePicker._getInformationJS; - } - WinJS.Class.mix(TimePicker, WinJS.Utilities.createEventProperties("change")); - WinJS.Class.mix(TimePicker, WinJS.UI.DOMEventMixin); - return TimePicker; - }) - }); - - -})(WinJS); - -(function selectInit(WinJS, undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - _Select: WinJS.Namespace._lazy(function () { - var encodeHtmlRegEx = /[&<>'"]/g; - var encodeHtmlEscapeMap = { - "&": "&", - "<": "<", - ">": ">", - "'": "'", - '"': """ - }; - var stringDirectionRegEx = /[\u200e\u200f]/g; - function encodeHtml(str) { - return str.replace(encodeHtmlRegEx, function (m) { - return encodeHtmlEscapeMap[m] || ""; - }); - }; - function stripDirectionMarker(str) { - return str.replace(stringDirectionRegEx, ""); - } - function stockGetValue(index) { return this[index]; } - function stockGetLength() { return this.length; } - function fixDataSource(dataSource) { - if (!dataSource.getValue) { - dataSource.getValue = stockGetValue - } - - if (!dataSource.getLength) { - dataSource.getLength = stockGetLength - } - return dataSource; - } - - return WinJS.Class.define(function _Select_ctor(element, options) { - // This is an implementation detail of the TimePicker and DatePicker, designed - // to provide a primitive "data bound" select control. This is not designed to - // be used outside of the TimePicker and DatePicker controls. - // - - this._dataSource = fixDataSource(options.dataSource); - this._index = options.index || 0; - - this._domElement = element; - // Mark this as a tab stop - this._domElement.tabIndex = 0; - - if (options.disabled) { - this.setDisabled(options.disabled); - } - - var that = this; - this._domElement.addEventListener("change", function (e) { - //Should be set to _index to prevent events from firing twice - that._index = that._domElement.selectedIndex; - }, false); - - //update runtime accessibility value after initialization - this._createSelectElement(); - }, { - _index: 0, - _dataSource: null, - - dataSource: { - get: function () { return this._dataSource; }, - set: function (value) { - this._dataSource = fixDataSource(value); - - //Update layout as data source change - if (this._domElement) { - this._createSelectElement(); - } - } - }, - - setDisabled: function (disabled) { - if (disabled) { - this._domElement.setAttribute("disabled", "disabled"); - } - else { - this._domElement.removeAttribute("disabled"); - } - }, - - _createSelectElement: function () { - var dataSourceLength = this._dataSource.getLength(); - var text = ""; - for (var i = 0; i < dataSourceLength; i++) { - var value = "" + this._dataSource.getValue(i); - var escaped = encodeHtml(value); - // WinRT localization often tags the strings with reading direction. We want this - // for display text (escaped), but don't want this in the value space, as it - // only present for display. - // - var stripped = stripDirectionMarker(escaped); - text += ""; - } - WinJS.Utilities.setInnerHTMLUnsafe(this._domElement, text); - this._domElement.selectedIndex = this._index; - }, - - index: { - get: function () { - return Math.max(0, Math.min(this._index, this._dataSource.getLength() - 1)); - }, - set: function (value) { - if (this._index !== value) { - this._index = value; - - var d = this._domElement; - if (d && d.selectedIndex !== value) { - d.selectedIndex = value; - } - } - } - }, - - value: { - get: function () { - return this._dataSource.getValue(this.index); - } - } - }); - }) - }) -})(WinJS); - -// Back Button -(function backButtonInit(WinJS) { - "use strict"; - - var nav = WinJS.Navigation; - - // Class Names - var navigationBackButtonClass = 'win-navigation-backbutton'; - var glyphClass = "win-back"; - - // CONSTANTS - var KEY_LEFT = "Left"; - var KEY_BROWSER_BACK = "BrowserBack"; - var MOUSE_BACK_BUTTON = 3; - - // Create Singleton for global event registering/unregistering. This Singleton should only be created once. - // Here the function 'returnBackButtonSingelton' is called immediateley and its result is the singleton object. - var singleton = (function createBackButtonSingleton() { - - /* Step 1: Build JavaScript closure */ - - function hookUpBackButtonGlobalEventHandlers() { - // Subscribes to global events on the window object - window.addEventListener('keyup', backButtonGlobalKeyUpHandler, false) - window.addEventListener('pointerup', backButtonGlobalMSPointerUpHandler, false); - } - - function unHookBackButtonGlobalEventHandlers() { - // Unsubscribes from global events on the window object - window.removeEventListener('keyup', backButtonGlobalKeyUpHandler, false) - window.removeEventListener('pointerup', backButtonGlobalMSPointerUpHandler, false); - } - - function backButtonGlobalKeyUpHandler(event) { - // Navigates back when (alt + left) or BrowserBack keys are released. - if ((event.key === KEY_LEFT && event.altKey && !event.shiftKey && !event.ctrlKey) || (event.key === KEY_BROWSER_BACK)) { - nav.back(); - } - } - - function backButtonGlobalMSPointerUpHandler(event) { - // Responds to clicks to enable navigation using 'back' mouse buttons. - if (event.button === MOUSE_BACK_BUTTON) { - nav.back(); - } - } - - // Singleton reference count for registering and unregistering global event handlers. - var backButtonReferenceCount = 0; // - - /* Step 2: Return Singleton object literal */ - return { - addRef: function () { - if (backButtonReferenceCount === 0) { - hookUpBackButtonGlobalEventHandlers(); - } - backButtonReferenceCount++; - }, - release: function () { - if (backButtonReferenceCount > 0) { // Ensure count won't become negative. - backButtonReferenceCount--; - if (backButtonReferenceCount === 0) { - unHookBackButtonGlobalEventHandlers(); - } - } - }, - getCount: function () { // Return the value of the reference count. Useful for unit testing. - return backButtonReferenceCount; - } - }; - }()); // Immediate invoke creates and returns the Singleton - - WinJS.Namespace.define("WinJS.UI", { - /// - /// - /// Provides backwards navigation functionality. - /// - /// - /// - /// - /// - /// ]]> - /// The BackButton control itself - /// The Back Arrow glyph - /// - /// - /// - BackButton: WinJS.Namespace._lazy(function () { - // Statics - var strings = { - get ariaLabel() { return WinJS.Resources._getWinJSString("ui/backbuttonarialabel").value; }, - get duplicateConstruction() { return WinJS.Resources._getWinJSString("ui/duplicateConstruction").value; }, - get badButtonElement() { return WinJS.Resources._getWinJSString("ui/badButtonElement").value; } - }; - - var BackButton = WinJS.Class.define(function BackButton_ctor(element, options) { - /// - /// - /// Creates a new BackButton control - /// - /// - /// The DOM element that will host the control. If this parameter is null, this constructor creates one for you. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. Each property of the options object corresponds to - /// one of the control's properties or events. - /// - /// - /// A BackButton control. - /// - /// - /// - - // Check to make sure we weren't duplicated - if (element && element.winControl) { - throw new WinJS.ErrorFromName("WinJS.UI.BackButton.DuplicateConstruction", strings.duplicateConstruction); - } - - this._element = element || document.createElement("button"); - options = options || {}; - - this._initializeButton(); // This will also set the aria-label and tooltip - - this._disposed = false; - - // Remember ourselves - this._element.winControl = this; - - WinJS.UI.setOptions(this, options); - - // Add event handlers for this back button instance - this._buttonClickHandler = this._handleBackButtonClick.bind(this); - this._element.addEventListener('click', this._buttonClickHandler, false); - this._navigatedHandler = this._handleNavigatedEvent.bind(this); - nav.addEventListener('navigated', this._navigatedHandler, false); - - // Increment reference count / manage add global event handlers - singleton.addRef(); - }, { - - /// - element: { - get: function () { - return this._element; - } - }, - - dispose: function () { - /// - /// - /// Disposes this control. - /// - /// - /// - if (this._disposed) { - return; - } - this._disposed = true; // Mark this control as disposed. - - // Remove 'navigated' eventhandler for this BackButton - nav.removeEventListener('navigated', this._navigatedHandler, false); - - singleton.release(); // Decrement reference count. - - }, - - refresh: function () { - /// - /// - /// Sets the 'disabled' attribute to correct the value based on the current navigation history stack. - /// - /// - /// - if (nav.canGoBack) { - this._element.disabled = false; - } else { - this._element.disabled = true; - } - }, - - _initializeButton: function () { - //Final EN-US HTML should be: - // - //Button will automatically be disabled if WinJS.Navigation.history.canGoBack is false. - - // Verify the HTML is a button - if (this._element.tagName !== "BUTTON") { - throw new WinJS.ErrorFromName("WinJS.UI.BackButton.BadButtonElement", strings.badButtonElement); - } - - // Attach our css classes - WinJS.Utilities.addClass(this._element, navigationBackButtonClass); - - // Attach disposable class. - WinJS.Utilities.addClass(this._element, "win-disposable"); - - // Create inner glyph element - this._element.innerHTML = ''; - - // Set the 'disabled' property to the correct value based on the current navigation history stack. - this.refresh(); - - // Set Aria-label and native tooltip to the same localized string equivalent of "Back" - this._element.setAttribute("aria-label", strings.ariaLabel); - this._element.setAttribute("title", strings.ariaLabel); - - // Explicitly set type attribute to avoid the default '; - this._headerTabStopElement = this._headerElement.firstElementChild; - this._headerContentElement = this._headerTabStopElement.firstElementChild; - this._headerChevronElement = this._headerTabStopElement.lastElementChild; - element.appendChild(this._headerElement); - - this._winKeyboard = new WinJS.UI._WinKeyboard(this._headerElement); - - this._contentElement = document.createElement("DIV"); - this._contentElement.className = WinJS.UI.HubSection._ClassName.hubSectionContent; - this._contentElement.style.visibility = "hidden"; - element.appendChild(this._contentElement); - - // Reparent any existing elements inside the new hub section content element. - var elementToMove = this.element.firstChild; - while (elementToMove !== this._headerElement) { - var nextElement = elementToMove.nextSibling; - this._contentElement.appendChild(elementToMove); - elementToMove = nextElement; - } - - this._processors = [WinJS.UI.processAll]; - - WinJS.UI.setOptions(this, options); - }, { - /// - element: { - get: function () { - return this._element; - } - }, - /// - /// Gets or sets a value that specifies whether the header is static. Set this value to true to disable clicks and other interactions. - /// - /// - isHeaderStatic: { - get: function () { - return this._isHeaderStatic; - }, - set: function (value) { - this._isHeaderStatic = value; - if (!this._isHeaderStatic) { - this._headerTabStopElement.setAttribute("role", "link"); - WinJS.Utilities.addClass(this._headerTabStopElement, WinJS.UI.HubSection._ClassName.hubSectionInteractive); - } else { - this._headerTabStopElement.setAttribute("role", "heading"); - WinJS.Utilities.removeClass(this._headerTabStopElement, WinJS.UI.HubSection._ClassName.hubSectionInteractive); - } - } - }, - /// - /// Gets the DOM element that hosts the HubSection's content. - /// - /// - contentElement: { - get: function () { - return this._contentElement; - } - }, - /// - /// Get or set the HubSection's header. After you set this property, the Hub renders the header again. - /// - /// - header: { - get: function () { - return this._header; - }, - set: function (value) { - // Render again even if it is equal to itself. - this._header = value; - this._renderHeader(); - } - }, - _setHeaderTemplate: function HubSection_setHeaderTemplate(template) { - this._template = WinJS.Utilities._syncRenderer(template); - this._renderHeader(); - }, - _renderHeader: function HubSection_renderHeader() { - if (this._template) { - WinJS.Utilities._disposeElement(this._headerContentElement); - WinJS.Utilities.empty(this._headerContentElement); - this._template(this, this._headerContentElement); - } - }, - _process: function HubSection_process() { - var that = this; - - this._processed = (this._processors || []).reduce(function (promise, processor) { - return promise.then(function () { - return processor(that.contentElement); - }); - }, this._processed || WinJS.Promise.as()); - this._processors = null; - - return this._processed; - }, - dispose: function HubSection_dispose() { - /// - /// - /// Disposes this control. - /// - /// - /// - if (this._disposed) { - return; - } - this._disposed = true; - this._processors = null; - - WinJS.Utilities._disposeElement(this._headerContentElement); - WinJS.Utilities.disposeSubTree(this.contentElement); - } - }, { - // Names of classes used by the HubSection. - _ClassName: { - hubSection: "win-hub-section", - hubSectionHeader: "win-hub-section-header", - hubSectionHeaderTabStop: "win-hub-section-header-tabstop", - hubSectionInteractive: "win-hub-section-header-interactive", - hubSectionHeaderContent: "win-hub-section-header-content", - hubSectionHeaderChevron: "win-hub-section-header-chevron", - hubSectionContent: "win-hub-section-content" - }, - _Constants: { - ellipsisTypeClassName: "win-type-ellipsis", - xLargeTypeClassName: "win-type-x-large" - }, - isDeclarativeControlContainer: WinJS.Utilities.markSupportedForProcessing(function (section, callback) { - if (callback === WinJS.UI.processAll) { - return; - } - - section._processors = section._processors || []; - section._processors.push(callback); - - // Once processed the first time synchronously queue up new processors as they come in - if (section._processed) { - section._process(); - } - }) - }); - }) - }); - -})(this, WinJS); - -/// animatable,appbar,appbars,divs,Flyout,Flyouts,iframe,Statics,unfocus,unselectable -(function overlayInit(WinJS) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - _Overlay: WinJS.Namespace._lazy(function () { - var thisWinUI = WinJS.UI; - var utilities = WinJS.Utilities; - var createEvent = utilities._createEventProperty; - - // Class Names - var overlayClass = "win-overlay"; - var hideFocusClass = "win-hidefocus"; // Prevents the element from showing a focus rect - - // Event Names - var BEFORESHOW = "beforeshow"; - var AFTERSHOW = "aftershow"; - var BEFOREHIDE = "beforehide"; - var AFTERHIDE = "afterhide"; - - // Helper to get DOM elements from input single object or array or IDs/toolkit/dom elements - function _resolveElements(elements) { - // No input is just an empty array - if (!elements) { - return []; - } - - // Make sure it's in array form. - if (typeof elements === "string" || !elements || !elements.length) { - elements = [elements]; - } - - // Make sure we have a DOM element for each one, (could be string id name or toolkit object) - var i, - realElements = []; - for (i = 0; i < elements.length; i++) { - if (elements[i]) { - if (typeof elements[i] === "string") { - var element = document.getElementById(elements[i]); - if (element) { - realElements.push(element); - } - } else if (elements[i].element) { - realElements.push(elements[i].element); - } else { - realElements.push(elements[i]); - } - } - } - - return realElements; - } - - // Helpers for keyboard showing related events - function _allOverlaysCallback(event, command) { - var elements = document.querySelectorAll("." + overlayClass); - if (elements) { - var len = elements.length; - for (var i = 0; i < len; i++) { - var element = elements[i]; - var control = element.winControl; - if (!control._disposed) { - if (control) { - control[command](event); - } - } - } - } - } - - function _edgyMayHideFlyouts() { - if (!_Overlay._rightMouseMightEdgy) { - _Overlay._hideAllFlyouts(); - } - } - - var _Overlay = WinJS.Class.define(function _Overlay_ctor(element, options) { - /// - /// - /// Constructs the Overlay control and associates it with the underlying DOM element. - /// - /// - /// The DOM element to be associated with the Overlay control. - /// - /// - /// The set of options to be applied initially to the Overlay control. - /// - /// A fully constructed Overlay control. - /// - this._baseOverlayConstructor(element, options); - }, { - // Functions/properties - _baseOverlayConstructor: function _Overlay_baseOverlayConstructor(element, options) { - this._disposed = false; - - // Make sure there's an input element - if (!element) { - element = document.createElement("div"); - } - - // Check to make sure we weren't duplicated - var overlay = element.winControl; - if (overlay) { - throw new WinJS.ErrorFromName("WinJS.UI._Overlay.DuplicateConstruction", strings.duplicateConstruction); - } - - if (!this._element) { - this._element = element; - } - this._sticky = false; - this._doNext = ""; - - this._element.style.visibility = "hidden"; - this._element.style.opacity = 0; - - // Remember ourselves - element.winControl = this; - - // Attach our css class - WinJS.Utilities.addClass(this._element, overlayClass); - WinJS.Utilities.addClass(this._element, "win-disposable"); - - // We don't want to be selectable, set UNSELECTABLE - var unselectable = this._element.getAttribute("unselectable"); - if (unselectable === null || unselectable === undefined) { - this._element.setAttribute("unselectable", "on"); - } - - // Base animation is popIn/popOut - this._currentAnimateIn = this._baseAnimateIn; - this._currentAnimateOut = this._baseAnimateOut; - this._animationPromise = WinJS.Promise.as(); - - // Command Animations to Queue - this._queuedToShow = []; - this._queuedToHide = []; - this._queuedCommandAnimation = false; - - if (options) { - WinJS.UI.setOptions(this, options); - } - }, - - /// - element: { - get: function () { - return this._element; - } - }, - - /// Disable an Overlay, setting or getting the HTML disabled attribute. When disabled the Overlay will no longer display with show(), and will hide if currently visible. - disabled: { - get: function () { - // Ensure it's a boolean because we're using the DOM element to keep in-sync - return !!this._element.disabled; - }, - set: function (value) { - // Force this check into a boolean because our current state could be a bit confused since we tie to the DOM element - value = !!value; - var oldValue = !!this._element.disabled; - if (oldValue !== value) { - this._element.disabled = value; - if (!this.hidden && this._element.disabled) { - this._hideOrDismiss(); - } - } - } - }, - - /// - /// Occurs immediately before the control is shown. - /// - onbeforeshow: createEvent(BEFORESHOW), - - /// - /// Occurs immediately after the control is shown. - /// - onaftershow: createEvent(AFTERSHOW), - - /// - /// Occurs immediately before the control is hidden. - /// - onbeforehide: createEvent(BEFOREHIDE), - - /// - /// Occurs immediately after the control is hidden. - /// - onafterhide: createEvent(AFTERHIDE), - - dispose: function () { - /// - /// - /// Disposes this Overlay. - /// - /// - if (this._disposed) { - return; - } - - this._disposed = true; - this._dispose(); - }, - - _dispose: function _Overlay_dispose() { - // To be overridden by subclasses - }, - - show: function () { - /// - /// - /// Shows the Overlay, if hidden, regardless of other state - /// - /// - // call private show to distinguish it from public version - this._show(); - }, - - _show: function _Overlay_show() { - // We call our base _baseShow because AppBar may need to override show - this._baseShow(); - }, - - hide: function () { - /// - /// - /// Hides the Overlay, if visible, regardless of other state - /// - /// - // call private hide to distinguish it from public version - this._hide(); - }, - - _hide: function _Overlay_hide() { - // We call our base _baseHide because AppBar may need to override hide - this._baseHide(); - }, - - // Is the overlay "hidden"? - /// - hidden: { - get: function () { - return (this._element.style.visibility === "hidden" || - this._element.winAnimating === "hiding" || - this._doNext === "hide" || - this._fakeHide); - } - }, - - addEventListener: function (type, listener, useCapture) { - /// - /// - /// Add an event listener to the DOM element for this Overlay - /// - /// Required. Event type to add, "beforehide", "afterhide", "beforeshow", or "aftershow" - /// Required. The event handler function to associate with this event. - /// Optional. True, register for the event capturing phase. False for the event bubbling phase. - /// - return this._element.addEventListener(type, listener, useCapture); - }, - - removeEventListener: function (type, listener, useCapture) { - /// - /// - /// Remove an event listener to the DOM element for this Overlay - /// - /// Required. Event type to remove, "beforehide", "afterhide", "beforeshow", or "aftershow" - /// Required. The event handler function to associate with this event. - /// Optional. True, register for the event capturing phase. False for the event bubbling phase. - /// - return this._element.removeEventListener(type, listener, useCapture); - }, - - _baseShow: function _Overlay_baseShow() { - // If we are already animating, just remember this for later - if (this._animating || this._keyboardShowing || this._keyboardHiding) { - this._doNext = "show"; - return false; - } - - // Each overlay tracks the window width for detecting resizes in the resize handler. - this._currentDocumentWidth = this._currentDocumentWidth || document.documentElement.offsetWidth; - - // "hiding" would need to cancel. - if (this._element.style.visibility !== "visible" || this._fakeHide) { - // Let us know we're showing. - this._element.winAnimating = "showing"; - - // Hiding, but not none - this._element.style.display = ""; - if (!this._fakeHide) { - this._element.style.visibility = "hidden"; - } - - // In case their event is going to manipulate commands, see if there are - // any queued command animations we can handle while we're still hidden. - if (this._queuedCommandAnimation) { - this._showAndHideFast(this._queuedToShow, this._queuedToHide); - this._queuedToShow = []; - this._queuedToHide = []; - } - - // Send our "beforeShow" event - this._sendEvent(_Overlay.beforeShow); - - // Need to measure - this._findPosition(); - - // Make sure it's visible, and fully opaque. - // Do the popup thing, sending event afterward. - var that = this; - this._animationPromise = this._currentAnimateIn(). - then(function () { - that._baseEndShow(); - }, function (err) { - that._baseEndShow(); - }); - this._fakeHide = false; - return true; - } - return false; - }, - - // Flyout in particular will need to measure our positioning. - _findPosition: function _Overlay_findPosition() { - }, - - _baseEndShow: function _Overlay_baseEndShow() { - if (this._disposed) { - return; - } - - // Make sure it's visible after showing - this._element.setAttribute("aria-hidden", "false"); - - this._element.winAnimating = ""; - - // Do our derived classes show stuff - this._endShow(); - - // We're shown now - if (this._doNext === "show") { - this._doNext = ""; - } - - // After showing, send the after showing event - this._sendEvent(_Overlay.afterShow); - this._writeProfilerMark("show,StopTM"); // Overlay writes the stop profiler mark for all of its derived classes. - - // If we had something queued, do that - WinJS.Utilities.Scheduler.schedule(this._checkDoNext, WinJS.Utilities.Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); - - }, - - _endShow: function _Overlay_endShow() { - // Nothing by default - }, - - _baseHide: function _Overlay_baseHide() { - // If we are already animating, just remember this for later - if (this._animating || this._keyboardShowing) { - this._doNext = "hide"; - return false; - } - - // In the unlikely event we're between the hiding keyboard and the resize events, just snap it away: - if (this._keyboardHiding) { - // use the "uninitialized" flag - this._element.style.visibility = ""; - } - - // "showing" would need to queue up. - if (this._element.style.visibility !== "hidden") { - // Let us know we're hiding, accessibility as well. - this._element.winAnimating = "hiding"; - this._element.setAttribute("aria-hidden", "true"); - - // Send our "beforeHide" event - this._sendEvent(_Overlay.beforeHide); - - // If our visibility is empty, then this is the first time, just hide it - if (this._element.style.visibility === "") { - // Initial hiding, just hide it - this._element.style.opacity = 0; - this._baseEndHide(); - } else { - // Make sure it's hidden, and fully transparent. - var that = this; - this._animationPromise = this._currentAnimateOut(). - then(function () { - that._baseEndHide(); - }, function (err) { - that._baseEndHide(); - }); - } - return true; - } - this._fakeHide = false; - - return false; - }, - - _baseEndHide: function _Overlay_baseEndHide() { - if (this._disposed) { - return; - } - - // Make sure animation is finished. - this._element.style.visibility = "hidden"; - this._element.style.display = "none"; - this._element.winAnimating = ""; - - // In case their event is going to manipulate commands, see if there - // are any queued command animations we can handle now we're hidden. - if (this._queuedCommandAnimation) { - this._showAndHideFast(this._queuedToShow, this._queuedToHide); - this._queuedToShow = []; - this._queuedToHide = []; - } - - // We're hidden now - if (this._doNext === "hide") { - this._doNext = ""; - } - - // After hiding, send our "afterHide" event - this._sendEvent(_Overlay.afterHide); - this._writeProfilerMark("hide,StopTM"); // Overlay writes the stop profiler mark for all of its derived classes. - - - // If we had something queued, do that. This has to be after - // the afterHide event in case it triggers a show() and they - // have something to do in beforeShow that requires afterHide first. - WinJS.Utilities.Scheduler.schedule(this._checkDoNext, WinJS.Utilities.Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); - }, - - _checkDoNext: function _Overlay_checkDoNext() { - // Do nothing if we're still animating - if (this._animating || this._keyboardShowing || this._keyboardHiding || this._disposed) { - return; - } - - if (this._doNext === "hide") { - // Do hide first because animating commands would be easier - this._hide(); - this._doNext = ""; - } else if (this._queuedCommandAnimation) { - // Do queued commands before showing if possible - this._showAndHideQueue(); - } else if (this._doNext === "show") { - // Show last so that we don't unnecessarily animate commands - this._show(); - this._doNext = ""; - } - }, - - // Default animations - _baseAnimateIn: function _Overlay_baseAnimateIn() { - this._element.style.opacity = 0; - this._element.style.visibility = "visible"; - // touch opacity so that IE fades from the 0 we just set to 1 - window.getComputedStyle(this._element, null).opacity; - return WinJS.UI.Animation.fadeIn(this._element); - }, - - _baseAnimateOut: function _Overlay_baseAnimateOut() { - this._element.style.opacity = 1; - // touch opacity so that IE fades from the 1 we just set to 0 - window.getComputedStyle(this._element, null).opacity; - return WinJS.UI.Animation.fadeOut(this._element); - }, - - _animating: { - get: function _Overlay_animating_get() { - // Ensure it's a boolean because we're using the DOM element to keep in-sync - return !!this._element.winAnimating; - } - }, - - // Send one of our events - _sendEvent: function _Overlay_sendEvent(eventName, detail) { - if (this._disposed) { - return; - } - var event = document.createEvent("CustomEvent"); - event.initEvent(eventName, true, true, (detail || {})); - this._element.dispatchEvent(event); - }, - - // Show commands - _showCommands: function _Overlay_showCommands(commands, immediate) { - var showHide = this._resolveCommands(commands); - this._showAndHideCommands(showHide.commands, [], immediate); - }, - - // Hide commands - _hideCommands: function _Overlay_hideCommands(commands, immediate) { - var showHide = this._resolveCommands(commands); - this._showAndHideCommands([], showHide.commands, immediate); - }, - - // Hide commands - _showOnlyCommands: function _Overlay_showOnlyCommands(commands, immediate) { - var showHide = this._resolveCommands(commands); - this._showAndHideCommands(showHide.commands, showHide.others, immediate); - }, - - _showAndHideCommands: function _Overlay_showAndHideCommands(showCommands, hideCommands, immediate) { - // Immediate is "easy" - if (immediate || (this.hidden && !this._animating)) { - // Immediate mode (not animated) - this._showAndHideFast(showCommands, hideCommands); - // Need to remove them from queues, but others could be queued - this._removeFromQueue(showCommands, this._queuedToShow); - this._removeFromQueue(hideCommands, this._queuedToHide); - } else { - - // Queue Commands - this._updateAnimateQueue(showCommands, this._queuedToShow, this._queuedToHide); - this._updateAnimateQueue(hideCommands, this._queuedToHide, this._queuedToShow); - } - }, - - _removeFromQueue: function _Overlay_removeFromQueue(commands, queue) { - // remove commands from queue. - var count; - for (count = 0; count < commands.length; count++) { - // Remove if it was in queue - var countQ; - for (countQ = 0; countQ < queue.length; countQ++) { - if (queue[countQ] === commands[count]) { - queue.splice(countQ, 1); - break; - } - } - } - }, - - _updateAnimateQueue: function _Overlay_updateAnimateQueue(addCommands, toQueue, fromQueue) { - if (this._disposed) { - return; - } - - // Add addCommands to toQueue and remove addCommands from fromQueue. - var count; - for (count = 0; count < addCommands.length; count++) { - // See if it's already in toQueue - var countQ; - for (countQ = 0; countQ < toQueue.length; countQ++) { - if (toQueue[countQ] === addCommands[count]) { - break; - } - } - if (countQ === toQueue.length) { - // Not found, add it - toQueue[countQ] = addCommands[count]; - } - // Remove if it was in fromQueue - for (countQ = 0; countQ < fromQueue.length; countQ++) { - if (fromQueue[countQ] === addCommands[count]) { - fromQueue.splice(countQ, 1); - break; - } - } - } - // If we haven't queued the actual animation - if (!this._queuedCommandAnimation) { - // If not already animating, we'll need to call _checkDoNext - if (!this._animating) { - WinJS.Utilities.Scheduler.schedule(this._checkDoNext, WinJS.Utilities.Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); - } - this._queuedCommandAnimation = true; - } - }, - - // show/hide commands without doing any animation. - _showAndHideFast: function _Overlay_showAndHideFast(showCommands, hideCommands) { - var count; - var command; - for (count = 0; count < showCommands.length; count++) { - command = showCommands[count]; - if (command && command.style) { - command.style.visibility = ""; - command.style.display = ""; - } - } - for (count = 0; count < hideCommands.length; count++) { - command = hideCommands[count]; - if (command && command.style) { - command.style.visibility = "hidden"; - command.style.display = "none"; - } - } - - this._contentChanged(); - - }, - - // show and hide the queued commands, perhaps animating if overlay isn't hidden. - _showAndHideQueue: function _Overlay_showAndHideQueue() { - // Only called if not currently animating. - // We'll be done with the queued stuff when we return. - this._queuedCommandAnimation = false; - - // Shortcut if hidden - if (this.hidden) { - this._showAndHideFast(this._queuedToShow, this._queuedToHide); - // Might be something else to do - WinJS.Utilities.Scheduler.schedule(this._checkDoNext, WinJS.Utilities.Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); - } else { - // Animation has 3 parts: "hiding", "showing", and "moving" - // PVL has "addToList" and "deleteFromList", both of which allow moving parts. - // So we'll set up "add" for showing, and use "delete" for "hiding" + moving, - // then trigger both at the same time. - var showCommands = this._queuedToShow; - var hideCommands = this._queuedToHide; - var siblings = this._findSiblings(showCommands.concat(hideCommands)); - - // Filter out the commands queued for animation that don't need to be animated. - var count; - for (count = 0; count < showCommands.length; count++) { - // If this one's not real or not attached, skip it - if (!showCommands[count] || - !showCommands[count].style || - !document.body.contains(showCommands[count])) { - // Not real, skip it - showCommands.splice(count, 1); - count--; - } else if (showCommands[count].style.visibility !== "hidden" && showCommands[count].style.opacity !== "0") { - // Don't need to animate showing this one, already visible, so now it's a sibling - siblings.push(showCommands[count]); - showCommands.splice(count, 1); - count--; - } - } - for (count = 0; count < hideCommands.length; count++) { - // If this one's not real or not attached, skip it - if (!hideCommands[count] || - !hideCommands[count].style || - !document.body.contains(hideCommands[count]) || - hideCommands[count].style.visibility === "hidden" || - hideCommands[count].style.opacity === "0") { - // Don't need to animate hiding this one, not real, or it's hidden, - // so don't even need it as a sibling. - hideCommands.splice(count, 1); - count--; - } - } - - // Start command animations. - var commandsAnimationPromise = this._baseBeginAnimateCommands(showCommands, hideCommands, siblings); - - // Hook end animations - var that = this; - if (commandsAnimationPromise) { - // Needed to animate - commandsAnimationPromise.done( - function () { that._baseEndAnimateCommands(hideCommands); }, - function () { that._baseEndAnimateCommands(hideCommands); } - ); - } else { - // Already positioned correctly - WinJS.Utilities.Scheduler.schedule(function () { that._baseEndAnimateCommands([]); }, - WinJS.Utilities.Scheduler.Priority.normal, null, - "WinJS.UI._Overlay._endAnimateCommandsWithoutAnimation"); - } - } - - // Done, clear queues - this._queuedToShow = []; - this._queuedToHide = []; - }, - - _baseBeginAnimateCommands: function _Overlay_baseBeginAnimateCommands(showCommands, hideCommands, siblings) { - // The parameters are 3 mutually exclusive arrays of win-command elements contained in this Overlay. - // 1) showCommands[]: All of the HIDDEN win-command elements that ARE scheduled to show. - // 2) hideCommands[]: All of the VISIBLE win-command elements that ARE shceduled to hide. - // 3) siblings[]: i. All VISIBLE win-command elements that ARE NOT scheduled to hide. - // ii. All HIDDEN win-command elements that ARE NOT scheduled to hide OR show. - this._beginAnimateCommands(showCommands, hideCommands, this._getVisibleCommands(siblings)); - - var showAnimated = null, - hideAnimated = null; - - // Hide commands first, with siblings if necessary, - // so that the showing commands don't disrupt the hiding commands position. - if (hideCommands.length > 0) { - hideAnimated = WinJS.UI.Animation.createDeleteFromListAnimation(hideCommands, showCommands.length === 0 ? siblings : undefined); - } - if (showCommands.length > 0) { - showAnimated = WinJS.UI.Animation.createAddToListAnimation(showCommands, siblings); - } - - // Update hiding commands - for (var count = 0, len = hideCommands.length; count < len; count++) { - // Need to fix our position - var rectangle = hideCommands[count].getBoundingClientRect(), - style = window.getComputedStyle(hideCommands[count]); - - // Use the bounding box, adjusting for margins - hideCommands[count].style.top = (rectangle.top - parseFloat(style.marginTop)) + "px"; - hideCommands[count].style.left = (rectangle.left - parseFloat(style.marginLeft)) + "px"; - hideCommands[count].style.opacity = 0; - hideCommands[count].style.position = "fixed"; - } - - // Mark as animating - this._element.winAnimating = "rearranging"; - - // Start hiding animations - // Hide needs extra cleanup when done - var promise = null; - if (hideAnimated) { - promise = hideAnimated.execute(); - } - - // Update showing commands, - // After hiding commands so that the hiding ones fade in the right place. - for (count = 0; count < showCommands.length; count++) { - showCommands[count].style.visibility = ""; - showCommands[count].style.display = ""; - showCommands[count].style.opacity = 1; - } - - // Start showing animations - if (showAnimated) { - var newPromise = showAnimated.execute(); - if (promise) { - promise = WinJS.Promise.join([promise, newPromise]); - } else { - promise = newPromise; - } - } - - return promise; - }, - - _beginAnimateCommands: function _Overlay_beginAnimateCommands(showCommands, hideCommands, siblings) { - // Nothing by default - }, - - _getVisibleCommands: function _Overlay_getVisibleCommands(commandSubSet) { - var command, - commands = commandSubSet, - visibleCommands = []; - - if (!commands) { - // Crawl the inner HTML for the commands. - commands = this.element.querySelectorAll(".win-command"); - } - - for (var i = 0, len = commands.length; i < len; i++) { - command = commands[i].winControl || commands[i]; - if (!command.hidden) { - visibleCommands.push(command); - } - } - - return visibleCommands; - }, - - // Once animation is complete, ensure that the commands are display:none - // and check if there's another animation to start. - _baseEndAnimateCommands: function _Overlay_baseEndAnimateCommands(hideCommands) { - if (this._disposed) { - return; - } - - // Update us - var count; - for (count = 0; count < hideCommands.length; count++) { - // Force us back into our appbar so that we can show again correctly - hideCommands[count].style.position = ""; - hideCommands[count].getBoundingClientRect(); - // Now make us really hidden - hideCommands[count].style.visibility = "hidden"; - hideCommands[count].style.display = "none"; - hideCommands[count].style.opacity = 1; - } - // Done animating - this._element.winAnimating = ""; - - this._endAnimateCommands(); - - // Might be something else to do - this._checkDoNext(); - }, - - _endAnimateCommands: function _Overlay_endAnimateCommands() { - // Nothing by default - }, - - // Resolves our commands - _resolveCommands: function _Overlay_resolveCommands(commands) { - // First make sure they're all DOM elements. - commands = _resolveElements(commands); - - // Now make sure they're all in this container - var result = {}; - result.commands = []; - result.others = []; - var allCommands = this.element.querySelectorAll(".win-command"); - var countAll, countIn; - for (countAll = 0; countAll < allCommands.length; countAll++) { - var found = false; - for (countIn = 0; countIn < commands.length; countIn++) { - if (commands[countIn] === allCommands[countAll]) { - result.commands.push(allCommands[countAll]); - commands.splice(countIn, 1); - found = true; - break; - } - } - if (!found) { - result.others.push(allCommands[countAll]); - } - } - return result; - }, - - // Find siblings, all DOM elements now. - // Returns all .win-commands in this Overlay that are NOT in the passed in 'commands' array. - _findSiblings: function _Overlay_findSiblings(commands) { - // Now make sure they're all in this container - var siblings = []; - var allCommands = this.element.querySelectorAll(".win-command"); - var countAll, countIn; - for (countAll = 0; countAll < allCommands.length; countAll++) { - var found = false; - for (countIn = 0; countIn < commands.length; countIn++) { - if (commands[countIn] === allCommands[countAll]) { - commands.splice(countIn, 1); - found = true; - break; - } - } - if (!found) { - siblings.push(allCommands[countAll]); - } - } - return siblings; - }, - - _baseResize: function _Overlay_baseResize(event) { - // Avoid the cost of a resize if the Overlay is hidden. - if (this._currentDocumentWidth !== undefined) { - if (this._element.style.visibility === "hidden") { - this._currentDocumentWidth = undefined; - } else { - // Overlays can light dismiss on horizontal resize. - var newWidth = document.documentElement.offsetWidth; - if (this._currentDocumentWidth !== newWidth) { - this._currentDocumentWidth = newWidth - if (!this._sticky) { - this._hideOrDismiss(); - } - } - } - } - - // Call specific resize - this._resize(event); - }, - - _hideOrDismiss: function _Overlay_hideOrDismiss() { - var element = this._element; - if (element && WinJS.Utilities.hasClass(element, "win-settingsflyout")) { - this._dismiss(); - } else { - this.hide(); - } - }, - - _resize: function _Overlay_resize(event) { - // Nothing by default - }, - - _contentChanged: function _Overlay_contentChanged(needToReMeasure) { - // Nothing by default - }, - - _checkScrollPosition: function _Overlay_checkScrollPosition(event) { - // Nothing by default - }, - - _showingKeyboard: function _Overlay_showingKeyboard(event) { - // Nothing by default - }, - - _hidingKeyboard: function _Overlay_hidingKeyboard(event) { - // Nothing by default - }, - - // Verify that this HTML AppBar only has AppBar/MenuCommands. - _verifyCommandsOnly: function _Overlay_verifyCommandsOnly(element, type) { - var children = element.children; - var commands = new Array(children.length); - for (var i = 0; i < children.length; i++) { - // If constructed they have win-command class, otherwise they have data-win-control - if (!WinJS.Utilities.hasClass(children[i], "win-command") && - children[i].getAttribute("data-win-control") !== type) { - // Wasn't tagged with class or AppBar/MenuCommand, not an AppBar/MenuCommand - throw new WinJS.ErrorFromName("WinJS.UI._Overlay.MustContainCommands", strings.mustContainCommands); - } else { - // Instantiate the commands. - WinJS.UI.processAll(children[i]); - commands[i] = children[i].winControl; - } - } - return commands; - }, - - // Sets focus on what we think is the last tab stop. If nothing is focusable will - // try to set focus on itself. - _focusOnLastFocusableElementOrThis: function _Overlay_focusOnLastFocusableElementOrThis() { - if (!this._focusOnLastFocusableElement()) { - // Nothing is focusable. Set focus to this. - _Overlay._trySetActive(this._element); - } - }, - - // Sets focus to what we think is the last tab stop. This element must have - // a firstDiv with tabIndex equal to the lowest tabIndex in the element - // and a finalDiv with tabIndex equal to the highest tabIndex in the element. - // Also the firstDiv must be its first child and finalDiv be its last child. - // Returns true if successful, false otherwise. - _focusOnLastFocusableElement: function _Overlay_focusOnLastFocusableElement() { - if (this._element.firstElementChild) { - var oldFirstTabIndex = this._element.firstElementChild.tabIndex; - var oldLastTabIndex = this._element.lastElementChild.tabIndex; - this._element.firstElementChild.tabIndex = -1; - this._element.lastElementChild.tabIndex = -1; - - var tabResult = WinJS.Utilities._focusLastFocusableElement(this._element); - - if (tabResult) { - _Overlay._trySelect(document.activeElement); - } - - this._element.firstElementChild.tabIndex = oldFirstTabIndex; - this._element.lastElementChild.tabIndex = oldLastTabIndex; - - return tabResult; - } else { - return false; - } - }, - - - // Sets focus on what we think is the first tab stop. If nothing is focusable will - // try to set focus on itself. - _focusOnFirstFocusableElementOrThis: function _Overlay_focusOnFirstFocusableElementOrThis() { - if (!this._focusOnFirstFocusableElement()) { - // Nothing is focusable. Set focus to this. - _Overlay._trySetActive(this._element); - } - }, - - // Sets focus to what we think is the first tab stop. This element must have - // a firstDiv with tabIndex equal to the lowest tabIndex in the element - // and a finalDiv with tabIndex equal to the highest tabIndex in the element. - // Also the firstDiv must be its first child and finalDiv be its last child. - // Returns true if successful, false otherwise. - _focusOnFirstFocusableElement: function _Overlay__focusOnFirstFocusableElement() { - if (this._element.firstElementChild) { - var oldFirstTabIndex = this._element.firstElementChild.tabIndex; - var oldLastTabIndex = this._element.lastElementChild.tabIndex; - this._element.firstElementChild.tabIndex = -1; - this._element.lastElementChild.tabIndex = -1; - - var tabResult = WinJS.Utilities._focusFirstFocusableElement(this._element); - - if (tabResult) { - _Overlay._trySelect(document.activeElement); - } - - this._element.firstElementChild.tabIndex = oldFirstTabIndex; - this._element.lastElementChild.tabIndex = oldLastTabIndex; - - return tabResult; - } else { - return false; - } - }, - - _addOverlayEventHandlers: function _Overlay_addOverlayEventHandlers(isFlyoutOrSettingsFlyout) { - // Set up global event handlers for all overlays - if (!_Overlay._flyoutEdgeLightDismissEvent) { - // Dismiss on blur & resize - window.addEventListener("blur", _Overlay._checkBlur, false); - - var that = this; - - // Be careful so it behaves in designer as well. - if (WinJS.Utilities.hasWinRT) { - // Catch edgy events too - var commandUI = Windows.UI.Input.EdgeGesture.getForCurrentView(); - commandUI.addEventListener("starting", _Overlay._hideAllFlyouts); - commandUI.addEventListener("completed", _edgyMayHideFlyouts); - - // React to Soft Keyboard events - var inputPane = Windows.UI.ViewManagement.InputPane.getForCurrentView(); - inputPane.addEventListener("showing", function (event) { - that._writeProfilerMark("_showingKeyboard,StartTM"); - _allOverlaysCallback(event, "_showingKeyboard"); - that._writeProfilerMark("_showingKeyboard,StopTM"); - }); - inputPane.addEventListener("hiding", function (event) { - that._writeProfilerMark("_hidingKeyboard,StartTM"); - _allOverlaysCallback(event, "_hidingKeyboard"); - that._writeProfilerMark("_hidingKeyboard,StopTM"); - }); - // Document scroll event - document.addEventListener("scroll", function (event) { - that._writeProfilerMark("_checkScrollPosition,StartTM"); - _allOverlaysCallback(event, "_checkScrollPosition"); - that._writeProfilerMark("_checkScrollPosition,StopTM"); - }); - } - // Window resize event - window.addEventListener("resize", function (event) { - that._writeProfilerMark("_baseResize,StartTM"); - _allOverlaysCallback(event, "_baseResize"); - that._writeProfilerMark("_baseResize,StopTM"); - }); - - _Overlay._flyoutEdgeLightDismissEvent = true; - } - - // Individual handlers for Flyouts only - if (isFlyoutOrSettingsFlyout) { - this._handleEventsForFlyoutOrSettingsFlyout(); - } - }, - - _handleEventsForFlyoutOrSettingsFlyout: function _Overlay_handleEventsForFlyoutOrSettingsFlyout() { - var that = this; - // Need to hide ourselves if we lose focus - this._element.addEventListener("focusout", function (e) { _Overlay._hideIfLostFocus(that, e); }, false); - - // Attempt to flag right clicks that may turn into edgy - this._element.addEventListener("pointerdown", _Overlay._checkRightClickDown, true); - this._element.addEventListener("pointerup", _Overlay._checkRightClickUp, true); - }, - - _writeProfilerMark: function _Overlay_writeProfilerMark(text) { - msWriteProfilerMark("WinJS.UI._Overlay:" + this._id + ":" + text); - } - }); - - // Statics - _Overlay._clickEatingAppBarDiv = false; - _Overlay._clickEatingFlyoutDiv = false; - _Overlay._flyoutEdgeLightDismissEvent = false; - - _Overlay._hideFlyouts = function (testElement, notSticky) { - var elements = testElement.querySelectorAll(".win-flyout"); - var len = elements.length; - for (var i = 0; i < len; i++) { - var element = elements[i]; - if (element.style.visibility !== "hidden") { - var flyout = element.winControl; - if (flyout && (!notSticky || !flyout._sticky)) { - flyout._hideOrDismiss(); - } - } - } - }; - - _Overlay._hideSettingsFlyouts = function (testElement, notSticky) { - var elements = testElement.querySelectorAll(".win-settingsflyout"); - var len = elements.length; - for (var i = 0; i < len; i++) { - var element = elements[i]; - if (element.style.visibility !== "hidden") { - var settingsFlyout = element.winControl; - if (settingsFlyout && (!notSticky || !settingsFlyout._sticky)) { - settingsFlyout._hideOrDismiss(); - } - } - } - }; - - _Overlay._hideAllFlyouts = function () { - _Overlay._hideFlyouts(document, true); - _Overlay._hideSettingsFlyouts(document, true) - }; - - _Overlay._createClickEatingDivTemplate = function (divClass, hideClickEatingDivFunction) { - var clickEatingDiv = document.createElement("section"); - WinJS.Utilities.addClass(clickEatingDiv, divClass); - clickEatingDiv.addEventListener("pointerup", function (event) { _Overlay._checkSameClickEatingPointerUp(event, true); }, true); - clickEatingDiv.addEventListener("pointerdown", function (event) { _Overlay._checkClickEatingPointerDown(event, true); }, true); - clickEatingDiv.addEventListener("click", hideClickEatingDivFunction, true); - // Tell Aria that it's clickable - clickEatingDiv.setAttribute("role", "menuitem"); - clickEatingDiv.setAttribute("aria-label", strings.closeOverlay); - // Prevent CED from removing any current selection - clickEatingDiv.setAttribute("unselectable", "on"); - document.body.appendChild(clickEatingDiv); - return clickEatingDiv; - }; - - // Used by AppBar, and Settings Pane - _Overlay._createClickEatingDivAppBar = function () { - if (!_Overlay._clickEatingAppBarDiv) { - _Overlay._clickEatingAppBarDiv = _Overlay._createClickEatingDivTemplate(_Overlay._clickEatingAppBarClass, _Overlay._handleAppBarClickEatingClick); - } - }; - - // Used by Flyout and Menu - _Overlay._createClickEatingDivFlyout = function () { - if (!_Overlay._clickEatingFlyoutDiv) { - _Overlay._clickEatingFlyoutDiv = _Overlay._createClickEatingDivTemplate(_Overlay._clickEatingFlyoutClass, _Overlay._handleFlyoutClickEatingClick); - } - }; - - // All click-eaters eat "down" clicks so that we can still eat - // the "up" click that'll come later. - _Overlay._checkClickEatingPointerDown = function (event, stopPropogation) { - var target = event.currentTarget; - if (target) { - try { - // Remember pointer id and remember right mouse - target._winPointerId = event.pointerId; - // Cache right mouse if that was what happened - target._winRightMouse = (event.button === 2); - } catch (e) { } - } - - if (stopPropogation && !target._winRightMouse) { - event.stopPropagation(); - event.preventDefault(); - } - }; - - // Make sure that if we have an up we had an earlier down of the same kind - _Overlay._checkSameClickEatingPointerUp = function (event, stopPropogation) { - var result = false, - rightMouse = false, - target = event.currentTarget; - - // Same pointer we were watching? - try { - if (target && target._winPointerId === event.pointerId) { - // Same pointer - result = true; - rightMouse = target._winRightMouse; - // For click-eaters, don't count right click the same because edgy will dismiss - if (rightMouse && stopPropogation) { - result = false; - } - } - } catch (e) { } - - - if (stopPropogation && !rightMouse) { - event.stopPropagation(); - event.preventDefault(); - } - - return result; - }; - - // If they click on a click eating div, even with a right click, - // touch or anything, then we want to light dismiss that layer. - _Overlay._handleAppBarClickEatingClick = function (event) { - event.stopPropagation(); - event.preventDefault(); - - thisWinUI.AppBar._hideLightDismissAppBars(null, false); - _Overlay._hideClickEatingDivAppBar(); - _Overlay._hideAllFlyouts(); - }; - - // If they click on a click eating div, even with a right click, - // touch or anything, then we want to light dismiss that layer. - _Overlay._handleFlyoutClickEatingClick = function (event) { - event.stopPropagation(); - event.preventDefault(); - - // Don't light dismiss AppBars because edgy will do that as needed, - // so flyouts only. - _Overlay._hideClickEatingDivFlyout(); - _Overlay._hideFlyouts(document, true); - }; - - _Overlay._checkRightClickDown = function (event) { - _Overlay._checkClickEatingPointerDown(event, false); - }; - - _Overlay._checkRightClickUp = function (event) { - if (_Overlay._checkSameClickEatingPointerUp(event, false)) { - // It was a right click we may want to eat. - _Overlay._rightMouseMightEdgy = true; - setImmediate(function () { _Overlay._rightMouseMightEdgy = false; }); - } - }; - - _Overlay._showClickEatingDivAppBar = function () { - WinJS.Utilities.Scheduler.schedule(function () { - _Overlay._clickEatingAppBarDiv.style.display = "block"; - }, WinJS.Utilities.Scheduler.Priority.high, null, "WinJS.UI._Overlay._showClickEatingDivAppBar"); - }; - - _Overlay._hideClickEatingDivAppBar = function () { - WinJS.Utilities.Scheduler.schedule(function () { - _Overlay._clickEatingAppBarDiv.style.display = "none"; - }, WinJS.Utilities.Scheduler.Priority.high, null, "WinJS.UI._Overlay._hideClickEatingDivAppBar"); - }; - - _Overlay._showClickEatingDivFlyout = function () { - WinJS.Utilities.Scheduler.schedule(function () { - _Overlay._clickEatingFlyoutDiv.style.display = "block"; - }, WinJS.Utilities.Scheduler.Priority.high, null, "WinJS.UI._Overlay._showClickEatingDivFlyout"); - }; - - _Overlay._hideClickEatingDivFlyout = function () { - WinJS.Utilities.Scheduler.schedule(function () { - _Overlay._clickEatingFlyoutDiv.style.display = "none"; - }, WinJS.Utilities.Scheduler.Priority.high, null, "WinJS.UI._Overlay._hideClickEatingDivFlyout"); - }; - - _Overlay._isFlyoutVisible = function () { - if (!_Overlay._clickEatingFlyoutDiv) { - return false; - } - return (_Overlay._clickEatingFlyoutDiv.style.display === "block"); - }; - - _Overlay._hideIfLostFocus = function (overlay, focusEvent) { - // If we're still showing we haven't really lost focus - if (overlay.hidden || overlay.element.winAnimating === "showing" || overlay._sticky) { - return; - } - // If the active thing is within our element, we haven't lost focus - var active = document.activeElement; - if (overlay._element && overlay._element.contains(active)) { - return; - } - // SettingFlyouts don't dismiss if they spawned a flyout - if (WinJS.Utilities.hasClass(overlay._element, "win-settingsflyout")) { - var settingsFlyout = overlay; - var flyoutControl = _Overlay._getParentControlUsingClassName(active, "win-flyout"); - if (flyoutControl && flyoutControl._previousFocus && settingsFlyout.element.contains(flyoutControl._previousFocus)) { - flyoutControl.element.addEventListener('focusout', function focusOut(event) { - // When the Flyout closes, hide the SetingsFlyout if it didn't regain focus. - _Overlay._hideIfLostFocus(settingsFlyout, event); - flyoutControl.element.removeEventListener('focusout', focusOut, false); - }, false); - return; - } - } - // Do not hide focus if focus moved to a CED. Let the click handler on the CED take care of hiding us. - if (active && - (WinJS.Utilities.hasClass(active, _Overlay._clickEatingFlyoutClass) || - WinJS.Utilities.hasClass(active, _Overlay._clickEatingAppBarClass))) { - return; - } - - overlay._hideOrDismiss(); - }; - - // Want to hide flyouts on blur. - // We get blur if we click off the window, including to an iframe within our window. - // Both blurs call this function, but fortunately document.hasFocus is true if either - // the document window or our iframe window has focus. - _Overlay._checkBlur = function (focusEvent) { - if (!document.hasFocus()) { - // The document doesn't have focus, so they clicked off the app, so light dismiss. - _Overlay._hideAllFlyouts(); - thisWinUI.AppBar._hideLightDismissAppBars(null, false); - } else { - if ((_Overlay._clickEatingFlyoutDiv && - _Overlay._clickEatingFlyoutDiv.style.display === "block") || - (_Overlay._clickEatingAppBarDiv && - _Overlay._clickEatingAppBarDiv.style.display === "block")) { - // We were trying to unfocus the window, but document still has focus, - // so make sure the iframe that took the focus will check for blur next time. - // We don't have to do this if the click eating div is hidden because then - // there would be no flyout or appbar needing light dismiss. - var active = document.activeElement; - if (active && active.tagName === "IFRAME" && !active.msLightDismissBlur) { - // This will go away when the IFRAME goes away, and we only create one - active.msLightDismissBlur = active.addEventListener("blur", _Overlay._checkBlur, false); - } - } - } - }; - - // Try to set us as active - _Overlay._trySetActive = function (element) { - if (!element || !element.setActive || !document.body || !document.body.contains(element)) { - return false; - } - try { - element.setActive(); - } catch (err) { - return false; - } - return (element === document.activeElement); - }; - - // Try to select the text so keyboard can be used. - _Overlay._trySelect = function (element) { - try { - if (element && element.select) { - element.select(); - } - } catch (e) { } - }; - - // Prevent the document.activeElement from showing focus - _Overlay._addHideFocusClass = function (element) { - if (element) { - WinJS.Utilities.addClass(element, hideFocusClass); - element.addEventListener("focusout", _Overlay._removeHideFocusClass, false); - } - }; - - // Allow the event.target (element that is losing focus) to show focus next time it gains focus - _Overlay._removeHideFocusClass = function (event) { - // Make sure we really lost focus and was not just an App switch - var target = event.target; - if (target && target !== document.activeElement) { - WinJS.Utilities.removeClass(target, hideFocusClass); - event.target.removeEventListener("focusout", _Overlay._removeHideFocusClass, false); - } - }; - - _Overlay._getParentControlUsingClassName = function (element, className) { - while (element && element !== document.body) { - if (WinJS.Utilities.hasClass(element, className)) { - return element.winControl; - } - element = element.parentNode; - } - return null; - }; - - // Global keyboard hiding offset - _Overlay._keyboardInfo = { - // Determine if the keyboard is visible or not. - get _visible() { - try { - return (WinJS.Utilities.hasWinRT && Windows.UI.ViewManagement.InputPane.getForCurrentView().occludedRect.height > 0); - } catch (e) { - return false; - } - }, - - // See if we have to reserve extra space for the IHM - get _extraOccluded() { - var occluded; - if (WinJS.Utilities.hasWinRT) { - try { - occluded = Windows.UI.ViewManagement.InputPane.getForCurrentView().occludedRect.height; - } catch (e) { - } - } - - // Nothing occluded if not visible. - if (occluded && !_Overlay._keyboardInfo._isResized) { - // View hasn't been resized, need to return occluded height. - return occluded; - } - - // View already has space for keyboard or there's no keyboard - return 0; - }, - - // See if the view has been resized to fit a keyboard - get _isResized() { - // Compare ratios. Very different includes IHM space. - var heightRatio = document.documentElement.clientHeight / window.innerHeight, - widthRatio = document.documentElement.clientWidth / window.innerWidth; - - // If they're nearly identical, then the view hasn't been resized for the IHM - // Only check one bound because we know the IHM will make it shorter, not skinnier. - return (widthRatio / heightRatio < 0.99); - }, - - // Get the top of our visible area in terms of document.documentElement. - get _visibleDocTop() { - return window.pageYOffset - document.documentElement.scrollTop; - }, - - // Get the bottom of our visible area. - get _visibleDocBottom() { - return _Overlay._keyboardInfo._visibleDocTop + _Overlay._keyboardInfo._visibleDocHeight; - }, - - // Get the height of the visible document, e.g. the height of the visual viewport minus any IHM occlusion. - get _visibleDocHeight() { - return _Overlay._keyboardInfo._visualViewportHeight -_Overlay._keyboardInfo._extraOccluded; - }, - - // Get the visual viewport height. window.innerHeight doesn't return floating point values which are present with high DPI. - get _visualViewportHeight() { - var boundingRect = _Overlay._keyboardInfo._visualViewportSpace; - return boundingRect.bottom - boundingRect.top; - }, - - // Get the visual viewport width. window.innerHeight doesn't return floating point values which are present with high DPI. - get _visualViewportWidth() { - var boundingRect = _Overlay._keyboardInfo._visualViewportSpace; - return boundingRect.right - boundingRect.left; - }, - - get _visualViewportSpace() { - var className = "win-visualviewport-space" - var visualViewportSpace = document.body.querySelector("." + className); - if (!visualViewportSpace) { - visualViewportSpace = document.createElement("DIV"); - visualViewportSpace.className = className; - document.body.appendChild(visualViewportSpace); - } - - return visualViewportSpace.getBoundingClientRect(); - }, - - // Get offset of visible window from bottom. - get _visibleDocBottomOffset() { - // If the view resizes we can return 0 and rely on appbar's -ms-device-fixed css positioning. - return (_Overlay._keyboardInfo._isResized) ? 0 : _Overlay._keyboardInfo._extraOccluded; - }, - - // Get total length of the IHM showPanel animation - get _animationShowLength() { - if (!WinJS.Utilities.hasWinRT) { - return 0; - } - - var a = Windows.UI.Core.AnimationMetrics, - animationDescription = new a.AnimationDescription(a.AnimationEffect.showPanel, a.AnimationEffectTarget.primary); - var animations = animationDescription.animations; - var max = 0; - for (var i = 0; i < animations.size; i++) { - var animation = animations[i]; - max = Math.max(max, animation.delay + animation.duration); - } - return max; - } - }; - - // Classes other objects use - _Overlay._clickEatingAppBarClass = "win-appbarclickeater"; - _Overlay._clickEatingFlyoutClass = "win-flyoutmenuclickeater"; - - // Padding for IHM timer to allow for first scroll event - _Overlay._scrollTimeout = 150; - - // Events - _Overlay.beforeShow = BEFORESHOW; - _Overlay.beforeHide = BEFOREHIDE; - _Overlay.afterShow = AFTERSHOW; - _Overlay.afterHide = AFTERHIDE; - - _Overlay.commonstrings = { - get cannotChangeCommandsWhenVisible() { return WinJS.Resources._getWinJSString("ui/cannotChangeCommandsWhenVisible").value; }, - get cannotChangeHiddenProperty() { return WinJS.Resources._getWinJSString("ui/cannotChangeHiddenProperty").value; } - }; - - var strings = { - get duplicateConstruction() { return WinJS.Resources._getWinJSString("ui/duplicateConstruction").value; }, - get mustContainCommands() { return WinJS.Resources._getWinJSString("ui/mustContainCommands").value; }, - get closeOverlay() { return WinJS.Resources._getWinJSString("ui/closeOverlay").value; }, - }; - - WinJS.Class.mix(_Overlay, WinJS.UI.DOMEventMixin); - - return _Overlay; - }) - }); - -})(WinJS); - - -// Glyph Enumeration -/// Segoe -(function appBarIconInit(WinJS) { - "use strict"; - - var glyphs = ["previous", - "next", - "play", - "pause", - "edit", - "save", - "clear", - "delete", - "remove", - "add", - "cancel", - "accept", - "more", - "redo", - "undo", - "home", - "up", - "forward", - "right", - "back", - "left", - "favorite", - "camera", - "settings", - "video", - "sync", - "download", - "mail", - "find", - "help", - "upload", - "emoji", - "twopage", - "leavechat", - "mailforward", - "clock", - "send", - "crop", - "rotatecamera", - "people", - "closepane", - "openpane", - "world", - "flag", - "previewlink", - "globe", - "trim", - "attachcamera", - "zoomin", - "bookmarks", - "document", - "protecteddocument", - "page", - "bullets", - "comment", - "mail2", - "contactinfo", - "hangup", - "viewall", - "mappin", - "phone", - "videochat", - "switch", - "contact", - "rename", - "pin", - "musicinfo", - "go", - "keyboard", - "dockleft", - "dockright", - "dockbottom", - "remote", - "refresh", - "rotate", - "shuffle", - "list", - "shop", - "selectall", - "orientation", - "import", - "importall", - "browsephotos", - "webcam", - "pictures", - "savelocal", - "caption", - "stop", - "showresults", - "volume", - "repair", - "message", - "page2", - "calendarday", - "calendarweek", - "calendar", - "characters", - "mailreplyall", - "read", - "link", - "accounts", - "showbcc", - "hidebcc", - "cut", - "attach", - "paste", - "filter", - "copy", - "emoji2", - "important", - "mailreply", - "slideshow", - "sort", - "manage", - "allapps", - "disconnectdrive", - "mapdrive", - "newwindow", - "openwith", - "contactpresence", - "priority", - "uploadskydrive", - "gototoday", - "font", - "fontcolor", - "contact2", - "folder", - "audio", - "placeholder", - "view", - "setlockscreen", - "settile", - "cc", - "stopslideshow", - "permissions", - "highlight", - "disableupdates", - "unfavorite", - "unpin", - "openlocal", - "mute", - "italic", - "underline", - "bold", - "movetofolder", - "likedislike", - "dislike", - "like", - "alignright", - "aligncenter", - "alignleft", - "zoom", - "zoomout", - "openfile", - "otheruser", - "admin", - "street", - "map", - "clearselection", - "fontdecrease", - "fontincrease", - "fontsize", - "cellphone", - "reshare", - "tag", - "repeatone", - "repeatall", - "outlinestar", - "solidstar", - "calculator", - "directions", - "target", - "library", - "phonebook", - "memo", - "microphone", - "postupdate", - "backtowindow", - "fullscreen", - "newfolder", - "calendarreply", - "unsyncfolder", - "reporthacked", - "syncfolder", - "blockcontact", - "switchapps", - "addfriend", - "touchpointer", - "gotostart", - "zerobars", - "onebar", - "twobars", - "threebars", - "fourbars", - "scan", - "preview"]; - - // Provide properties to grab resources for each of the icons - /// - /// The AppBarIcon enumeration provides a set of glyphs for use with the AppBarCommand icon property. - /// - WinJS.Namespace.define("WinJS.UI.AppBarIcon", - glyphs.reduce(function (fixedIcons, item) { - fixedIcons[item] = { get: function () { return WinJS.Resources._getWinJSString("ui/appBarIcons/" + item).value; } }; - return fixedIcons; - }, {})); -})(WinJS); -// AppBarCommand -/// appbar,appbars,Flyout,Flyouts,onclick,Statics -(function appBarCommandInit(WinJS) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// Represents a command to display in an AppBar. - /// - /// - /// - /// ]]> - /// The AppBarCommand control itself. - /// The AppBarCommand's icon box. - /// The AppBarCommand's icon's image formatting. - /// The AppBarCommand's icon's ring. - /// The AppBarCommand's label - /// - /// - /// - AppBarCommand: WinJS.Namespace._lazy(function () { - var thisWinUI = WinJS.UI; - - // Class Names - var appBarCommandClass = "win-command", - appBarCommandGlobalClass = "win-global", - appBarCommandSelectionClass = "win-selection", - reducedClass = "win-reduced", - typeSeparator = "separator", - typeButton = "button", - typeToggle = "toggle", - typeFlyout = "flyout", - typeContent = "content", - sectionSelection = "selection", - sectionGlobal = "global"; - - function _handleClick(event) { - var command = this.winControl; - if (command) { - if (command._type === typeToggle) { - command.selected = !command.selected; - } else if (command._type === typeFlyout && command._flyout) { - var parentAppBar = thisWinUI._Overlay._getParentControlUsingClassName(this, "win-appbar"); - var placement = "top"; - if (parentAppBar && parentAppBar.placement === "top") { - placement = "bottom"; - } - var flyout = command._flyout; - // Flyout may not have processAll'd, so this may be a DOM object - if (typeof flyout === "string") { - flyout = document.getElementById(flyout); - } - if (!flyout.show) { - flyout = flyout.winControl; - } - if (flyout && flyout.show) { - flyout.show(this, placement); - } - } - if (command.onclick) { - command.onclick(event); - } - } - } - - var strings = { - get ariaLabel() { return WinJS.Resources._getWinJSString("ui/appBarCommandAriaLabel").value; }, - get duplicateConstruction() { return WinJS.Resources._getWinJSString("ui/duplicateConstruction").value; }, - get badClick() { return WinJS.Resources._getWinJSString("ui/badClick").value; }, - get badDivElement() { return WinJS.Resources._getWinJSString("ui/badDivElement").value; }, - get badHrElement() { return WinJS.Resources._getWinJSString("ui/badHrElement").value; }, - get badButtonElement() { return WinJS.Resources._getWinJSString("ui/badButtonElement").value; } - }; - - return WinJS.Class.define(function AppBarCommand_ctor(element, options) { - /// - /// - /// Creates a new AppBarCommand control. - /// - /// - /// The DOM element that will host the control. AppBarCommand will create one if null. - /// - /// - /// The set of properties and values to apply to the new AppBarCommand. - /// - /// - /// The new AppBarCommand control. - /// - /// - - // Check to make sure we weren't duplicated - if (element && element.winControl) { - throw new WinJS.ErrorFromName("WinJS.UI.AppBarCommand.DuplicateConstruction", strings.duplicateConstruction); - } - - this._disposed = false; - - // Don't blow up if they didn't pass options - if (!options) { - options = {}; - } - - // Need a type before we can create our element - if (!options.type) { - this._type = typeButton; - } - - // Go ahead and create it, separator and content types look different than buttons - // Don't forget to use passed in element if one was provided. - this._element = element; - - if (options.type === typeContent) { - this._createContent(); - } - else if (options.type === typeSeparator) { - this._createSeparator(); - } else { - // This will also set the icon & label - this._createButton(); - } - WinJS.Utilities.addClass(this._element, "win-disposable"); - - // Remember ourselves - this._element.winControl = this; - - // Attach our css class - WinJS.Utilities.addClass(this._element, appBarCommandClass); - - if (options.onclick) { - this.onclick = options.onclick; - } - // We want to handle some clicks - options.onclick = _handleClick; - - WinJS.UI.setOptions(this, options); - - if (!options.section) { - this._setSection(options.section); - } - - if (this._type === typeToggle && !options.selected) { - this.selected = false; - } - - // Set up pointerdown handler and clean up ARIA if needed - if (this._type !== typeSeparator) { - - // Hide the modern focus rect on click or touch - var that = this; - this._element.addEventListener("pointerdown", function () { thisWinUI._Overlay._addHideFocusClass(that._element); }, false); - - // Make sure we have an ARIA role - var role = this._element.getAttribute("role"); - if (role === null || role === "" || role === undefined) { - if (this._type === typeToggle) { - role = "menuitemcheckbox"; - } else if (this._type === typeContent) { - role = "group"; - } else { - role = "menuitem"; - } - this._element.setAttribute("role", role); - if (this._type === typeFlyout) { - this._element.setAttribute("aria-haspopup", true); - } - } - // Label should've been set by label, but if it was missed for some reason: - var label = this._element.getAttribute("aria-label"); - if (label === null || label === "" || label === undefined) { - this._element.setAttribute("aria-label", strings.ariaLabel); - } - } - }, { - /// - /// Gets or sets the ID of the AppBarCommand. - /// - id: { - get: function () { - return this._element.id; - }, - - set: function (value) { - // we allow setting first time only. otherwise we ignore it. - if (value && !this._element.id) { - this._element.id = value; - } - } - }, - - /// - /// Gets or sets the type of the AppBarCommand. Possible values are "button", "toggle", "flyout", or "separator". - /// - type: { - get: function () { - return this._type; - }, - set: function (value) { - // we allow setting first time only. otherwise we ignore it. - if (!this._type) { - if (value !== typeContent && value !== typeFlyout && value !== typeToggle && value !== typeSeparator) { - this._type = typeButton; - } else { - this._type = value; - } - } - } - }, - - /// - /// Gets or sets the label of the AppBarCommand. - /// - label: { - get: function () { - return this._label; - }, - set: function (value) { - this._label = value; - if (this._labelSpan) { - this._labelSpan.innerText = this.label; - } - - // Ensure that we have a tooltip, by updating already-constructed tooltips. Separators won't have these: - if (!this.tooltip && this._tooltipControl) { - this._tooltip = this.label; - this._tooltipControl.innerHTML = this.label; - } - - // Update aria-label - this._element.setAttribute("aria-label", this.label); - - // Check if we need to suppress the tooltip - this._testIdenticalTooltip(); - } - }, - - /// - /// Gets or sets the icon of the AppBarCommand. - /// - icon: { - get: function () { - return this._icon; - }, - set: function (value) { - if (value) { - this._icon = (WinJS.UI.AppBarIcon[value] || value); - } else { - this._icon = value; - } - - if (this._imageSpan) { - // If the icon's a single character, presume a glyph - if (this._icon && this._icon.length === 1) { - // Set the glyph - this._imageSpan.innerText = this._icon; - this._imageSpan.style.backgroundImage = ""; - this._imageSpan.style.msHighContrastAdjust = ""; - } else { - // Must be an image, set that - this._imageSpan.innerText = ""; - this._imageSpan.style.backgroundImage = this._icon; - this._imageSpan.style.msHighContrastAdjust = "none"; - } - } - } - }, - - /// - /// Gets or sets the function to invoke when the command is clicked. - /// - onclick: { - get: function () { - return this._onclick; - }, - set: function (value) { - if (value && typeof value !== "function") { - throw new WinJS.ErrorFromName("WinJS.UI.AppBarCommand.BadClick", WinJS.Resources._formatString(strings.badClick, "AppBarCommand")); - } - this._onclick = value; - } - }, - - /// - /// For flyout-type AppBarCommands, this property returns the WinJS.UI.Flyout that this command invokes. - /// When setting this property, you may also use the String ID of the flyout to invoke, the DOM object - /// for the flyout, or the WinJS.UI.Flayout object itself. - /// - flyout: { - get: function () { - // Resolve it to the flyout - var flyout = this._flyout; - if (typeof flyout === "string") { - flyout = document.getElementById(flyout); - } - // If it doesn't have a .element, then we need to getControl on it - if (flyout && !flyout.element) { - flyout = flyout.winControl; - } - - return flyout; - }, - set: function (value) { - // Need to update aria-owns with the new ID. - var id = value; - if (id && typeof id !== "string") { - // Our controls have .element properties - if (id.element) { - id = id.element; - } - // Hope it's a DOM element, get ID from DOM element - if (id) { - if (id.id) { - id = id.id; - } else { - // No id, have to fake one - id.id = id.uniqueID; - id = id.id; - } - } - } - if (typeof id === "string") { - this._element.setAttribute("aria-owns", id); - } - - // Remember it - this._flyout = value; - } - }, - - /// - /// Gets or sets the section that the AppBarCommand is in. Possible values are "selection" and "global". - /// - section: { - get: function () { - return this._section; - }, - set: function (value) { - // we allow settings section only one time - if (!this._section || (window.Windows && Windows.ApplicationModel && Windows.ApplicationModel.DesignMode && Windows.ApplicationModel.DesignMode.designModeEnabled)) { - this._setSection(value); - } - } - }, - - /// Gets or sets the tooltip text of the AppBarCommand. - tooltip: { - get: function () { - return this._tooltip; - }, - set: function (value) { - this._tooltip = value; - - // Update already-constructed tooltips. Separators and content commands won't have these: - if (this._tooltipControl) { - this._tooltipControl.innerHTML = this._tooltip; - } - - // Check if we need to suppress the tooltip - this._testIdenticalTooltip(); - } - }, - - /// Set or get the selected state of a toggle button. - selected: { - get: function () { - // Ensure it's a boolean because we're using the DOM element to keep in-sync - return this._element.getAttribute("aria-checked") === "true"; - }, - set: function (value) { - this._element.setAttribute("aria-checked", value); - } - }, - - /// - element: { - get: function () { - return this._element; - } - }, - - /// - /// Gets or sets a value that indicates whether the AppBarCommand is disabled. A value of true disables the AppBarCommand, and a value of false enables it. - /// - disabled: { - get: function () { - // Ensure it's a boolean because we're using the DOM element to keep in-sync - return !!this._element.disabled; - }, - set: function (value) { - this._element.disabled = value; - } - }, - - /// - hidden: { - get: function () { - // Ensure it's a boolean because we're using the DOM element to keep in-sync - return this._element.style.visibility === "hidden"; - }, - set: function (value) { - var appbarControl = thisWinUI._Overlay._getParentControlUsingClassName(this._element, "win-appbar"); - if (appbarControl && !appbarControl.hidden) { - throw new WinJS.ErrorFromName("WinJS.UI.AppBarCommand.CannotChangeHiddenProperty", WinJS.Resources._formatString(thisWinUI._Overlay.commonstrings.cannotChangeHiddenProperty, "AppBar")); - } - - if (value === this.hidden) { - // No changes to make. - return; - } - - var style = this._element.style; - - if (value) { - style.visibility = "hidden"; - style.display = "none"; - } else { - style.visibility = ""; - style.display = "inline-block"; - } - if (appbarControl) { - appbarControl._contentChanged(); - } - } - }, - - /// - /// Gets or sets the HTMLElement within a "content" type AppBarCommand that should receive focus whenever focus moves via Home or the arrow keys, - /// from the previous AppBarCommand to the this AppBarCommand. Returns the AppBarCommand object's host element by default. - /// - firstElementFocus: { - get: function () { - return this._firstElementFocus || this._lastElementFocus || this._element; - }, - set: function (element) { - // Arguments of null and this.element should treated the same to ensure that this.element is never a tabstop when either focus property has been set. - this._firstElementFocus = (element === this.element) ? null : element; - this._updateTabStop(); - } - }, - - /// - /// Gets or sets the HTMLElement within a "content" type AppBarCommand that should receive focus whenever focus would move, via End or arrow keys, - /// from the next AppBarCommand to this AppBarCommand. Returns this AppBarCommand object's host element by default. - /// - lastElementFocus: { - get: function () { - return this._lastElementFocus || this._firstElementFocus || this._element; - }, - set: function (element) { - // Arguments of null and this.element should treated the same to ensure that this.element is never a tabstop when either focus property has been set. - this._lastElementFocus = (element === this.element) ? null : element; - this._updateTabStop(); - } - }, - - dispose: function () { - /// - /// - /// Disposes this control. - /// - /// - if (this._disposed) { - return; - } - this._disposed = true; - - if (this._tooltipControl) { - this._tooltipControl.dispose(); - } - - if (this._type === typeContent) { - WinJS.Utilities.disposeSubTree(this.element); - } - }, - - addEventListener: function (type, listener, useCapture) { - /// - /// - /// Registers an event handler for the specified event. - /// - /// - /// Required. The name of the event to register. It must be "beforeshow", "beforehide", "aftershow", or "afterhide". - /// - /// Required. The event handler function to associate with this event. - /// - /// Optional. Set to true to register the event handler for the capturing phase; otherwise, set to false to register the event handler for the bubbling phase. - /// - /// - return this._element.addEventListener(type, listener, useCapture); - }, - - removeEventListener: function (type, listener, useCapture) { - /// - /// - /// Removes an event handler that the addEventListener method registered. - /// - /// Required. The name of the event to remove. - /// Required. The event handler function to remove. - /// - /// Optional. Set to true to remove the capturing phase event handler; otherwise, set to false to remove the bubbling phase event handler. - /// - /// - return this._element.removeEventListener(type, listener, useCapture); - }, - - /// Adds an extra CSS class during construction. - extraClass: { - get: function () { - return this._extraClass; - }, - set: function (value) { - if (this._extraClass) { - WinJS.Utilities.removeClass(this._element, this._extraClass); - } - this._extraClass = value; - WinJS.Utilities.addClass(this._element, this._extraClass); - } - }, - - // Private - _testIdenticalTooltip: function AppBarCommand_testIdenticalToolTip() { - this._hideIfFullSize = (this._label === this._tooltip); - }, - - _createContent: function AppBarCommand_createContent() { - // Make sure there's an element - if (!this._element) { - this._element = document.createElement("div"); - } else { - // Verify the element was a div - if (this._element.tagName !== "DIV") { - throw new WinJS.ErrorFromName("WinJS.UI.AppBarCommand.BadDivElement", strings.badDivElement); - } - } - - // If a tabIndex isnt set, default to 0; - if (parseInt(this._element.getAttribute("tabIndex"), 10) !== this._element.tabIndex) { - this._element.tabIndex = 0; - } - }, - - _createSeparator: function AppBarCommand_createSeparator() { - // Make sure there's an element - if (!this._element) { - this._element = document.createElement("hr"); - } else { - // Verify the element was an hr - if (this._element.tagName !== "HR") { - throw new WinJS.ErrorFromName("WinJS.UI.AppBarCommand.BadHrElement", strings.badHrElement); - } - } - }, - - _createButton: function AppBarCommand_createButton() { - // Make sure there's an element - if (!this._element) { - this._element = document.createElement("button"); - } else { - // Verify the element was a button - if (this._element.tagName !== "BUTTON") { - throw new WinJS.ErrorFromName("WinJS.UI.AppBarCommand.BadButtonElement", strings.badButtonElement); - } - // Make sure it has a type="button" - var type = this._element.getAttribute("type"); - if (type === null || type === "" || type === undefined) { - this._element.setAttribute("type", "button"); - } - this._element.innerHTML = ""; - } - - // AppBarCommand buttons need to look like this: - //// - this._element.type = "button"; - this._iconSpan = document.createElement("span"); - this._iconSpan.setAttribute("aria-hidden", "true"); - this._iconSpan.className = "win-commandicon win-commandring"; - this._iconSpan.tabIndex = -1; - this._element.appendChild(this._iconSpan); - this._imageSpan = document.createElement("span"); - this._imageSpan.setAttribute("aria-hidden", "true"); - this._imageSpan.className = "win-commandimage"; - this._imageSpan.tabIndex = -1; - this._iconSpan.appendChild(this._imageSpan); - this._labelSpan = document.createElement("span"); - this._labelSpan.setAttribute("aria-hidden", "true"); - this._labelSpan.className = "win-label"; - this._labelSpan.tabIndex = -1; - this._element.appendChild(this._labelSpan); - // 'win-global' or 'win-selection' are added later by caller. - // Label and icon are added later by caller. - - // Attach a tooltip - Note: we're going to stomp on it's setControl so we don't have to make another DOM element to hang it off of. - // This private _tooltipControl attribute is used by other pieces, changing the name could break them. - this._tooltipControl = new WinJS.UI.Tooltip(this._element); - var that = this; - this._tooltipControl.addEventListener("beforeopen", function () { - if (that._hideIfFullSize && !thisWinUI._Overlay._getParentControlUsingClassName(that._element.parentElement, reducedClass)) { - that._tooltipControl.close(); - } - }, false); - }, - - _setSection: function AppBarCommand_setSection(section) { - if (!section) { - section = sectionGlobal; - } - if (this._section) { - // Remove the old section class - if (this._section === sectionGlobal) { - WinJS.Utilities.removeClass(this._element, appBarCommandGlobalClass); - } else if (this.section === sectionSelection) { - WinJS.Utilities.removeClass(this._element, appBarCommandSelectionClass); - } - } - // Add the new section class - this._section = section; - if (section === sectionGlobal) { - WinJS.Utilities.addClass(this._element, appBarCommandGlobalClass); - } else if (section === sectionSelection) { - WinJS.Utilities.addClass(this._element, appBarCommandSelectionClass); - } - }, - - _updateTabStop: function AppBarCommand_updateTabStop() { - // Whenever the firstElementFocus or lastElementFocus properties are set for content type AppBarCommands, - // the containing command element is no longer a tabstop. - - if (this._firstElementFocus || this._lastElementFocus ) { - this.element.tabIndex = -1; - } else { - this.element.tabIndex = 0; - } - }, - - _isFocusable: function AppBarCommand_isFocusable() { - return (!this.hidden && this._type !== typeSeparator && !this.element.disabled && - (this.firstElementFocus.tabIndex >= 0 || this.lastElementFocus.tabIndex >= 0)) - }, - }); - }) - }); - -})(WinJS); - -// AppBar -/// appbar,appBars,Flyout,Flyouts,iframe,Statics,unfocus,WinJS -(function appBarInit(WinJS) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// Represents an application toolbar for display commands. - /// - /// - /// - /// - /// - /// ]]> - /// Raised just before showing the AppBar. - /// Raised immediately after the AppBar is fully shown. - /// Raised just before hiding the AppBar. - /// Raised immediately after the AppBar is fully hidden. - /// The AppBar control itself. - /// Style for a custom layout AppBar. - /// - /// - /// - AppBar: WinJS.Namespace._lazy(function () { - var thisWinUI = WinJS.UI; - - // Class Names - var commandClass = "win-commandlayout", - appBarClass = "win-appbar", - reducedClass = "win-reduced", - settingsFlyoutClass = "win-settingsflyout", - topClass = "win-top", - bottomClass = "win-bottom", - appBarCommandClass = "win-command"; - - var firstDivClass = "win-firstdiv", - finalDivClass = "win-finaldiv"; - - // Constants for placement - var appBarPlacementTop = "top", - appBarPlacementBottom = "bottom"; - - // Constants for layout - var appBarLayoutCustom = "custom", - appBarLayoutCommands = "commands"; - - // Constants for AppBarCommands - var typeSeparator = "separator", - typeContent = "content", - separatorWidth = 60, - buttonWidth = 100; - - // Hook into event - var appBarCommandEvent = false; - var edgyHappening = null; - - // Handler for the edgy starting/completed/cancelled events - function _completedEdgy(e) { - // If we had a right click on a flyout, ignore it. - if (thisWinUI._Overlay._rightMouseMightEdgy && - e.kind === Windows.UI.Input.EdgeGestureKind.mouse) { - return; - } - if (edgyHappening) { - // Edgy was happening, just skip it - edgyHappening = null; - } else { - // Edgy wasn't happening, so toggle - var keyboardInvoked = e.kind === Windows.UI.Input.EdgeGestureKind.keyboard; - WinJS.UI.AppBar._toggleAppBarEdgy(keyboardInvoked); - } - } - - function _startingEdgy() { - if (!edgyHappening) { - // Edgy wasn't happening, so toggle & start it - edgyHappening = WinJS.UI.AppBar._toggleAppBarEdgy(false); - } - } - - function _canceledEdgy() { - // Shouldn't get here unless edgy was happening. - // Undo whatever we were doing. - var bars = _getDynamicBarsForEdgy(); - if (edgyHappening === "showing") { - _hideAllBars(bars, false); - } else if (edgyHappening === "hiding") { - _showAllBars(bars, false); - } - edgyHappening = null; - } - - function _allManipulationChanged(event) { - var elements = document.querySelectorAll("." + appBarClass); - if (elements) { - var len = elements.length; - for (var i = 0; i < len; i++) { - var element = elements[i]; - var appbar = element.winControl; - if (appbar && !element.disabled) { - appbar._manipulationChanged(event); - } - } - } - } - - // Get all the non-sticky bars and return them. - // Returns array of AppBar objects. - // The array also has _hidden and/or _visible set if ANY are hidden or visible. - function _getDynamicBarsForEdgy() { - var elements = document.querySelectorAll("." + appBarClass); - var len = elements.length; - var AppBars = []; - AppBars._visible = false; - AppBars._hidden = false; - for (var i = 0; i < len; i++) { - var element = elements[i]; - if (element.disabled) { - // Skip disabled AppBars - continue; - } - var AppBar = element.winControl; - if (AppBar) { - AppBars.push(AppBar); - // Middle of animation is different than animated - if (AppBar._element.winAnimating) { - // If animating, look at showing/hiding - if (AppBar._element.winAnimating === "hiding") { - AppBars._hidden = true; - } else { - AppBars._visible = true; - } - } else { - // Not animating, so check visibility - if (AppBar._element.style.visibility === "hidden") { - AppBars._hidden = true; - } else { - AppBars._visible = true; - } - } - } - } - - return AppBars; - } - - // Show or hide all bars - function _hideAllBars(bars, keyboardInvoked) { - var len = bars.length; - var allBarsAnimationPromises = new Array(len); - for (var i = 0; i < len; i++) { - bars[i]._keyboardInvoked = keyboardInvoked; - bars[i].hide(); - allBarsAnimationPromises[i] = bars[i]._animationPromise; - } - return WinJS.Promise.join(allBarsAnimationPromises); - } - - function _showAllBars(bars, keyboardInvoked) { - var len = bars.length; - var allBarsAnimationPromises = new Array(len); - for (var i = 0; i < len; i++) { - bars[i]._keyboardInvoked = keyboardInvoked; - bars[i]._doNotFocus = false; - bars[i]._show(); - allBarsAnimationPromises[i] = bars[i]._animationPromise; - } - return WinJS.Promise.join(allBarsAnimationPromises); - } - - // Sets focus to the last AppBar in the provided appBars array with given placement. - // Returns true if focus was set. False otherwise. - function _setFocusToPreviousAppBarHelper(startIndex, appBarPlacement, appBars) { - for (var i = startIndex; i >= 0; i--) { - if (appBars[i].winControl - && appBars[i].winControl.placement === appBarPlacement - && !appBars[i].winControl.hidden - && appBars[i].winControl._focusOnLastFocusableElement - && appBars[i].winControl._focusOnLastFocusableElement()) { - return true; - } - } - return false; - } - - // Sets focus to the last AppBar in the provided appBars array with other placement. - // Returns true if focus was set. False otherwise. - function _setFocusToPreviousAppBarHelperNeither(startIndex, appBars) { - for (var i = startIndex; i >= 0; i--) { - if (appBars[i].winControl - && appBars[i].winControl.placement != appBarPlacementBottom - && appBars[i].winControl.placement != appBarPlacementTop - && !appBars[i].winControl.hidden - && appBars[i].winControl._focusOnLastFocusableElement - && appBars[i].winControl._focusOnLastFocusableElement()) { - return true; - } - } - return false; - } - - // Sets focus to the last tab stop of the previous AppBar - // AppBar tabbing order: - // 1) Bottom AppBars - // 2) Top AppBars - // 3) Other AppBars - // DOM order is respected, because an AppBar should not have a defined tabIndex - function _setFocusToPreviousAppBar() { - var appBars = document.querySelectorAll("." + appBarClass); - if (!appBars.length) { - return; - } - - var thisAppBarIndex = 0; - for (var i = 0; i < appBars.length; i++) { - if (appBars[i] === this.parentElement) { - thisAppBarIndex = i; - break; - } - } - - var appBarControl = this.parentElement.winControl; - if (appBarControl.placement === appBarPlacementBottom) { - // Bottom appBar: Focus order: (1)previous bottom appBars (2)other appBars (3)top appBars (4)bottom appBars - if (thisAppBarIndex && _setFocusToPreviousAppBarHelper(thisAppBarIndex - 1, appBarPlacementBottom, appBars)) { return; } - if (_setFocusToPreviousAppBarHelperNeither(appBars.length - 1, appBars)) { return; } - if (_setFocusToPreviousAppBarHelper(appBars.length - 1, appBarPlacementTop, appBars)) { return; } - if (_setFocusToPreviousAppBarHelper(appBars.length - 1, appBarPlacementBottom, appBars)) { return; } - } else if (appBarControl.placement === appBarPlacementTop) { - // Top appBar: Focus order: (1)previous top appBars (2)bottom appBars (3)other appBars (4)top appBars - if (thisAppBarIndex && _setFocusToPreviousAppBarHelper(thisAppBarIndex - 1, appBarPlacementTop, appBars)) { return; } - if (_setFocusToPreviousAppBarHelper(appBars.length - 1, appBarPlacementBottom, appBars)) { return; } - if (_setFocusToPreviousAppBarHelperNeither(appBars.length - 1, appBars)) { return; } - if (_setFocusToPreviousAppBarHelper(appBars.length - 1, appBarPlacementTop, appBars)) { return; } - } else { - // Other appBar: Focus order: (1)previous other appBars (2)top appBars (3)bottom appBars (4)other appBars - if (thisAppBarIndex && _setFocusToPreviousAppBarHelperNeither(thisAppBarIndex - 1, appBars)) { return; } - if (_setFocusToPreviousAppBarHelper(appBars.length - 1, appBarPlacementTop, appBars)) { return; } - if (_setFocusToPreviousAppBarHelper(appBars.length - 1, appBarPlacementBottom, appBars)) { return; } - if (_setFocusToPreviousAppBarHelperNeither(appBars.length - 1, appBars)) { return; } - } - } - - // Sets focus to the first AppBar in the provided appBars array with given placement. - // Returns true if focus was set. False otherwise. - function _setFocusToNextAppBarHelper(startIndex, appBarPlacement, appBars) { - for (var i = startIndex; i < appBars.length; i++) { - if (appBars[i].winControl - && appBars[i].winControl.placement === appBarPlacement - && !appBars[i].winControl.hidden - && appBars[i].winControl._focusOnFirstFocusableElement - && appBars[i].winControl._focusOnFirstFocusableElement()) { - return true; - } - } - return false; - } - - // Sets focus to the first AppBar in the provided appBars array with other placement. - // Returns true if focus was set. False otherwise. - function _setFocusToNextAppBarHelperNeither(startIndex, appBars) { - for (var i = startIndex; i < appBars.length; i++) { - if (appBars[i].winControl - && appBars[i].winControl.placement != appBarPlacementBottom - && appBars[i].winControl.placement != appBarPlacementTop - && !appBars[i].winControl.hidden - && appBars[i].winControl._focusOnFirstFocusableElement - && appBars[i].winControl._focusOnFirstFocusableElement()) { - return true; - } - } - return false; - } - - // Sets focus to the first tab stop of the next AppBar - // AppBar tabbing order: - // 1) Bottom AppBars - // 2) Top AppBars - // 3) Other AppBars - // DOM order is respected, because an AppBar should not have a defined tabIndex - function _setFocusToNextAppBar() { - var appBars = document.querySelectorAll("." + appBarClass); - - var thisAppBarIndex = 0; - for (var i = 0; i < appBars.length; i++) { - if (appBars[i] === this.parentElement) { - thisAppBarIndex = i; - break; - } - } - - var appBarControl = this.parentElement.winControl; - if (this.parentElement.winControl.placement === appBarPlacementBottom) { - // Bottom appBar: Focus order: (1)next bottom appBars (2)top appBars (3)other appBars (4)bottom appBars - if (_setFocusToNextAppBarHelper(thisAppBarIndex + 1, appBarPlacementBottom, appBars)) { return; } - if (_setFocusToNextAppBarHelper(0, appBarPlacementTop, appBars)) { return; } - if (_setFocusToNextAppBarHelperNeither(0, appBars)) { return; } - if (_setFocusToNextAppBarHelper(0, appBarPlacementBottom, appBars)) { return; } - } else if (this.parentElement.winControl.placement === appBarPlacementTop) { - // Top appBar: Focus order: (1)next top appBars (2)other appBars (3)bottom appBars (4)top appBars - if (_setFocusToNextAppBarHelper(thisAppBarIndex + 1, appBarPlacementTop, appBars)) { return; } - if (_setFocusToNextAppBarHelperNeither(0, appBars)) { return; } - if (_setFocusToNextAppBarHelper(0, appBarPlacementBottom, appBars)) { return; } - if (_setFocusToNextAppBarHelper(0, appBarPlacementTop, appBars)) { return; } - } else { - // Other appBar: Focus order: (1)next other appBars (2)bottom appBars (3)top appBars (4)other appBars - if (_setFocusToNextAppBarHelperNeither(thisAppBarIndex + 1, appBars)) { return; } - if (_setFocusToNextAppBarHelper(0, appBarPlacementBottom, appBars)) { return; } - if (_setFocusToNextAppBarHelper(0, appBarPlacementTop, appBars)) { return; } - if (_setFocusToNextAppBarHelperNeither(0, appBars)) { return; } - } - } - - // Updates the firstDiv & finalDiv of all visible AppBars - function _updateAllAppBarsFirstAndFinalDiv() { - var appBars = document.querySelectorAll("." + appBarClass); - - for (var i = 0; i < appBars.length; i++) { - if (appBars[i].winControl - && !appBars[i].winControl.hidden - && appBars[i].winControl._updateFirstAndFinalDiv) { - appBars[i].winControl._updateFirstAndFinalDiv(); - } - } - } - - // Returns true if a visible non-sticky (light dismiss) AppBar is found in the document - function _isThereVisibleNonStickyBar() { - var appBars = document.querySelectorAll("." + appBarClass); - for (var i = 0; i < appBars.length; i++) { - var appBarControl = appBars[i].winControl; - if (appBarControl && !appBarControl.sticky && - (!appBarControl.hidden || appBarControl._element.winAnimating === "showing")) { - return true; - } - } - - return false; - } - - // Hide all light dismiss AppBars if what has focus is not part of a AppBar or flyout. - function _hideIfAllAppBarsLostFocus() { - if (!thisWinUI.AppBar._isAppBarOrChild(document.activeElement)) { - thisWinUI.AppBar._hideLightDismissAppBars(null, false); - // Ensure that sticky appbars clear cached focus after light dismiss are dismissed, which moved focus. - thisWinUI.AppBar._ElementWithFocusPreviousToAppBar = null; - } - } - - // If the previous focus was not a AppBar or CED, store it in the cache - // (_isAppBarOrChild tests CED for us). - function _checkStorePreviousFocus(focusEvent) { - if (focusEvent.relatedTarget - && focusEvent.relatedTarget.focus - && !thisWinUI.AppBar._isAppBarOrChild(focusEvent.relatedTarget)) { - _storePreviousFocus(focusEvent.relatedTarget); - } - } - - // Cache the previous focus information - function _storePreviousFocus(element) { - if (element) { - thisWinUI.AppBar._ElementWithFocusPreviousToAppBar = element; - } - } - - // Try to return focus to what had focus before. - // If successfully return focus to a textbox, restore the selection too. - function _restorePreviousFocus() { - thisWinUI._Overlay._trySetActive(thisWinUI.AppBar._ElementWithFocusPreviousToAppBar); - } - - var strings = { - get ariaLabel() { return WinJS.Resources._getWinJSString("ui/appBarAriaLabel").value; }, - get requiresCommands() { return WinJS.Resources._getWinJSString("ui/requiresCommands").value; }, - get nullCommand() { return WinJS.Resources._getWinJSString("ui/nullCommand").value; }, - get cannotChangePlacementWhenVisible() { return WinJS.Resources._getWinJSString("ui/cannotChangePlacementWhenVisible").value; }, - get badLayout() { return WinJS.Resources._getWinJSString("ui/badLayout").value; }, - get cannotChangeLayoutWhenVisible() { return WinJS.Resources._getWinJSString("ui/cannotChangeLayoutWhenVisible").value; } - }; - - var AppBar = WinJS.Class.derive(WinJS.UI._Overlay, function AppBar_ctor(element, options) { - /// - /// - /// Creates a new AppBar control. - /// - /// - /// The DOM element that will host the control. - /// - /// - /// The set of properties and values to apply to the new AppBar control. - /// - /// - /// The new AppBar control. - /// - /// - - this._initializing = true; - - // Simplify checking later - options = options || {}; - - // Make sure there's an input element - this._element = element || document.createElement("div"); - this._id = this._element.id || this._element.uniqueID; - this._writeProfilerMark("constructor,StartTM"); - - // validate that if they didn't set commands, but want command - // layout that the HTML only contains commands. Do this first - // so that we don't leave partial AppBars in the DOM. - if (options.layout !== appBarLayoutCustom && !options.commands && this._element) { - // Shallow copy object so we can modify it. - options = WinJS.Utilities._shallowCopy(options); - options.commands = this._verifyCommandsOnly(this._element, "WinJS.UI.AppBarCommand"); - } - - // Call the base overlay constructor helper - this._baseOverlayConstructor(this._element, options); - - this._initializing = false; - - // Make a click eating div - thisWinUI._Overlay._createClickEatingDivAppBar(); - - // Attach our css class, - WinJS.Utilities.addClass(this._element, appBarClass); - // Also may need a command class if not a custom layout appbar - if (options.layout !== appBarLayoutCustom) { - WinJS.Utilities.addClass(this._element, commandClass); - } - - if (!options.placement) { - // Make sure we have default placement - this.placement = appBarPlacementBottom; - } - - // Make sure we have an ARIA role - var role = this._element.getAttribute("role"); - if (!role) { - this._element.setAttribute("role", "menubar"); - } - var label = this._element.getAttribute("aria-label"); - if (!label) { - this._element.setAttribute("aria-label", strings.ariaLabel); - } - - // Handle key down (esc) and key pressed (left & right) - this._element.addEventListener("keydown", this._handleKeyDown.bind(this), false); - - // Attach event handler - if (!appBarCommandEvent) { - // We'll trigger on invoking. Could also have invoked or canceled - // Eventually we may want click up on invoking and drop back on invoked. - // Check for namespace so it'll behave in the designer. - if (WinJS.Utilities.hasWinRT) { - var commandUI = Windows.UI.Input.EdgeGesture.getForCurrentView(); - commandUI.addEventListener("starting", _startingEdgy); - commandUI.addEventListener("completed", _completedEdgy); - commandUI.addEventListener("canceled", _canceledEdgy); - } - - // Need to know if the IHM is done scrolling - document.addEventListener("MSManipulationStateChanged", _allManipulationChanged, false); - - appBarCommandEvent = true; - } - - // Make sure _Overlay event handlers are hooked up (this aids light dismiss) - this._addOverlayEventHandlers(false); - - // Need to store what had focus before - this._element.addEventListener("focusin", function (event) { _checkStorePreviousFocus(event); }, false); - - // Need to hide ourselves if we lose focus - this._element.addEventListener("focusout", function (event) { _hideIfAllAppBarsLostFocus(); }, false); - - // Commands layout AppBar measures and caches its content synchronously in setOptions through the .commands property setter. - // Remove the commands layout AppBar from the layout tree at this point so we don't cause unnecessary layout costs whenever - // the window resizes or when CSS changes are applied to the commands layout AppBar's parent element. - if (this.layout === appBarLayoutCommands) { - this._element.style.display = "none"; - } - - this._writeProfilerMark("constructor,StopTM"); - - return this; - }, { - // Public Properties - - /// The placement of the AppBar on the display. Values are "top" or "bottom". - placement: { - get: function () { - return this._placement; - }, - set: function (value) { - // In designer we may have to move it - var wasShown = false; - if (window.Windows && Windows.ApplicationModel && Windows.ApplicationModel.DesignMode && Windows.ApplicationModel.DesignMode.designModeEnabled && !this.hidden) { - this._hide(); - wasShown = true; - } - - if (!this.hidden) { - throw new WinJS.ErrorFromName("WinJS.UI.AppBar.CannotChangePlacementWhenVisible", strings.cannotChangePlacementWhenVisible); - } - - // Set placement - this._placement = value; - - // Clean up win-top, win-bottom styles - if (this._placement === appBarPlacementTop) { - WinJS.Utilities.addClass(this._element, topClass); - WinJS.Utilities.removeClass(this._element, bottomClass); - } else if (this._placement === appBarPlacementBottom) { - WinJS.Utilities.removeClass(this._element, topClass); - WinJS.Utilities.addClass(this._element, bottomClass); - } else { - WinJS.Utilities.removeClass(this._element, topClass); - WinJS.Utilities.removeClass(this._element, bottomClass); - } - - // Make sure our animations are correct - this._assignAnimations(); - - // Show again if we hid ourselves for the designer - if (wasShown) { - this._show(); - } - } - }, - - /// - /// Gets or sets the layout of the AppBar contents to either "commands" or "custom". - /// - layout: { - get: function () { - // Defaults to commands if not set - return this._layout ? this._layout : appBarLayoutCommands; - }, - set: function (value) { - if (value !== appBarLayoutCommands && value !== appBarLayoutCustom) { - throw new WinJS.ErrorFromName("WinJS.UI.AppBar.BadLayout", strings.badLayout); - } - - // In designer we may have to redraw it - var wasShown = false; - if (window.Windows && Windows.ApplicationModel && Windows.ApplicationModel.DesignMode && Windows.ApplicationModel.DesignMode.designModeEnabled && !this.hidden) { - this._hide(); - wasShown = true; - } - - if (!this.hidden) { - throw new WinJS.ErrorFromName("WinJS.UI.AppBar.CannotChangeLayoutWhenVisible", strings.cannotChangeLayoutWhenVisible); - } - - // Set layout - this._layout = value; - - // Update our classes - if (this._layout === appBarLayoutCommands) { - // Add the appbar css class back - WinJS.Utilities.addClass(this._element, commandClass); - } else { - // Remove the appbar css class - WinJS.Utilities.removeClass(this._element, commandClass); - } - - // Show again if we hid ourselves for the designer - if (wasShown) { - this._show(); - } - }, - configurable: true - }, - - /// - /// Gets or sets value that indicates whether the AppBar is sticky. - /// This value is true if the AppBar is sticky; otherwise, it's false. - /// - sticky: { - get: function () { - return this._sticky; - }, - set: function (value) { - // If it doesn't change, do nothing - if (this._sticky === !!value) { - return; - } - - this._sticky = !!value; - - // Note: caller has to call .show() if they also want it visible - - // Show or hide the click eating div based on sticky value - if (!this.hidden && this._element.style.visibility === "visible") { - // May have changed sticky state for keyboard navigation - _updateAllAppBarsFirstAndFinalDiv(); - - // Ensure that the click eating div is in the correct state - if (this._sticky) { - if (!_isThereVisibleNonStickyBar()) { - thisWinUI._Overlay._hideClickEatingDivAppBar(); - } - } else { - thisWinUI._Overlay._showClickEatingDivAppBar(); - - if (this._shouldStealFocus()) { - _storePreviousFocus(document.activeElement); - this._setFocusToAppBar(); - } - } - } - } - }, - - /// - /// Sets the commands for the AppBar. This property accepts an array of AppBarCommand objects. - /// - commands: { - set: function (value) { - // Fail if trying to set when visible - if (!this.hidden) { - throw new WinJS.ErrorFromName("WinJS.UI.AppBar.CannotChangeCommandsWhenVisible", WinJS.Resources._formatString(thisWinUI._Overlay.commonstrings.cannotChangeCommandsWhenVisible, "AppBar")); - } - - // Start from scratch - if (!this._initializing) { - // AppBarCommands defined in markup don't want to be disposed during initialization. - this._disposeChildren(); - } - WinJS.Utilities.empty(this._element); - - // In case they had only one... - if (!Array.isArray(value)) { - value = [value]; - } - - // Add commands - var len = value.length; - for (var i = 0; i < len; i++) { - this._addCommand(value[i]); - } - - // Need to measure all content commands after they have been added to the AppBar to make sure we allow - // user defined CSS rules based on the ancestor of the content command to take affect. - this._needToMeasure = true; - - // In case this is called from the constructor we wait for the AppBar to get added to the DOM. - // It should be added in the synchronous block in which the constructor was called. - WinJS.Utilities.Scheduler.schedule(this._layoutCommands, WinJS.Utilities.Scheduler.Priority.idle, this, "WinJS.AppBar._layoutCommands"); - } - }, - - getCommandById: function (id) { - /// - /// - /// Retrieves the command with the specified ID from this AppBar. - /// If more than one command is found, this method returns them all. - /// - /// Id of the command to return. - /// - /// The command found, an array of commands if more than one have the same ID, or null if no command is found. - /// - /// - var commands = this.element.querySelectorAll("#" + id); - for (var count = 0; count < commands.length; count++) { - // Any elements we generated this should succeed for, - // but remove missing ones just to be safe. - commands[count] = commands[count].winControl; - if (!commands[count]) { - commands.splice(count, 1); - } - } - - if (commands.length === 1) { - return commands[0]; - } else if (commands.length === 0) { - return null; - } - - return commands; - }, - - - showCommands: function (commands) { - /// - /// - /// Show the specified commands of the AppBar. - /// - /// - /// An array of the commands to show. The array elements may be AppBarCommand objects, or the string identifiers (IDs) of commands. - /// - /// - if (!commands) { - throw new WinJS.ErrorFromName("WinJS.UI.AppBar.RequiresCommands", strings.requiresCommands); - } - - this._showCommands(commands); - }, - - - hideCommands: function (commands) { - /// - /// - /// Hides the specified commands of the AppBar. - /// - /// Required. Command or Commands to hide, either String, DOM elements, or WinJS objects. - /// - if (!commands) { - throw new WinJS.ErrorFromName("WinJS.UI.AppBar.RequiresCommands", strings.requiresCommands); - } - - this._hideCommands(commands); - }, - - - showOnlyCommands: function (commands) { - /// - /// - /// Show the specified commands, hiding all of the others in the AppBar. - /// - /// - /// An array of the commands to show. The array elements may be AppBarCommand objects, or the string identifiers (IDs) of commands. - /// - /// - if (!commands) { - throw new WinJS.ErrorFromName("WinJS.UI.AppBar.RequiresCommands", strings.requiresCommands); - } - - this._showOnlyCommands(commands); - }, - - - show: function () { - /// - /// - /// Shows the AppBar, if hidden, regardless of other state - /// - /// - // Just wrap the private one, turning off keyboard invoked flag - this._writeProfilerMark("show,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndShow(). - this._keyboardInvoked = false; - this._doNotFocus = !!this.sticky; - this._show(); - }, - - _show: function AppBar_show() { - // Don't do anything if disabled - if (this.disabled) { - return; - } - - // Make sure everything fits before showing - this._layoutCommands(); - - this._scaleAppBar(); - - // If we're covered by a keyboard we look hidden, so we may have to jump up - if (this._keyboardObscured) { - // just make us look hidden so that show() gets called. - this._fakeHide = true; - this._keyboardObscured = false; - } - - // Regardless we're going to be in a CED state - if (!this.sticky) { - // Need click-eating div to be visible ASAP. - thisWinUI._Overlay._showClickEatingDivAppBar(); - } - - // If we are already animating, just remember this for later - if (this._element.winAnimating) { - this._doNext = "show"; - return false; - } - - // We call our base _baseShow because AppBar may need to override show - // "hiding" would need to cancel. - this._baseShow(); - - // Clean up tabbing behavior by making sure first and final divs are correct after showing. - if (!this.sticky && _isThereVisibleNonStickyBar()) { - _updateAllAppBarsFirstAndFinalDiv(); - } else { - this._updateFirstAndFinalDiv(); - } - - // Check if we should steal focus - if (!this._doNotFocus && this._shouldStealFocus()) { - // Store what had focus if nothing currently is stored - if (!thisWinUI.AppBar._ElementWithFocusPreviousToAppBar) { - _storePreviousFocus(document.activeElement); - } - - this._setFocusToAppBar(); - } - }, - - hide: function () { - /// - /// - /// Hides the AppBar. - /// - /// - // Just wrap the private one - this._writeProfilerMark("hide,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndHide(). - this._hide(); - }, - - _hide: function AppBar_hide() { - // If we're covered by a keyboard we already look hidden - if (this._keyboardObscured && !this._animating) { - this._keyboardObscured = false; - this._baseEndHide(); - } else { - // We call our base "_baseHide" because AppBar may need to override hide - this._baseHide(); - } - - // Determine if there are any AppBars that are visible. - // Set the focus to the next visible AppBar. - // If there are none, set the focus to the control stored in the cache, which - // is what had focus before the AppBars were given focus. - var appBars = document.querySelectorAll("." + appBarClass); - var areOtherAppBars = false; - var areOtherNonStickyAppBars = false; - var i; - for (i = 0; i < appBars.length; i++) { - var appBarControl = appBars[i].winControl; - if (appBarControl && !appBarControl.hidden && (appBarControl !== this)) { - areOtherAppBars = true; - - if (!appBarControl.sticky) { - areOtherNonStickyAppBars = true; - break; - } - } - } - - var settingsFlyouts = document.querySelectorAll("." + settingsFlyoutClass); - var areVisibleSettingsFlyouts = false; - for (i = 0; i < settingsFlyouts.length; i++) { - var settingsFlyoutControl = settingsFlyouts[i].winControl; - if (settingsFlyoutControl && !settingsFlyoutControl.hidden) { - areVisibleSettingsFlyouts = true; - break; - } - } - - if (!areOtherNonStickyAppBars && !areVisibleSettingsFlyouts) { - // Hide the click eating div because there are no other AppBars showing - thisWinUI._Overlay._hideClickEatingDivAppBar(); - } - - var that = this; - if (!areOtherAppBars) { - // Set focus to what had focus before showing the AppBar - if (thisWinUI.AppBar._ElementWithFocusPreviousToAppBar && - (!document.activeElement || thisWinUI.AppBar._isAppBarOrChild(document.activeElement))) { - _restorePreviousFocus(); - } - // Always clear the previous focus (to prevent temporary leaking of element) - thisWinUI.AppBar._ElementWithFocusPreviousToAppBar = null; - } else if (thisWinUI.AppBar._isWithinAppBarOrChild(document.activeElement, that.element)) { - // Set focus to next visible AppBar in DOM - - var foundCurrentAppBar = false; - for (i = 0; i <= appBars.length; i++) { - if (i === appBars.length) { - i = 0; - } - - var appBar = appBars[i]; - if (appBar === this.element) { - foundCurrentAppBar = true; - } else if (foundCurrentAppBar && !appBar.winControl.hidden) { - appBar.winControl._keyboardInvoked = !!this._keyboardInvoked; - appBar.winControl._setFocusToAppBar(); - break; - } - } - } - - // If we are hiding the last lightDismiss AppBar, - // then we need to update the tabStops of the other AppBars - if (!this.sticky && !_isThereVisibleNonStickyBar()) { - _updateAllAppBarsFirstAndFinalDiv(); - } - - // Reset these values - this._keyboardInvoked = false; - this._doNotFocus = false; - }, - - _dispose: function AppBar_dispose() { - WinJS.Utilities.disposeSubTree(this.element); - this._hide(); - }, - - _disposeChildren: function AppBar_disposeChildren() { - var appBarFirstDiv = this._element.querySelectorAll("." + firstDivClass); - appBarFirstDiv = appBarFirstDiv.length >= 1 ? appBarFirstDiv[0] : null; - var appBarFinalDiv = this._element.querySelectorAll("." + finalDivClass); - appBarFinalDiv = appBarFinalDiv.length >= 1 ? appBarFinalDiv[0] : null; - - var children = this.element.children; - var length = children.length; - for (var i = 0; i < length; i++) { - var element = children[i]; - if (element === appBarFirstDiv || element === appBarFinalDiv) { - continue; - } - if (this.layout === appBarLayoutCommands) { - element.winControl.dispose(); - } else { - WinJS.Utilities.disposeSubTree(element); - } - } - }, - - _handleKeyDown: function AppBar_handleKeyDown(event) { - // On Left/Right arrow keys, moves focus to previous/next AppbarCommand element. - // On "Esc" key press hide all flyouts and light dismiss AppBars. - - // Esc closes light-dismiss AppBars in all layouts but if the user has a text box with an IME - // candidate window open, we want to skip the ESC key event since it is handled by the IME. - // When the IME handles a key it sets event.keyCode to 229 for an easy check. - if (event.key === "Esc" && event.keyCode !== 229) { - event.preventDefault(); - event.stopPropagation(); - thisWinUI._Overlay._hideAllFlyouts(); - thisWinUI.AppBar._hideLightDismissAppBars(null, true); - } - - // Commands layout only. - if (this.layout === appBarLayoutCommands && !event.altKey) { - if (event.srcElement.msMatchesSelector(".win-interactive, .win-interactive *")) { - return; //ignore left, right, home & end keys if focused element has win-interactive class. - } - var rtl = getComputedStyle(this._element).direction === "rtl"; - var leftKey = rtl ? "Right" : "Left"; - var rightKey = rtl ? "Left" : "Right"; - - if (event.key === leftKey || event.key == rightKey || event.key === "Home" || event.key === "End") { - - var focusableCommands = this._getFocusableCommandsInLogicalOrder(); - var targetCommand; - - if (focusableCommands.length) { - switch (event.key) { - case leftKey: - // Arrowing past the last command wraps back around to the first command. - var index = Math.max(-1, focusableCommands.focusedIndex - 1) + focusableCommands.length; - targetCommand = focusableCommands[index % focusableCommands.length].winControl.lastElementFocus; - break; - - case rightKey: - // Arrowing previous to the first command wraps back around to the last command. - var index = focusableCommands.focusedIndex + 1 + focusableCommands.length; - targetCommand = focusableCommands[index % focusableCommands.length].winControl.firstElementFocus; - break; - - case "Home": - var index = 0; - targetCommand = focusableCommands[index].winControl.firstElementFocus; - break; - - case "End": - var index = focusableCommands.length - 1; - targetCommand = focusableCommands[index].winControl.lastElementFocus; - break; - } - } - - if (targetCommand) { - targetCommand.focus(); - // Prevent default so that Trident doesn't resolve the keydown event on the newly focused element. - event.preventDefault(); - } - } - } - }, - - _getFocusableCommandsInLogicalOrder: function AppBar_getCommandsInLogicalOrder() { - // Function returns an array of all the contained AppBarCommands which are reachable by left/right arrows. - // - if (this.layout === appBarLayoutCommands) { - var selectionCommands = [], - globalCommands = [], - children = this._element.children, - globalCommandHasFocus = false, - focusedIndex = -1; - - var categorizeCommand = function (element, isGlobalCommand, containsFocus) { - // Helper function to categorize the element by AppBarCommand's section property. The passed in element could be the - // AppBarCommand, or the element referenced by a content AppBarCommands's firstElementFocus/lastElementFocus property. - // - if (isGlobalCommand) { - globalCommands.push(element); - if (containsFocus) { - focusedIndex = globalCommands.length - 1; - globalCommandHasFocus = true; - } - } else { - selectionCommands.push(element); - if (containsFocus) { - focusedIndex = selectionCommands.length - 1; - } - } - } - - // Separate commands into global and selection arrays. Find the current command with focus. - // Skip the first and last indices to avoid "firstDiv" and "finalDiv". - for (var i = 1, len = children.length; i < len - 1; i++) { - var element = children[i]; - if (element && element.winControl) { - var containsFocus = element.contains(document.activeElement); - // With the inclusion of content type commands, it may be possible to tab to elements in AppBarCommands that are not reachable by arrow keys. - // Regardless, when an AppBarCommand contains the element with focus, we just include the whole command so that we can determine which - // Commands are adjacent to it when looking for the next focus destination. - if (element.winControl._isFocusable() || containsFocus) { - var isGlobalCommand = (element.winControl.section === "global"); - categorizeCommand(element, isGlobalCommand, containsFocus); - } - } - } - - var focusableCommands = selectionCommands.concat(globalCommands); - focusableCommands.focusedIndex = globalCommandHasFocus ? focusedIndex + selectionCommands.length : focusedIndex; - return focusableCommands; - } - }, - - _assignAnimations: function AppBar_assignAnimations() { - // Make sure the animations are correct for our current placement - if (this._placement === appBarPlacementTop || this._placement === appBarPlacementBottom) { - // Top or Bottom - this._currentAnimateIn = this._animateSlideIn; - this._currentAnimateOut = this._animateSlideOut; - } else { - // Default for in the middle of nowhere - this._currentAnimateIn = this._baseAnimateIn; - this._currentAnimateOut = this._baseAnimateOut; - } - }, - - // AppBar animations - _animateSlideIn: function AppBar_animateSlideIn() { - var where, - height = this._element.offsetHeight; - // Get top/bottoms - this._checkPosition(); - // Get animation direction and clear other value - if (this._placement === appBarPlacementTop) { - // Top Bar - where = { top: "-" + height + "px", left: "0px" }; - this._element.style.bottom = "auto"; - } else { - // Bottom Bar - where = { top: height + "px", left: "0px" }; - this._element.style.top = "auto"; - } - - this._element.style.opacity = 1; - this._element.style.visibility = "visible"; - return WinJS.UI.Animation.showEdgeUI(this._element, where, { mechanism: "transition" }); - }, - - _animateSlideOut: function AppBar_animateSlideOut() { - var where, - height = this._element.offsetHeight; - if (this._placement === appBarPlacementTop) { - // Top Bar - where = { top: "-" + height + "px", left: "0px" }; - // Adjust for scrolling or soft keyboard positioning - this._element.style.top = (this._getTopOfVisualViewport()) + "px"; - } else { - // Bottom Bar - where = { top: height + "px", left: "0px" }; - // Adjust for scrolling or soft keyboard positioning - this._element.style.bottom = (this._getAdjustedBottom()) + "px"; - } - - return WinJS.UI.Animation.hideEdgeUI(this._element, where, { mechanism: "transition" }); - }, - - _isABottomAppBarInTheProcessOfShowing: function AppBar_isABottomAppBarInTheProcessOfShowing() { - var appbars = document.querySelectorAll("." + appBarClass + "." + bottomClass); - for (var i = 0; i < appbars.length; i++) { - if (appbars[i].winAnimating === "showing") { - return true; - } - } - - return false; - }, - - // Returns true if - // 1) This is a bottom appbar - // 2) No appbar has focus and a bottom appbar is not in the process of showing - // 3) What currently has focus is neither a bottom appbar nor a top appbar - // AND a bottom appbar is not in the process of showing. - // Otherwise Returns false - _shouldStealFocus: function AppBar_shouldStealFocus() { - var activeElementAppBar = thisWinUI.AppBar._isAppBarOrChild(document.activeElement); - if (this._element === activeElementAppBar) { - // This appbar already has focus and we don't want to move focus - // from where it currently is in this appbar. - return false; - } - if (this._placement === appBarPlacementBottom) { - // This is a bottom appbar - return true; - } - - var isBottomAppBarShowing = this._isABottomAppBarInTheProcessOfShowing(); - if (!activeElementAppBar) { - // Currently no appbar has focus. - // Return true if a bottom appbar is not in the process of showing. - return !isBottomAppBarShowing; - } - if (!activeElementAppBar.winControl) { - // This should not happen, but if it does we want to make sure - // that an AppBar ends up with focus. - return true; - } - if ((activeElementAppBar.winControl._placement !== appBarPlacementBottom) - && (activeElementAppBar.winControl._placement !== appBarPlacementTop) - && !isBottomAppBarShowing) { - // What currently has focus is neither a bottom appbar nor a top appbar - // -and- - // a bottom appbar is not in the process of showing. - return true; - } - return false - }, - - // Set focus to the passed in AppBar - _setFocusToAppBar: function AppBar_setFocusToAppBar() { - if (this._focusOnFirstFocusableElement()) { - // Prevent what is gaining focus from showing that it has focus, - // but only in the non-keyboard scenario. - if (!this._keyboardInvoked) { - thisWinUI._Overlay._addHideFocusClass(document.activeElement); - } - } else { - // No first element, set it to appbar itself - thisWinUI._Overlay._trySetActive(this._element); - } - }, - - _contentChanged: function AppBar_contentChanged() { - this._updateCommandsWidth(); - this._scaleAppBar(); - }, - - _scaleAppBar: function AppBar_scaleAppBar() { - // For commands layout AppBars only. If the total width of all AppBarCommands is greater than the - // width of the AppBar, add the win-reduced class to the AppBar element. - - if (this.layout === appBarLayoutCommands) { - // Measure AppBar's contents width, AppBar offsetWidth and AppBar padding: - var widthOfVisibleContent = this._getCommandsWidth(); - if (this._appBarTotalKnownWidth !== +this._appBarTotalKnownWidth) { - this._appBarTotalKnownWidth = this._scaleAppBarHelper(); - } - - if (widthOfVisibleContent <= this._appBarTotalKnownWidth) { - // Full size commands - WinJS.Utilities.removeClass(this._element, reducedClass); - } - else { - // Reduced size commands - WinJS.Utilities.addClass(this._element, reducedClass); - } - } - }, - - _scaleAppBarHelper: function AppBar_scaleAppBarHelper() { - // This exists as a single line function so that unit tests can - // overwrite it since they can't resize the WWA window. - return document.documentElement.clientWidth; - }, - - _updateCommandsWidth: function AppBar_updateCommandsWidth(commandSubSet) { - // Whenever Commands are hidden/shown in the Commands layout AppBar, this function is called - // to update the cached width measurement of all visible AppBarCommands in the AppBar. - if (this.layout === appBarLayoutCommands) { - var buttonsCount = 0; - var separatorsCount = 0; - var command; - var commands = commandSubSet; - - this._widthOfAllCommands = 0; - if (!commands) { - // Crawl the AppBar's inner HTML for the commands. - commands = this._getVisibleCommands(); - } - this._widthOfAllCommands = this._getCommandsWidth(commands); - } - }, - - _getCommandsWidth: function AppBar_getCommandsWidth(commandSubSet) { - if (!commandSubSet) { - // Return the cached width of all previously visible commands in the AppBar. - return this._widthOfAllCommands; - } else { - // Return the width of the specified subset. - var separatorsCount = 0; - var buttonsCount = 0; - var widthOfCommandSubSet = 0; - var command; - for (var i = 0, len = commandSubSet.length; i < len; i++) { - command = commandSubSet[i].winControl || commandSubSet[i]; - if (command._type === typeSeparator) { - separatorsCount++ - } else if (command._type !== typeContent) { - // button, toggle, and flyout types all have the same width. - buttonsCount++; - } else { - widthOfCommandSubSet += command._fullSizeWidth; - } - } - } - return widthOfCommandSubSet += (separatorsCount * separatorWidth) + (buttonsCount * buttonWidth); - }, - - _beginAnimateCommands: function AppBar_beginAnimateCommands(showCommands, hideCommands, otherVisibleCommands) { - // The parameters are 3 mutually exclusive arrays of win-command elements contained in this Overlay. - // 1) showCommands[]: All of the HIDDEN win-command elements that ARE scheduled to show. - // 2) hideCommands[]: All of the VISIBLE win-command elements that ARE scheduled to hide. - // 3) otherVisibleCommands[]: All VISIBLE win-command elements that ARE NOT scheduled to hide. - if (this.layout === appBarLayoutCommands) { - this._scaleCommandsAfterAnimations = false; - // Update our command counts now, to what they will be after we complete the animations. - var visibleCommandsAfterAnimations = otherVisibleCommands.concat(showCommands); - this._updateCommandsWidth(visibleCommandsAfterAnimations) - var changeInWidth = this._getCommandsWidth(showCommands) - this._getCommandsWidth(hideCommands); - if (changeInWidth > 0) { - // Width of contents is going to increase. If there won't be enough room to fit them all on a single row, - // reduce size of commands before the new content appears. - this._scaleAppBar(); - } else if (changeInWidth < 0) { - // Width of contents is going to decrease. Once animations are complete, check if - // there is enough available space to make the remaining commands full size. - this._scaleCommandsAfterAnimations = true; - } - } - }, - - _endAnimateCommands: function AppBar_endAnimateCommands() { - if (this._scaleCommandsAfterAnimations) { - this._scaleAppBar(); - } - }, - - _addCommand: function AppBar_addCommand(command) { - if (!command) { - throw new WinJS.ErrorFromName("WinJS.UI.AppBar.NullCommand", strings.nullCommand); - } - // See if it's a command already - if (!command._element) { - // Not a command, so assume it is options for the command's constructor. - command = new WinJS.UI.AppBarCommand(null, command); - } - // If we were attached somewhere else, detach us - if (command._element.parentElement) { - command._element.parentElement.removeChild(command._element); - } - // Reattach us - this._element.appendChild(command._element); - }, - - _measureContentCommands: function AppBar_measureContentCommands() { - // AppBar measures the width of content commands when they are first added - // and then caches that value to avoid additional layouts in the future. - - // Can't measure unless We're in the document body - if (document.body.contains(this.element)) { - this._needToMeasure = false; - - // Remove the reducedClass from AppBar to ensure fullsize measurements - var hadReducedClass = WinJS.Utilities.hasClass(this.element, reducedClass); - WinJS.Utilities.removeClass(this._element, reducedClass); - - // Make sure AppBar and children have width dimensions. - var prevAppBarDisplay = this.element.style.display; - var prevCommandDisplay; - this.element.style.display = ""; - - var commandElements = this._element.children; - var element; - for (var i = 0, len = commandElements.length; i < len; i++) { - element = commandElements[i]; - if (element.winControl && element.winControl._type === typeContent) { - // Make sure command has width dimensions before we measure. - prevCommandDisplay = element.style.display; - element.style.display = ""; - element.winControl._fullSizeWidth = WinJS.Utilities.getTotalWidth(element) || 0; - element.style.display = prevCommandDisplay; - } - } - - // Restore state to AppBar. - this.element.display = prevAppBarDisplay; - if (hadReducedClass) { - WinJS.Utilities.addClass(this._element, reducedClass); - } - } - }, - - // Performs any pending measurements on "content" type AppBarCommands and scales the AppBar to fit all AppBarCommand types accordingly. - _layoutCommands: function AppBar_layoutCommands() { - if (this._needToMeasure && this.layout === appBarLayoutCommands) { - this._measureContentCommands(); - this._contentChanged(); - } - }, - - // Get the top of the top appbars, this is always 0 because appbar uses - // -ms-device-fixed positioning. - _getTopOfVisualViewport: function AppBar_getTopOfVisualViewPort() { - return 0; - }, - - // Get the bottom of the bottom appbars, Bottom is just 0, if there's no IHM. - // When the IHM appears, the default behavior is to resize the view. If a resize - // happens, we can rely on -ms-device-fixed positioning and leave the bottom - // at 0. However if resize doesn't happen, then the keyboard obscures the appbar - // and we will need to adjust the bottom of the appbar by distance of the keyboard. - _getAdjustedBottom: function AppBar_getAdjustedBottom() { - // Need the distance the IHM moved as well. - return thisWinUI._Overlay._keyboardInfo._visibleDocBottomOffset; - }, - - _showingKeyboard: function AppBar_showingKeyboard(event) { - // Remember keyboard showing state. - this._keyboardObscured = false; - this._keyboardHiding = false; - - // If we're already moved, then ignore the whole thing - if (thisWinUI._Overlay._keyboardInfo._visible && this._alreadyInPlace()) { - return; - } - - this._keyboardShowing = true; - // If focus is in the appbar, don't cause scrolling. - if (!this.hidden && this._element.contains(document.activeElement)) { - event.ensuredFocusedElementInView = true; - } - - // Check if appbar moves or is obscured - if (!this.hidden && this._placement !== appBarPlacementTop && thisWinUI._Overlay._isFlyoutVisible()) { - // Remember that we're obscured - this._keyboardObscured = true; - } else { - // If not obscured, tag as showing and set timeout to restore us. - this._scrollHappened = false; - } - - // Also set timeout regardless, so we can clean up our _keyboardShowing flag. - var that = this; - setTimeout(function (e) { that._checkKeyboardTimer(e); }, thisWinUI._Overlay._keyboardInfo._animationShowLength + thisWinUI._Overlay._scrollTimeout); - }, - - _hidingKeyboard: function AppBar_hidingKeyboard(event) { - // We won't be obscured - this._keyboardObscured = false; - this._keyboardShowing = false; - this._keyboardHiding = true; - - // We'll either just reveal the current space or resize the window - if (!thisWinUI._Overlay._keyboardInfo._isResized) { - // If we're visible or only fake hiding under keyboard, or already animating, - // then snap us to our final position. - if (!this.hidden || this._fakeHide || this._animating) { - // Not resized, update our final position immediately - this._checkScrollPosition(); - this._element.style.display = ""; - this._fakeHide = false; - } - this._keyboardHiding = false; - } - // Else resize should clear keyboardHiding. - }, - - _resize: function AppBar_resize(event) { - // If we're hidden by the keyboard, then hide bottom appbar so it doesn't pop up twice when it scrolls - if (this._keyboardShowing) { - // Top is allowed to scroll off the top, but we don't want bottom to peek up when - // scrolled into view since we'll show it ourselves and don't want a stutter effect. - if (!this.hidden) { - if (this._placement !== appBarPlacementTop && !this._keyboardObscured) { - // If viewport doesn't match window, need to vanish momentarily so it doesn't scroll into view, - // however we don't want to toggle the visibility="hidden" hidden flag. - this._element.style.display = "none"; - } - } - // else if we're top we stay, and if there's a flyout, stay obscured by the keyboard. - } else if (this._keyboardHiding) { - this._keyboardHiding = false; - if (!this.hidden || this._animating) { - // Snap to final position - this._checkScrollPosition(); - this._element.style.display = ""; - this._fakeHide = false; - } - } - - // Check for horizontal window resizes. - this._appBarTotalKnownWidth = null; - if (!this.hidden) { - this._scaleAppBar(); - } - }, - - _checkKeyboardTimer: function AppBar_checkKeyboardTimer() { - if (!this._scrollHappened) { - this._mayEdgeBackIn(); - } - }, - - _manipulationChanged: function AppBar_manipulationChanged(event) { - // See if we're at the not manipulating state, and we had a scroll happen, - // which is implicitly after the keyboard animated. - if (event.currentState === 0 && this._scrollHappened) { - this._mayEdgeBackIn(); - } - }, - - _mayEdgeBackIn: function AppBar_mayEdgeBackIn(event) { - // May need to react to IHM being resized event - if (this._keyboardShowing) { - // If not top appbar or viewport isn't still at top, then need to show again - this._keyboardShowing = false; - // If obscured (flyout showing), don't change. - // If hidden, may be because _fakeHide was set in _resize. - // If bottom we have to move, or if top scrolled off screen. - if (!this._keyboardObscured && (!this.hidden || this._fakeHide) && - (this._placement !== appBarPlacementTop || thisWinUI._Overlay._keyboardInfo._visibleDocTop !== 0)) { - this._doNotFocus = true; - this._fakeHide = true; - this._show(); - } else { - // Ensure any animation dropped during the showing keyboard are caught up. - this._checkDoNext(); - } - } - this._scrollHappened = false; - }, - - // _checkPosition repositions the AppBar when the soft keyboard shows up - _checkPosition: function AppBar_checkPosition() { - // Bottom's the only one needing movement - if (this._placement === appBarPlacementBottom) { - this._element.style.bottom = this._getAdjustedBottom() + "px"; - } else if (this._placement === appBarPlacementTop) { - this._element.style.top = this._getTopOfVisualViewport() + "px"; - } - // else we don't touch custom positions - }, - - _checkScrollPosition: function AppBar_checkScrollPosition(event) { - // If keyboard's animating, then remember we may come in - if (this._keyboardShowing) { - // Tag that it's OK to edge back in. - this._scrollHappened = true; - return; - } - - // We only need to update if we're visible - if (!this.hidden || this._animating) { - this._checkPosition(); - // Ensure any animation dropped during the showing keyboard are caught up. - this._checkDoNext(); - } - }, - - _alreadyInPlace: function AppBar_alreadyInPlace() { - // See if we're already where we're supposed to be. - if (this._placement === appBarPlacementBottom) { - if (parseInt(this._element.style.bottom) === this._getAdjustedBottom()) { - return true; - } - } else if (this._placement === appBarPlacementTop) { - if (parseInt(this._element.style.top) === this._getTopOfVisualViewport()) { - return true; - } - } - // else we don't understand custom positioning - return false; - }, - - // If there is a visible non-sticky AppBar then it sets the firstDiv tabIndex to - // the minimum tabIndex found in the AppBars and finalDiv to the max found. - // Otherwise sets their tabIndex to -1 so they are not tab stops. - _updateFirstAndFinalDiv: function AppBar_updateFirstAndFinalDiv() { - var appBarFirstDiv = this._element.querySelectorAll("." + firstDivClass); - appBarFirstDiv = appBarFirstDiv.length >= 1 ? appBarFirstDiv[0] : null; - - var appBarFinalDiv = this._element.querySelectorAll("." + finalDivClass); - appBarFinalDiv = appBarFinalDiv.length >= 1 ? appBarFinalDiv[0] : null; - - // Remove the firstDiv & finalDiv if they are not at the appropriate locations - if (appBarFirstDiv && (this._element.children[0] != appBarFirstDiv)) { - appBarFirstDiv.parentNode.removeChild(appBarFirstDiv); - appBarFirstDiv = null; - } - if (appBarFinalDiv && (this._element.children[this._element.children.length - 1] != appBarFinalDiv)) { - appBarFinalDiv.parentNode.removeChild(appBarFinalDiv); - appBarFinalDiv = null; - } - - // Create and add the firstDiv & finalDiv if they don't already exist - if (!appBarFirstDiv) { - // Add a firstDiv that will be the first child of the appBar. - // On focus set focus to the previous appBar. - // The div should only be focusable if there are visible non-sticky AppBars. - appBarFirstDiv = document.createElement("div"); - // display: inline is needed so that the div doesn't take up space and cause the page to scroll on focus - appBarFirstDiv.style.display = "inline"; - appBarFirstDiv.className = firstDivClass; - appBarFirstDiv.tabIndex = -1; - appBarFirstDiv.setAttribute("aria-hidden", "true"); - appBarFirstDiv.addEventListener("focus", _setFocusToPreviousAppBar, true); - this._element.insertAdjacentElement("AfterBegin", appBarFirstDiv); - } - if (!appBarFinalDiv) { - // Add a finalDiv that will be the last child of the appBar. - // On focus set focus to the next appBar. - // The div should only be focusable if there are visible non-sticky AppBars. - appBarFinalDiv = document.createElement("div"); - // display: inline is needed so that the div doesn't take up space and cause the page to scroll on focus - appBarFinalDiv.style.display = "inline"; - appBarFinalDiv.className = finalDivClass; - appBarFinalDiv.tabIndex = -1; - appBarFinalDiv.setAttribute("aria-hidden", "true"); - appBarFinalDiv.addEventListener("focus", _setFocusToNextAppBar, true); - this._element.appendChild(appBarFinalDiv); - } - - // Update the tabIndex of the firstDiv & finalDiv - if (_isThereVisibleNonStickyBar()) { - var elms = this._element.getElementsByTagName("*"); - - if (appBarFirstDiv) { - appBarFirstDiv.tabIndex = WinJS.Utilities._getLowestTabIndexInList(elms); - } - if (appBarFinalDiv) { - appBarFinalDiv.tabIndex = WinJS.Utilities._getHighestTabIndexInList(elms); - } - } else { - if (appBarFirstDiv) { - appBarFirstDiv.tabIndex = -1; - } - if (appBarFinalDiv) { - appBarFinalDiv.tabIndex = -1; - } - } - }, - - _writeProfilerMark: function AppBar_writeProfilerMark(text) { - msWriteProfilerMark("WinJS.UI.AppBar:" + this._id + ":" + text); - } - }); - - // Statics - AppBar._ElementWithFocusPreviousToAppBar = null; - - // Returns appbar element (or CED/sentinal) if the element or what had focus before the element (if a Flyout) is either: - // 1) an AppBar, - // 2) OR in the subtree of an AppBar, - // 3) OR an AppBar click eating div. - // Returns null otherwise. - AppBar._isAppBarOrChild = function (element) { - // If it's null, we can't do this - if (!element) { - return null; - } - - // click eating divs and sentinals should not have children - if (WinJS.Utilities.hasClass(element, thisWinUI._Overlay._clickEatingAppBarClass) || - WinJS.Utilities.hasClass(element, thisWinUI._Overlay._clickEatingFlyoutClass) || - WinJS.Utilities.hasClass(element, firstDivClass) || - WinJS.Utilities.hasClass(element, finalDivClass)) { - return element; - } - - while (element && element !== document) { - if (WinJS.Utilities.hasClass(element, appBarClass)) { - return element; - } - if (WinJS.Utilities.hasClass(element, "win-flyout") - && element != element.winControl._previousFocus) { - var flyoutControl = element.winControl; - // If _previousFocus was in a light dismissable AppBar, then this Flyout is considered of an extension of it and that AppBar will not close. - // Hook up a 'focusout' listener to this Flyout element to make sure that light dismiss AppBars close if focus moves anywhere other than back to an AppBar. - var appBarElement = thisWinUI.AppBar._isAppBarOrChild(flyoutControl._previousFocus); - if (appBarElement) { - flyoutControl.element.addEventListener('focusout', function focusOut(event) { - // Hides any open AppBars if the new activeElement is not in an AppBar. - _hideIfAllAppBarsLostFocus(); - flyoutControl.element.removeEventListener('focusout', focusOut, false); - }, false); - } - return appBarElement; - } - - element = element.parentNode; - } - - return null; - }; - - // Returns true if the element or what had focus before the element (if a Flyout) is either: - // 1) the appBar or subtree - // 2) OR in a flyout spawned by the appBar - // Returns false otherwise. - AppBar._isWithinAppBarOrChild = function (element, appBar) { - if (!element || !appBar) { - return false; - } - if (appBar.contains(element)) { - return true; - } - var flyout = thisWinUI._Overlay._getParentControlUsingClassName(element, "win-flyout"); - return (flyout && appBar.contains(flyout._previousFocus)); - }; - - // Overlay class calls this for global light dismiss events - AppBar._hideLightDismissAppBars = function (event, keyboardInvoked) { - var elements = document.querySelectorAll("." + appBarClass); - var len = elements.length; - var AppBars = []; - for (var i = 0; i < len; i++) { - var AppBar = elements[i].winControl; - if (AppBar && !AppBar.sticky && !AppBar.hidden) { - AppBars.push(AppBar); - } - } - - _hideAllBars(AppBars, keyboardInvoked); - }; - - var appBarSynchronizationPromise = WinJS.Promise.as(); - - // Callback for AppBar Edgy Event Command - AppBar._toggleAppBarEdgy = function (keyboardInvoked) { - var bars = _getDynamicBarsForEdgy(); - - // If they're all visible hide them, otherwise show them all - if (bars._visible && !bars._hidden) { - appBarSynchronizationPromise = appBarSynchronizationPromise.then(function () { - return _hideAllBars(bars, keyboardInvoked); - }); - return "hiding"; - } else { - appBarSynchronizationPromise = appBarSynchronizationPromise.then(function () { - return _showAllBars(bars, keyboardInvoked); - }); - return "showing"; - } - }; - - return AppBar; - }) - }); - -})(WinJS); - - -/// appbar,Flyout,Flyouts,Statics -(function flyoutInit(WinJS) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// - /// Displays lightweight UI that is either informational, or requires user interaction. - /// Unlike a dialog, a Flyout can be light dismissed by clicking or tapping off of it. - /// - /// - /// - /// Flyout - /// - /// - /// ]]> - /// Raised just before showing a flyout. - /// Raised immediately after a flyout is fully shown. - /// Raised just before hiding a flyout. - /// Raised immediately after a flyout is fully hidden. - /// The Flyout control itself. - /// - /// - /// - Flyout: WinJS.Namespace._lazy(function () { - var thisWinUI = WinJS.UI; - - // Class Names - var appBarCommandClass = "win-command"; - var flyoutClass = "win-flyout"; - var flyoutLightClass = "win-ui-light"; - var menuClass = "win-menu"; - var scrollsClass = "win-scrolls"; - - var finalDivClass = "win-finaldiv"; - var firstDivClass = "win-firstdiv"; - - function getDimension(element, property) { - return parseFloat(element, window.getComputedStyle(element, null)[property]); - } - - var strings = { - get ariaLabel() { return WinJS.Resources._getWinJSString("ui/flyoutAriaLabel").value; }, - get noAnchor() { return WinJS.Resources._getWinJSString("ui/noAnchor").value; }, - get badPlacement() { return WinJS.Resources._getWinJSString("ui/badPlacement").value; }, - get badAlignment() { return WinJS.Resources._getWinJSString("ui/badAlignment").value; } - }; - - var Flyout = WinJS.Class.derive(WinJS.UI._Overlay, function Flyout_ctor(element, options) { - /// - /// - /// Creates a new Flyout control. - /// - /// - /// The DOM element that hosts the control. - /// - /// - /// The set of properties and values to apply to the new Flyout. - /// - /// The new Flyout control. - /// - /// - - // Simplify checking later - options = options || {}; - - // Make sure there's an input element - this._element = element || document.createElement("div"); - this._id = this._element.id || this._element.uniqueID; - this._writeProfilerMark("constructor,StartTM"); - - this._baseFlyoutConstructor(this._element, options); - - var _elms = this._element.getElementsByTagName("*"); - var firstDiv = this._addFirstDiv(); - firstDiv.tabIndex = WinJS.Utilities._getLowestTabIndexInList(_elms); - var finalDiv = this._addFinalDiv(); - finalDiv.tabIndex = WinJS.Utilities._getHighestTabIndexInList(_elms); - - // Handle "esc" & "tab" key presses - this._element.addEventListener("keydown", this._handleKeyDown, true); - - this._writeProfilerMark("constructor,StopTM"); - return this; - }, { - _lastMaxHeight: null, - - _baseFlyoutConstructor: function Flyout_baseFlyoutContstructor(element, options) { - // Flyout constructor - - // We have some options with defaults - this._placement = "auto"; - this._alignment = "center"; - - // Call the base overlay constructor helper - this._baseOverlayConstructor(element, options); - - // Make a click eating div - thisWinUI._Overlay._createClickEatingDivFlyout(); - - // Start flyouts hidden - this._element.style.visibilty = "hidden"; - this._element.style.display = "none"; - - // Attach our css class - WinJS.Utilities.addClass(this._element, flyoutClass); - WinJS.Utilities.addClass(this._element, flyoutLightClass); - - // Make sure we have an ARIA role - var role = this._element.getAttribute("role"); - if (role === null || role === "" || role === undefined) { - if (WinJS.Utilities.hasClass(this._element, menuClass)) { - this._element.setAttribute("role", "menu"); - } else { - this._element.setAttribute("role", "dialog"); - } - } - var label = this._element.getAttribute("aria-label"); - if (label === null || label === "" || label === undefined) { - this._element.setAttribute("aria-label", strings.ariaLabel); - } - - // Base animation is popIn, but our flyout has different arguments - this._currentAnimateIn = this._flyoutAnimateIn; - this._currentAnimateOut = this._flyoutAnimateOut; - - // Make sure _Overlay event handlers are hooked up - this._addOverlayEventHandlers(true); - }, - - /// - /// Gets or sets the Flyout control's anchor. The anchor element is the HTML element which the Flyout originates from and is positioned relative to. - /// (This setting can be overridden when you call the show method.) - /// - /// - anchor: { - get: function () { - return this._anchor; - }, - set: function (value) { - this._anchor = value; - } - }, - - /// - /// Gets or sets the default placement of this Flyout. (This setting can be overridden when you call the show method.) - /// - /// - placement: { - get: function () { - return this._placement; - }, - set: function (value) { - if (value !== "top" && value !== "bottom" && value !== "left" && value !== "right" && value !== "auto") { - // Not a legal placement value - throw new WinJS.ErrorFromName("WinJS.UI.Flyout.BadPlacement", strings.badPlacement); - } - this._placement = value; - } - }, - - /// - /// Gets or sets the default alignment for this Flyout. (This setting can be overridden when you call the show method.) - /// - /// - alignment: { - get: function () { - return this._alignment; - }, - set: function (value) { - if (value !== "right" && value !== "left" && value !== "center") { - // Not a legal alignment value - throw new WinJS.ErrorFromName("WinJS.UI.Flyout.BadAlignment", strings.badAlignment); - } - this._alignment = value; - } - }, - - _dispose: function Flyout_dispose() { - WinJS.Utilities.disposeSubTree(this.element); - this._hide(); - this.anchor = null; - }, - - show: function (anchor, placement, alignment) { - /// - /// - /// Shows the Flyout, if hidden, regardless of other states. - /// - /// - /// The DOM element, or ID of a DOM element to anchor the Flyout, overriding the anchor property for this time only. - /// - /// - /// The placement of the Flyout to the anchor: 'auto' (default), 'top', 'bottom', 'left', or 'right'. This parameter overrides the placement property for this show only. - /// - /// - /// For 'top' or 'bottom' placement, the alignment of the Flyout to the anchor's edge: 'center' (default), 'left', or 'right'. - /// This parameter overrides the alignment property for this show only. - /// - /// - /// - this._writeProfilerMark("show,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndShow(). - // Just call private version to make appbar flags happy - this._show(anchor, placement, alignment); - }, - - _show: function Flyout_show(anchor, placement, alignment) { - this._baseFlyoutShow(anchor, placement, alignment); - }, - - hide: function () { - /// - /// - /// Hides the Flyout, if visible, regardless of other states. - /// - /// - /// - // Just wrap the private one, turning off keyboard invoked flag - this._writeProfilerMark("hide,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndHide(). - this._keyboardInvoked = false; - this._hide(); - }, - - _hide: function Flyout_hide() { - if (this._baseHide()) { - // Return focus if this or the flyout CED has focus - var active = document.activeElement; - if (this._previousFocus - && active - && (this._element.contains(active) - || WinJS.Utilities.hasClass(active, thisWinUI._Overlay._clickEatingFlyoutClass)) - && this._previousFocus.focus !== undefined) { - - // _isAppBarOrChild may return a CED or sentinal - var appBar = thisWinUI.AppBar._isAppBarOrChild(this._previousFocus); - if (!appBar || (appBar.winControl && !appBar.winControl.hidden && !appBar.winAnimating)) { - // Don't move focus back to a appBar that is hidden - // We cannot rely on element.style.visibility because it will be visible while animating - var role = this._previousFocus.getAttribute("role"); - var fHideRole = thisWinUI._Overlay._keyboardInfo._visible && !this._keyboardWasUp; - if (fHideRole) { - // Convince IHM to dismiss because it only came up after the flyout was up. - // Change aria role and back to get IHM to dismiss. - this._previousFocus.setAttribute("role", ""); - } - - if (this._keyboardInvoked) { - this._previousFocus.focus(); - } else { - thisWinUI._Overlay._trySetActive(this._previousFocus); - } - active = document.activeElement; - - if (fHideRole) { - // Restore the role so that css is applied correctly - var previousFocus = this._previousFocus; - if (previousFocus) { - setImmediate(function () { - previousFocus.setAttribute("role", role); - }); - } - } - } - - // If the anchor gained focus we want to hide the focus in the non-keyboarding scenario - if (!this._keyboardInvoked && (this._previousFocus === active) && appBar && active) { - thisWinUI._Overlay._addHideFocusClass(active); - } - } - - this._previousFocus = null; - - // Need click-eating div to be hidden if there are no other visible flyouts - if (!this._isThereVisibleFlyout()) { - thisWinUI._Overlay._hideClickEatingDivFlyout(); - } - } - }, - - _baseFlyoutShow: function Flyout_baseFlyoutShow(anchor, placement, alignment) { - // Don't do anything if disabled - if (this.disabled) { - return; - } - // Pick up defaults - if (!anchor) { - anchor = this._anchor; - } - if (!placement) { - placement = this._placement; - } - if (!alignment) { - alignment = this._alignment; - } - - // Dereference the anchor if necessary - if (typeof anchor === "string") { - anchor = document.getElementById(anchor); - } else if (anchor && anchor.element) { - anchor = anchor.element; - } - - // We expect an anchor - if (!anchor) { - // If we have _nextLeft, etc., then we were continuing an old animation, so that's OK - if (!this._retryLast) { - throw new WinJS.ErrorFromName("WinJS.UI.Flyout.NoAnchor", strings.noAnchor); - } - // Last call was incomplete, so use the previous _current values. - this._retryLast = null; - } else { - // Remember the anchor so that if we lose focus we can go back - this._currentAnchor = anchor; - // Remember current values - this._currentPlacement = placement; - this._currentAlignment = alignment; - } - - // Need click-eating div to be visible, no matter what - if (!this._sticky) { - thisWinUI._Overlay._showClickEatingDivFlyout(); - } - - // If we're animating (eg baseShow is going to fail), then don't mess up our current state. - // Queue us up to wait for current animation to finish first. - if (this._element.winAnimating) { - this._doNext = "show"; - this._retryLast = true; - return; - } - - // We call our base _baseShow to handle the actual animation - if (this._baseShow()) { - // (_baseShow shouldn't ever fail because we tested winAnimating above). - if (!WinJS.Utilities.hasClass(this.element, "win-menu")) { - // Verify that the firstDiv is in the correct location. - // Move it to the correct location or add it if not. - var _elms = this._element.getElementsByTagName("*"); - var firstDiv = this.element.querySelectorAll(".win-first"); - if (this.element.children.length && !WinJS.Utilities.hasClass(this.element.children[0], firstDivClass)) { - if (firstDiv && firstDiv.length > 0) { - firstDiv.item(0).parentNode.removeChild(firstDiv.item(0)); - } - - firstDiv = this._addFirstDiv(); - } - firstDiv.tabIndex = WinJS.Utilities._getLowestTabIndexInList(_elms); - - // Verify that the finalDiv is in the correct location. - // Move it to the correct location or add it if not. - var finalDiv = this.element.querySelectorAll(".win-final"); - if (!WinJS.Utilities.hasClass(this.element.children[this.element.children.length - 1], finalDivClass)) { - if (finalDiv && finalDiv.length > 0) { - finalDiv.item(0).parentNode.removeChild(finalDiv.item(0)); - } - - finalDiv = this._addFinalDiv(); - } - finalDiv.tabIndex = WinJS.Utilities._getHighestTabIndexInList(_elms); - } - - // Hide all other flyouts - this._hideAllOtherFlyouts(this); - - // Store what had focus before showing the Flyout. - // This must happen after we hide all other flyouts so that we store the correct element. - this._previousFocus = document.activeElement; - } - }, - - _endShow: function Flyout_endShow() { - // Remember if the IHM was up since we may need to hide it when the flyout hides. - // This check needs to happen after the IHM has a chance to hide itself after we force hide - // all other visible Flyouts. - this._keyboardWasUp = thisWinUI._Overlay._keyboardInfo._visible; - - if (!WinJS.Utilities.hasClass(this.element, "win-menu")) { - // Put focus on the first child in the Flyout - this._focusOnFirstFocusableElementOrThis(); - - // Prevent what is gaining focus from showing that it has focus - thisWinUI._Overlay._addHideFocusClass(document.activeElement); - } else { - // Make sure the menu has focus, but don't show a focus rect - thisWinUI._Overlay._trySetActive(this._element); - } - }, - - // Find our new flyout position. - _findPosition: function Flyout_findPosition() { - this._nextHeight = null; - this._keyboardMovedUs = false; - this._hasScrolls = false; - this._keyboardSquishedUs = 0; - - // Make sure menu toggles behave - if (this._checkToggle) { - this._checkToggle(); - } - - // Update margins for this alignment and remove old scrolling - this._updateAdjustments(this._currentAlignment); - - // Set up the new position, and prep the offset for showPopup - this._getTopLeft(); - // Panning top offset is calculated top - this._scrollTop = this._nextTop; - - // Adjust position - if (this._nextTop < 0) { - // Need to attach to bottom - this._element.style.bottom = "0px"; - this._element.style.top = "auto"; - } else { - // Normal, attach to top - this._element.style.top = this._nextTop + "px"; - this._element.style.bottom = "auto"; - } - if (this._nextLeft < 0) { - // Overran right, attach to right - this._element.style.right = "0px"; - this._element.style.left = "auto"; - } else { - // Normal, attach to left - this._element.style.left = this._nextLeft + "px"; - this._element.style.right = "auto"; - } - - // Adjust height/scrollbar - if (this._nextHeight !== null) { - WinJS.Utilities.addClass(this._element, scrollsClass); - this._lastMaxHeight = this._element.style.maxHeight; - this._element.style.maxHeight = this._nextHeight + "px"; - this._nextBottom = this._nextTop + this._nextHeight; - this._hasScrolls = true; - } - - // May need to adjust if the IHM is showing. - if (thisWinUI._Overlay._keyboardInfo._visible) { - // Use keyboard logic - this._checkKeyboardFit(); - - if (this._keyboardMovedUs) { - this._adjustForKeyboard(); - } - } - }, - - // This determines our positioning. We have 5 modes, the 1st four are explicit, the last is automatic: - // * top - position explicitly on the top of the anchor, shrinking and adding scrollbar as needed. - // * bottom - position explicitly below the anchor, shrinking and adding scrollbar as needed. - // * left - position left of the anchor, shrinking and adding a vertical scrollbar as needed. - // * right - position right of the anchor, shrinking and adding a vertical scroolbar as needed. - // * auto - Automatic placement. - // Auto tests the height of the anchor and the flyout. For consistency in orientation, we imagine - // that the anchor is placed in the vertical center of the display. If the flyout would fit above - // that centered anchor, then we will place the flyout vertically in relation to the anchor, otherwise - // placement will be horizontal. - // Vertical auto placement will be positioned on top of the anchor if room, otherwise below the anchor. - // - this is because touch users would be more likely to obscure flyouts below the anchor. - // Horizontal auto placement will be positioned to the left of the anchor if room, otherwise to the right. - // - this is because right handed users would be more likely to obscure a flyout on the right of the anchor. - // Auto placement will add a vertical scrollbar if necessary. - _getTopLeft: function Flyout_getTopLeft() { - var anchorRawRectangle = this._currentAnchor.getBoundingClientRect(), - flyout = {}, - anchor = {}; - - // Adjust for the anchor's margins. - anchor.top = anchorRawRectangle.top; - anchor.bottom = anchorRawRectangle.bottom; - anchor.left = anchorRawRectangle.left; - anchor.right = anchorRawRectangle.right; - anchor.height = anchor.bottom - anchor.top; - anchor.width = anchor.right - anchor.left; - - // Get our flyout and margins, note that getDimension calls - // window.getComputedStyle, which ensures layout is updated. - flyout.marginTop = getDimension(this._element, "marginTop"); - flyout.marginBottom = getDimension(this._element, "marginBottom"); - flyout.marginLeft = getDimension(this._element, "marginLeft"); - flyout.marginRight = getDimension(this._element, "marginRight"); - flyout.width = WinJS.Utilities.getTotalWidth(this._element); - flyout.height = WinJS.Utilities.getTotalHeight(this._element); - flyout.innerWidth = WinJS.Utilities.getContentWidth(this._element); - flyout.innerHeight = WinJS.Utilities.getContentHeight(this._element); - this._nextMarginPadding = (flyout.height - flyout.innerHeight); - - // Check fit for requested this._currentPlacement, doing fallback if necessary - switch (this._currentPlacement) { - case "top": - if (!this._fitTop(anchor, flyout)) { - // Didn't fit, needs scrollbar - this._nextTop = 0; - this._nextHeight = anchor.top - this._nextMarginPadding; - } - this._centerHorizontally(anchor, flyout, this._currentAlignment); - break; - case "bottom": - if (!this._fitBottom(anchor, flyout)) { - // Didn't fit, needs scrollbar - this._nextTop = -1; - this._nextHeight = thisWinUI._Overlay._keyboardInfo._visibleDocHeight - anchor.bottom - this._nextMarginPadding; - } - this._centerHorizontally(anchor, flyout, this._currentAlignment); - break; - case "left": - if (!this._fitLeft(anchor, flyout)) { - // Didn't fit, just shove it to edge - this._nextLeft = 0; - } - this._centerVertically(anchor, flyout); - break; - case "right": - if (!this._fitRight(anchor, flyout)) { - // Didn't fit,just shove it to edge - this._nextLeft = -1; - } - this._centerVertically(anchor, flyout); - break; - case "auto": - // Auto, if the anchor was in the vertical center of the display would we fit above it? - if (this._sometimesFitsAbove(anchor, flyout)) { - // It will fit above or below the anchor - if (!this._fitTop(anchor, flyout)) { - // Didn't fit above (preferred), so go below. - this._fitBottom(anchor, flyout); - } - this._centerHorizontally(anchor, flyout, this._currentAlignment); - } else { - // Won't fit above or below, try a side - if (!this._fitLeft(anchor, flyout) && - !this._fitRight(anchor, flyout)) { - // Didn't fit left or right either, is top or bottom bigger? - if (this._topHasMoreRoom(anchor)) { - // Top, won't fit, needs scrollbar - this._nextTop = 0; - this._nextHeight = anchor.top - this._nextMarginPadding; - } else { - // Bottom, won't fit, needs scrollbar - this._nextTop = -1; - this._nextHeight = thisWinUI._Overlay._keyboardInfo._visibleDocHeight - anchor.bottom - this._nextMarginPadding; - } - this._centerHorizontally(anchor, flyout, this._currentAlignment); - } else { - this._centerVertically(anchor, flyout); - } - } - break; - default: - // Not a legal this._currentPlacement value - throw new WinJS.ErrorFromName("WinJS.UI.Flyout.BadPlacement", strings.badPlacement); - } - - // Remember "bottom" in case we need to consider keyboard later, only tested for top-pinned bars - this._nextBottom = this._nextTop + flyout.height; - }, - - // If the anchor is centered vertically, would the flyout fit above it? - _sometimesFitsAbove: function Flyout_sometimesFitsAbove(anchor, flyout) { - return ((thisWinUI._Overlay._keyboardInfo._visibleDocHeight - anchor.height) / 2) >= flyout.height; - }, - - _topHasMoreRoom: function Flyout_topHasMoreRoom(anchor) { - return anchor.top > thisWinUI._Overlay._keyboardInfo._visibleDocHeight - anchor.bottom; - }, - - // See if we can fit in various places, fitting in the main view, - // ignoring viewport changes, like for the IHM. - _fitTop: function Flyout_fitTop(anchor, flyout) { - this._nextTop = anchor.top - flyout.height; - this._nextAnimOffset = { top: "50px", left: "0px", keyframe: "WinJS-showFlyoutTop" }; - return (this._nextTop >= 0 && - this._nextTop + flyout.height <= thisWinUI._Overlay._keyboardInfo._visibleDocBottom); - }, - - _fitBottom: function Flyout_fitBottom(anchor, flyout) { - this._nextTop = anchor.bottom; - this._nextAnimOffset = { top: "-50px", left: "0px", keyframe: "WinJS-showFlyoutBottom" }; - return (this._nextTop >= 0 && - this._nextTop + flyout.height <= thisWinUI._Overlay._keyboardInfo._visibleDocBottom); - }, - - _fitLeft: function Flyout_fitLeft(anchor, flyout) { - this._nextLeft = anchor.left - flyout.width; - this._nextAnimOffset = { top: "0px", left: "50px", keyframe: "WinJS-showFlyoutLeft" }; - return (this._nextLeft >= 0 && this._nextLeft + flyout.width <= thisWinUI._Overlay._keyboardInfo._visualViewportWidth); - }, - - _fitRight: function Flyout_fitRight(anchor, flyout) { - this._nextLeft = anchor.right; - this._nextAnimOffset = { top: "0px", left: "-50px", keyframe: "WinJS-showFlyoutRight" }; - return (this._nextLeft >= 0 && this._nextLeft + flyout.width <= thisWinUI._Overlay._keyboardInfo._visualViewportWidth); - }, - - _centerVertically: function Flyout_centerVertically(anchor, flyout) { - this._nextTop = anchor.top + anchor.height / 2 - flyout.height / 2; - if (this._nextTop < 0) { - this._nextTop = 0; - } else if (this._nextTop + flyout.height >= thisWinUI._Overlay._keyboardInfo._visibleDocBottom) { - // Flag to put on bottom - this._nextTop = -1; - } - }, - - _centerHorizontally: function Flyout_centerHorizontally(anchor, flyout, alignment) { - if (alignment === "center") { - this._nextLeft = anchor.left + anchor.width / 2 - flyout.width / 2; - } else if (alignment === "left") { - this._nextLeft = anchor.left; - } else if (alignment === "right") { - this._nextLeft = anchor.right - flyout.width; - } else { - throw new WinJS.ErrorFromName("WinJS.UI.Flyout.BadAlignment", strings.badAlignment); - } - if (this._nextLeft < 0) { - this._nextLeft = 0; - } else if (this._nextLeft + flyout.width >= document.documentElement.clientWidth) { - // flag to put on right - this._nextLeft = -1; - } - }, - - _updateAdjustments: function Flyout_updateAdjustments(alignment) { - // Move to 0,0 in case it is off screen, so that it lays out at a reasonable size - this._element.style.top = "0px"; - this._element.style.bottom = "auto"; - this._element.style.left = "0px"; - this._element.style.right = "auto"; - - // Scrolling may not be necessary - WinJS.Utilities.removeClass(this._element, scrollsClass); - if (this._lastMaxHeight !== null) { - this._element.style.maxHeight = this._lastMaxHeight; - this._lastMaxHeight = null; - } - // Alignment - if (alignment === "center") { - WinJS.Utilities.removeClass(this._element, "win-leftalign"); - WinJS.Utilities.removeClass(this._element, "win-rightalign"); - } else if (alignment === "left") { - WinJS.Utilities.addClass(this._element, "win-leftalign"); - WinJS.Utilities.removeClass(this._element, "win-rightalign"); - } else if (alignment === "right") { - WinJS.Utilities.addClass(this._element, "win-rightalign"); - WinJS.Utilities.removeClass(this._element, "win-leftalign"); - } - }, - - _showingKeyboard: function Flyout_showingKeyboard(event) { - if (this.hidden) { - return; - } - - // The only way that we can be showing a keyboard when a flyout is up is because the input was - // in the flyout itself, in which case we'll be moving ourselves. There is no practical way - // for the application to override this as the focused element is in our flyout. - event.ensuredFocusedElementInView = true; - - // See if the keyboard is going to force us to move - this._checkKeyboardFit(); - - if (this._keyboardMovedUs) { - // Pop out immediately, then move to new spot - this._element.style.opacity = 0; - var that = this; - setTimeout(function () { that._adjustForKeyboard(); that._baseAnimateIn(); }, thisWinUI._Overlay._keyboardInfo._animationShowLength); - } - }, - - _resize: function Flyout_resize(event) { - // If hidden and not busy animating, then nothing to do - if (this.hidden && !this._animating) { - return; - } - - // This should only happen if the IHM is dismissing, - // the only other way is for viewstate changes, which - // would dismiss any flyout. - if (this._keyboardHiding) { - // Hiding keyboard, update our position, giving the anchor a chance to update first. - var that = this; - setImmediate(function () { that._findPosition(); }); - this._keyboardHiding = false; - } - }, - - _checkKeyboardFit: function Flyout_checkKeyboardFit() { - // Check for moving to fit keyboard: - // - Too Tall, above top, or below bottom. - var height = WinJS.Utilities.getTotalHeight(this._element); - var viewportHeight = thisWinUI._Overlay._keyboardInfo._visibleDocHeight - this._nextMarginPadding; - if (height > viewportHeight) { - // Too Tall, pin to top with max height - this._keyboardMovedUs = true; - this._scrollTop = 0; - this._keyboardSquishedUs = viewportHeight; - } else if (this._nextTop === -1) { - // Pinned to bottom counts as moved - this._keyboardMovedUs = true; - } else if (this._nextTop < 0) { - // Above the top of the viewport - this._scrollTop = 0; - this._keyboardMovedUs = true; - } else if (this._nextBottom > thisWinUI._Overlay._keyboardInfo._visibleDocBottom) { - // Below the bottom of the viewport - this._scrollTop = -1; - this._keyboardMovedUs = true; - } - }, - - _adjustForKeyboard: function Flyout_adjustForKeyboard() { - // Keyboard moved us, update our metrics as needed - if (this._keyboardSquishedUs) { - // Add scrollbar if we didn't already have scrollsClass - if (!this._hasScrolls) { - WinJS.Utilities.addClass(this._element, scrollsClass); - this._lastMaxHeight = this._element.style.maxHeight; - } - // Adjust height - this._element.style.maxHeight = this._keyboardSquishedUs + "px"; - } - - // Update top/bottom - this._checkScrollPosition(true); - }, - - _hidingKeyboard: function Flyout_hidingKeyboard(event) { - // If we aren't visible and not animating, or haven't been repositioned, then nothing to do - // We don't know if the keyboard moved the anchor, so _keyboardMovedUs doesn't help here - if (this.hidden && !this._animating) { - return; - } - - // Snap to the final position - // We'll either just reveal the current space or resize the window - if (thisWinUI._Overlay._keyboardInfo._isResized) { - // Flag resize that we'll need an updated position - this._keyboardHiding = true; - } else { - // Not resized, update our final position, giving the anchor a chance to update first. - var that = this; - setImmediate(function () { that._findPosition(); }); - } - }, - - _checkScrollPosition: function Flyout_checkScrollPosition(showing) { - if (this.hidden && !showing) { - return; - } - - // May need to adjust top by viewport offset - if (this._scrollTop < 0) { - // Need to attach to bottom - this._element.style.bottom = thisWinUI._Overlay._keyboardInfo._visibleDocBottomOffset + "px"; - this._element.style.top = "auto"; - } else { - // Normal, attach to top - this._element.style.top = "0px"; - this._element.style.bottom = "auto"; - } - }, - - // AppBar flyout animations - _flyoutAnimateIn: function Flyout_flyoutAnimateIn() { - if (this._keyboardMovedUs) { - return this._baseAnimateIn(); - } else { - this._element.style.opacity = 1; - this._element.style.visibility = "visible"; - return WinJS.UI.Animation.showPopup(this._element, this._nextAnimOffset); - } - }, - - _flyoutAnimateOut: function Flyout_flyoutAnimateOut() { - if (this._keyboardMovedUs) { - return this._baseAnimateOut(); - } else { - this._element.style.opacity = 0; - return WinJS.UI.Animation.hidePopup(this._element, this._nextAnimOffset); - } - }, - - // Hide all other flyouts besides this one - _hideAllOtherFlyouts: function Flyout_hideAllOtherFlyouts(thisFlyout) { - var flyouts = document.querySelectorAll(".win-flyout"); - for (var i = 0; i < flyouts.length; i++) { - var flyoutControl = flyouts[i].winControl; - if (flyoutControl && !flyoutControl.hidden && (flyoutControl !== thisFlyout)) { - flyoutControl.hide(); - } - } - }, - - // Returns true if there is a flyout in the DOM that is not hidden - _isThereVisibleFlyout: function Flyout_isThereVisibleFlyout() { - var flyouts = document.querySelectorAll(".win-flyout"); - for (var i = 0; i < flyouts.length; i++) { - var flyoutControl = flyouts[i].winControl; - if (flyoutControl && !flyoutControl.hidden) { - return true; - } - } - - return false; - }, - - _handleKeyDown: function Flyout_handleKeyDown(event) { - // Escape closes flyouts but if the user has a text box with an IME candidate - // window open, we want to skip the ESC key event since it is handled by the IME. - // When the IME handles a key it sets event.keyCode to 229 for an easy check. - if (event.key === "Esc" && event.keyCode !== 229) { - // Show a focus rect on what we move focus to - event.preventDefault(); - event.stopPropagation(); - this.winControl._keyboardInvoked = true; - this.winControl._hide(); - } else if ((event.key === "Spacebar" || event.key === "Enter") - && (this === document.activeElement)) { - event.preventDefault(); - event.stopPropagation(); - this.winControl.hide(); - } else if (event.shiftKey && event.key === "Tab" - && this === document.activeElement - && !event.altKey && !event.ctrlKey && !event.metaKey) { - event.preventDefault(); - event.stopPropagation(); - this.winControl._focusOnLastFocusableElementOrThis(); - } - }, - - // Create and add a new first div as the first child - _addFirstDiv: function Flyout_addFirstDiv() { - var firstDiv = document.createElement("div"); - firstDiv.className = firstDivClass; - firstDiv.style.display = "inline"; - firstDiv.setAttribute("role", "menuitem"); - firstDiv.setAttribute("aria-hidden", "true"); - - this._element.insertAdjacentElement("AfterBegin", firstDiv); - var that = this; - firstDiv.addEventListener("focus", function () { that._focusOnLastFocusableElementOrThis(); }, false); - - return firstDiv; - }, - - // Create and add a new final div as the last child - _addFinalDiv: function Flyout_addFinalDiv() { - var finalDiv = document.createElement("div"); - finalDiv.className = finalDivClass; - finalDiv.style.display = "inline"; - finalDiv.setAttribute("role", "menuitem"); - finalDiv.setAttribute("aria-hidden", "true"); - - this._element.appendChild(finalDiv); - var that = this; - finalDiv.addEventListener("focus", function () { that._focusOnFirstFocusableElementOrThis(); }, false); - - return finalDiv; - }, - - _writeProfilerMark: function Flyout_writeProfilerMark(text) { - msWriteProfilerMark("WinJS.UI.Flyout:" + this._id + ":" + text); - } - }); - return Flyout; - }) - }); - -})(WinJS); - -// Menu -/// Menu,Menus,Flyout,Flyouts,Statics -(function menuInit(WinJS) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// Represents a menu flyout for displaying commands. - /// - /// - /// Menu - /// - /// - /// - /// - /// ]]> - /// Raised just before showing a menu. - /// Raised immediately after a menu is fully shown. - /// Raised just before hiding a menu. - /// Raised immediately after a menu is fully hidden. - /// The Menu control itself - /// - /// - /// - Menu: WinJS.Namespace._lazy(function () { - var thisWinUI = WinJS.UI; - - // Class Names - var menuClass = "win-menu"; - var menuToggleClass = "win-menu-toggle"; - - var strings = { - get ariaLabel() { return WinJS.Resources._getWinJSString("ui/menuAriaLabel").value; }, - get requiresCommands() { return WinJS.Resources._getWinJSString("ui/requiresCommands").value; }, - get nullCommand() { return WinJS.Resources._getWinJSString("ui/nullCommand").value; }, - }; - - var Menu = WinJS.Class.derive(WinJS.UI.Flyout, function Menu_ctor(element, options) { - /// - /// - /// Creates a new Menu control. - /// - /// - /// The DOM element that will host the control. - /// - /// - /// The set of properties and values to apply to the control. - /// - /// The new Menu control. - /// - /// - - // We need to be built on top of a Flyout, so stomp on the user's input - options = options || {}; - - // Make sure there's an input element - this._element = element || document.createElement("div"); - this._id = this._element.id || this._element.uniqueID; - this._writeProfilerMark("constructor,StartTM"); - - // validate that if they didn't set commands, in which - // case any HTML only contains commands. Do this first - // so that we don't leave partial Menus in the DOM. - if (!options.commands && this._element) { - // Shallow copy object so we can modify it. - options = WinJS.Utilities._shallowCopy(options); - options.commands = this._verifyCommandsOnly(this._element, "WinJS.UI.MenuCommand"); - } - - // Remember aria role in case base constructor changes it - var role = this._element ? this._element.getAttribute("role") : null; - var label = this._element ? this._element.getAttribute("aria-label") : null; - - // Call the base overlay constructor helper - this._baseFlyoutConstructor(this._element, options); - - // Make sure we have an ARIA role - if (role === null || role === "" || role === undefined) { - this._element.setAttribute("role", "menu"); - } - if (label === null || label === "" || label === undefined) { - this._element.setAttribute("aria-label", strings.ariaLabel); - } - - // Handle "esc" & "up/down" key presses - this._element.addEventListener("keydown", this._handleKeyDown, true); - - // Attach our css class - WinJS.Utilities.addClass(this._element, menuClass); - - // Need to set our commands, making sure we're hidden first - this.hide(); - this._writeProfilerMark("constructor,StopTM"); - }, { - // Public Properties - - /// - /// Sets the MenuCommand objects that appear in the Menu. You can set this to a single MenuCommand or an array of MenuCommand objects. - /// - /// - commands: { - set: function (value) { - // Fail if trying to set when visible - if (!this.hidden) { - throw new WinJS.ErrorFromName("WinJS.UI.Menu.CannotChangeCommandsWhenVisible", WinJS.Resources._formatString(thisWinUI._Overlay.commonstrings.cannotChangeCommandsWhenVisible, "Menu")); - } - - // Start from scratch - WinJS.Utilities.empty(this._element); - - // In case they had only one... - if (!Array.isArray(value)) { - value = [value]; - } - - // Add commands - var len = value.length; - for (var i = 0; i < len; i++) { - this._addCommand(value[i]); - } - } - }, - - getCommandById: function (id) { - /// - /// - /// Retrieve the command with the specified ID from this Menu. If more than one command is found, all are returned. - /// - /// The ID of the command to find. - /// - /// The command found, an array of commands if more than one have the same ID, or null if no command is found. - /// - /// - /// - var commands = this.element.querySelectorAll("#" + id); - for (var count = 0; count < commands.length; count++) { - // Any elements we generated this should succeed for, - // but remove missing ones just to be safe. - commands[count] = commands[count].winControl; - if (!commands[count]) { - commands.splice(count, 1); - } - } - - if (commands.length === 1) { - return commands[0]; - } else if (commands.length === 0) { - return null; - } - - return commands; - }, - - - showCommands: function (commands) { - /// - /// - /// Shows the specified commands of the Menu. - /// - /// - /// The commands to show. The array elements may be Menu objects, or the string identifiers (IDs) of commands. - /// - /// - /// - if (!commands) { - throw new WinJS.ErrorFromName("WinJS.UI.Menu.RequiresCommands", strings.requiresCommands); - } - - this._showCommands(commands, true); - }, - - hideCommands: function (commands) { - /// - /// - /// Hides the Menu. - /// - /// - /// Required. Command or Commands to hide, either String, DOM elements, or WinJS objects. - /// - /// - /// - if (!commands) { - throw new WinJS.ErrorFromName("WinJS.UI.Menu.RequiresCommands", strings.requiresCommands); - } - - this._hideCommands(commands, true); - }, - - showOnlyCommands: function (commands) { - /// - /// - /// Shows the specified commands of the Menu while hiding all other commands. - /// - /// - /// The commands to show. The array elements may be MenuCommand objects, or the string identifiers (IDs) of commands. - /// - /// - /// - if (!commands) { - throw new WinJS.ErrorFromName("WinJS.UI.Menu.RequiresCommands", strings.requiresCommands); - } - - this._showOnlyCommands(commands, true); - }, - - show: function (anchor, placement, alignment) { - /// - /// - /// Shows the Menu, if hidden, regardless of other states. - /// - /// - /// The DOM element, or ID of a DOM element, to anchor the Menu. This parameter overrides the anchor property for this method call only. - /// - /// - /// The placement of the Menu to the anchor: 'auto' (default), 'top', 'bottom', 'left', or 'right'. This parameter overrides the placement - /// property for this method call only. - /// - /// - /// For 'top' or 'bottom' placement, the alignment of the Menu to the anchor's edge: 'center' (default), 'left', or 'right'. This parameter - /// overrides the alignment property for this method call only. - /// - /// - /// - // Just call private version to make appbar flags happy - this._writeProfilerMark("show,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndShow(). - this._show(anchor, placement, alignment); - }, - - _show: function Menu_show(anchor, placement, alignment) { - // Before we show, we also need to check for children flyouts needing anchors - this._checkForFlyoutCommands(); - - // Call flyout show - this._baseFlyoutShow(anchor, placement, alignment); - - // We need to check for toggles after we send the beforeshow event, - // so the developer has a chance to show or hide more commands. - // Flyout's _findPosition will make that call. - }, - - _addCommand: function Menu_addCommand(command) { - if (!command) { - throw new WinJS.ErrorFromName("WinJS.UI.Menu.NullCommand", strings.nullCommand); - } - // See if it's a command already - if (!command._element) { - // Not a command, so assume it's options for a command - command = new WinJS.UI.MenuCommand(null, command); - } - // If we were attached somewhere else, detach us - if (command._element.parentElement) { - command._element.parentElement.removeChild(command._element); - } - - // Reattach us - this._element.appendChild(command._element); - }, - - // Called by flyout's _findPosition so that application can update it status - // we do the test and we can then fix this last-minute before showing. - _checkToggle: function Menu_checkToggle() { - var toggles = this._element.querySelectorAll(".win-command[aria-checked]"); - var hasToggle = false; - if (toggles) { - for (var i = 0; i < toggles.length; i++) { - if (toggles[i] && toggles[i].winControl && !toggles[i].winControl.hidden) { - // Found a visible toggle control - hasToggle = true; - break; - } - } - } - if (hasToggle) { - WinJS.Utilities.addClass(this._element, menuToggleClass); - } else { - WinJS.Utilities.removeClass(this._element, menuToggleClass); - } - }, - - _checkForFlyoutCommands: function Menu_checkForFlyoutCommands() { - var commands = this._element.querySelectorAll(".win-command"); - for (var count = 0; count < commands.length; count++) { - if (commands[count].winControl) { - // Remember our anchor in case it's a flyout - commands[count].winControl._parentFlyout = this; - } - } - }, - - _handleKeyDown: function Menu_handleKeyDown(event) { - if (event.key === "Esc") { - // Show a focus rect on what we move focus to - this.winControl._keyboardInvoked = true; - this.winControl._hide(); - } else if ((event.key === "Spacebar" || event.key === "Enter") - && (this === document.activeElement)) { - event.preventDefault(); - this.winControl.hide(); - } else if (event.key === "Up") { - var that = this; - thisWinUI.Menu._focusOnPreviousElement(that); - - // Prevent the page from scrolling - event.preventDefault(); - } else if (event.key === "Down") { - that = this; - thisWinUI.Menu._focusOnNextElement(that); - - // Prevent the page from scrolling - event.preventDefault(); - } else if (event.key === "Tab") { - event.preventDefault(); - } - }, - - _writeProfilerMark: function Menu_writeProfilerMark(text) { - msWriteProfilerMark("WinJS.UI.Menu:" + this._id + ":" + text); - } - }); - - // Statics - - // Set focus to next focusable element in the menu (loop if necessary). - // Note: The loop works by first setting focus to the menu itself. If the menu is - // what had focus before, then we break. Otherwise we try the first child next. - // Focus remains on the menu if nothing is focusable. - Menu._focusOnNextElement = function (menu) { - var _currentElement = document.activeElement; - - do { - if (_currentElement === menu) { - _currentElement = _currentElement.firstElementChild; - } else { - _currentElement = _currentElement.nextElementSibling; - } - - if (_currentElement) { - _currentElement.focus(); - } else { - _currentElement = menu; - } - - } while (_currentElement !== document.activeElement) - }; - - // Set focus to previous focusable element in the menu (loop if necessary). - // Note: The loop works by first setting focus to the menu itself. If the menu is - // what had focus before, then we break. Otherwise we try the last child next. - // Focus remains on the menu if nothing is focusable. - Menu._focusOnPreviousElement = function (menu) { - var _currentElement = document.activeElement; - - do { - if (_currentElement === menu) { - _currentElement = _currentElement.lastElementChild; - } else { - _currentElement = _currentElement.previousElementSibling; - } - - if (_currentElement) { - _currentElement.focus(); - } else { - _currentElement = menu; - } - - } while (_currentElement !== document.activeElement) - }; - - return Menu; - }) - }); - -})(WinJS); - - -// Menu Command -/// appbar,appbars,Flyout,Flyouts,onclick,Statics -(function menuCommandInit(WinJS) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// - /// Represents a command to be displayed in a Menu. MenuCommand objects provide button, toggle button, flyout button, - /// or separator functionality for Menu controls. - /// - /// - /// - /// - /// - /// ]]> - /// The MenuCommand control itself - /// - /// - /// - MenuCommand: WinJS.Namespace._lazy(function () { - var thisWinUI = WinJS.UI; - - // Class Names - var menuCommandClass = "win-command"; - var typeSeparator = "separator"; - var typeButton = "button"; - var typeToggle = "toggle"; - var typeFlyout = "flyout"; - - function _handleMenuClick(event) { - var command = this.winControl; - if (command) { - var hideParent = true; - if (command._type === typeToggle) { - command.selected = !command.selected; - } else if (command._type === typeFlyout && command._flyout) { - var flyout = command._flyout; - // Flyout may not have processAll'd, so this may be a DOM object - if (typeof flyout === "string") { - flyout = document.getElementById(flyout); - } - if (!flyout.show) { - flyout = flyout.winControl; - } - if (flyout && flyout.show) { - if (command._parentFlyout) { - hideParent = false; - flyout.show(command._parentFlyout._currentAnchor, command._parentFlyout._currentPlacement, command._parentFlyout._currentAlignment); - } else { - flyout.show(this); - } - } - } - if (command.onclick) { - command.onclick(event); - } - // Dismiss parent flyout - if (hideParent && command._parentFlyout) { - command._parentFlyout.hide(); - } - } - } - - function _handleMouseOver(event) { - if (this && this.focus) { - this.focus(); - - this.addEventListener("mousemove", _handleMouseMove, false); - } - } - - function _handleMouseMove(event) { - if (this && this.focus && this !== document.activeElement) { - this.focus(); - } - } - - function _handleMouseOut(event) { - var that = this; - var parentFlyout = _getParentFlyout(that); - if (parentFlyout - && this === document.activeElement - && WinJS.Utilities.hasClass(parentFlyout, "win-menu") - && parentFlyout.focus) { - // Menu gives focus to the menu itself - parentFlyout.focus(); - } else if (parentFlyout - && this === document.activeElement - && parentFlyout.children - && parentFlyout.children.length > 0 - && parentFlyout.children[0] - && WinJS.Utilities.hasClass(parentFlyout.children[0], "win-firstdiv") - && parentFlyout.children[0].focus) { - // Flyout gives focus to firstDiv - parentFlyout.children[0].focus(); - } - - this.removeEventListener("mousemove", _handleMouseMove, false); - } - - function _getParentFlyout(element) { - while (element && !WinJS.Utilities.hasClass(element, "win-flyout")) { - element = element.parentElement; - } - - return element; - } - - var strings = { - get ariaLabel() { return WinJS.Resources._getWinJSString("ui/menuCommandAriaLabel").value; }, - get duplicateConstruction() { return WinJS.Resources._getWinJSString("ui/duplicateConstruction").value; }, - get badClick() { return WinJS.Resources._getWinJSString("ui/badClick").value; }, - get badHrElement() { return WinJS.Resources._getWinJSString("ui/badHrElement").value; }, - get badButtonElement() { return WinJS.Resources._getWinJSString("ui/badButtonElement").value; } - }; - - return WinJS.Class.define(function MenuCommand_ctor(element, options) { - /// - /// - /// Creates a new MenuCommand object. - /// - /// - /// The DOM element that will host the control. - /// - /// - /// The set of properties and values to apply to the new MenuCommand. - /// - /// - /// A MenuCommand control. - /// - /// - /// - - // Check to make sure we weren't duplicated - if (element && element.winControl) { - throw new WinJS.ErrorFromName("WinJS.UI.MenuCommand.DuplicateConstruction", strings.duplicateConstruction); - } - - this._disposed = false; - - // Don't blow up if they didn't pass options - if (!options) { - options = {}; - } - - // Need a type before we can create our element - if (!options.type) { - this._type = typeButton; - } - - // Go ahead and create it, separator types look different than buttons - // Don't forget to use passed in element if one was provided. - this._element = element; - if (options.type === typeSeparator) { - this._createSeparator(); - } else { - // This will also set the icon & label - this._createButton(); - } - WinJS.Utilities.addClass(this._element, "win-disposable"); - - // Remember ourselves - this._element.winControl = this; - - // Attach our css class - WinJS.Utilities.addClass(this._element, menuCommandClass); - - if (!options.selected && options.type === typeToggle) { - // Make sure toggle's have selected false for CSS - this.selected = false; - } - if (options.onclick) { - this.onclick = options.onclick; - } - options.onclick = _handleMenuClick; - - WinJS.UI.setOptions(this, options); - - // Set our options - if (this._type !== typeSeparator) { - // Make sure we have an ARIA role - var role = this._element.getAttribute("role"); - if (role === null || role === "" || role === undefined) { - role = "menuitem"; - if (this._type === typeToggle) { - role = "menuitemcheckbox"; - } - this._element.setAttribute("role", role); - if (this._type === typeFlyout) { - this._element.setAttribute("aria-haspopup", true); - } - } - var label = this._element.getAttribute("aria-label"); - if (label === null || label === "" || label === undefined) { - this._element.setAttribute("aria-label", strings.ariaLabel); - } - } - - this._element.addEventListener("mouseover", _handleMouseOver, false); - this._element.addEventListener("mouseout", _handleMouseOut, false); - }, { - /// - /// Gets the ID of the MenuCommand. - /// - /// - id: { - get: function () { - return this._element.id; - }, - set: function (value) { - // we allow setting first time only. otherwise we ignore it. - if (!this._element.id) { - this._element.id = value; - } - } - }, - - /// - /// Gets the type of the MenuCommand. Possible values are "button", "toggle", "flyout", or "separator". - /// - /// - type: { - get: function () { - return this._type; - }, - set: function (value) { - // we allow setting first time only. otherwise we ignore it. - if (!this._type) { - if (value !== typeButton && value !== typeFlyout && value !== typeToggle && value !== typeSeparator) { - this._type = typeButton; - } else { - this._type = value; - } - } - } - }, - - /// - /// The label of the MenuCommand - /// - /// - label: { - get: function () { - return this._label; - }, - set: function (value) { - this._label = value; - this._element.innerText = this.label; - - // Update aria-label - this._element.setAttribute("aria-label", this.label); - } - }, - - /// - /// Gets or sets the function to invoke when the command is clicked. - /// - /// - onclick: { - get: function () { - return this._onclick; - }, - set: function (value) { - if (value && typeof value !== "function") { - throw new WinJS.ErrorFromName("WinJS.UI.MenuCommand.BadClick", WinJS.Resources._formatString(strings.badClick, "MenuCommand")); - } - this._onclick = value; - } - }, - - /// - /// For flyout type MenuCommands, this property returns the WinJS.UI.Flyout that this command invokes. When setting this property, you can set - /// it to the string ID of the Flyout, the DOM object that hosts the Flyout, or the Flyout object itself. - /// - /// - flyout: { - get: function () { - // Resolve it to the flyout - var flyout = this._flyout; - if (typeof flyout === "string") { - flyout = document.getElementById(flyout); - } - // If it doesn't have a .element, then we need to getControl on it - if (flyout && !flyout.element) { - flyout = flyout.winControl; - } - - return flyout; - }, - set: function (value) { - // Need to update aria-owns with the new ID. - var id = value; - if (id && typeof id !== "string") { - // Our controls have .element properties - if (id.element) { - id = id.element; - } - // Hope it's a DOM element, get ID from DOM element - if (id) { - if (id.id) { - id = id.id; - } else { - // No id, have to fake one - id.id = id.uniqueID; - id = id.id; - } - } - } - if (typeof id === "string") { - this._element.setAttribute("aria-owns", id); - } - - // Remember it - this._flyout = value; - } - }, - - /// - /// Gets or sets the selected state of a toggle button. This property is true if the toggle button is selected; otherwise, it's false. - /// - /// - selected: { - get: function () { - // Ensure it's a boolean because we're using the DOM element to keep in-sync - return this._element.getAttribute("aria-checked") === "true"; - }, - set: function (value) { - this._element.setAttribute("aria-checked", !!value); - } - }, - - /// - element: { - get: function () { - return this._element; - } - }, - - /// - /// Gets or sets a value that indicates whether the MenuCommand is disabled. This value is true if the MenuCommand is disabled; otherwise, false. - /// - /// - disabled: { - get: function () { - // Ensure it's a boolean because we're using the DOM element to keep in-sync - return !!this._element.disabled; - }, - set: function (value) { - this._element.disabled = !!value; - } - }, - - /// - hidden: { - get: function () { - // Ensure it's a boolean because we're using the DOM element to keep in-sync - return this._element.style.visibility === "hidden"; - }, - set: function (value) { - var menuControl = thisWinUI._Overlay._getParentControlUsingClassName(this._element, "win-menu"); - if (menuControl && !menuControl.hidden) { - throw new WinJS.ErrorFromName("WinJS.UI.MenuCommand.CannotChangeHiddenProperty", WinJS.Resources._formatString(thisWinUI._Overlay.commonstrings.cannotChangeHiddenProperty, "Menu")); - } - - var style = this._element.style; - if (value) { - style.visibility = "hidden"; - style.display = "none"; - } else { - style.visibility = ""; - style.display = "block"; - } - } - }, - - /// - /// Gets or sets the extra CSS class that is applied to the host DOM element. - /// - /// - extraClass: { - get: function () { - return this._extraClass; - }, - set: function (value) { - if (this._extraClass) { - WinJS.Utilities.removeClass(this._element, this._extraClass); - } - this._extraClass = value; - WinJS.Utilities.addClass(this._element, this._extraClass); - } - }, - - - dispose: function () { - /// - /// - /// Disposes this control. - /// - /// - /// - if (this._disposed) { - return; - } - this._disposed = true; - - if (this._flyout) { - this._flyout.dispose(); - } - }, - - addEventListener: function (type, listener, useCapture) { - /// - /// - /// Registers an event handler for the specified event. - /// - /// The name of the event to register. - /// The function that handles the event. - /// - /// Set to true to register the event handler for the capturing phase; otherwise, set to false to register the event handler for the bubbling phase. - /// - /// - /// - return this._element.addEventListener(type, listener, useCapture); - }, - - removeEventListener: function (type, listener, useCapture) { - /// - /// - /// Removes the specified event handler that the addEventListener method registered. - /// - /// The name of the event to remove. - /// The event handler function to remove. - /// - /// Set to true to remove the capturing phase event handler; set to false to remove the bubbling phase event handler. - /// - /// - /// - return this._element.removeEventListener(type, listener, useCapture); - }, - - // Private properties - _createSeparator: function MenuCommand_createSeparator() { - // Make sure there's an input element - if (!this._element) { - this._element = document.createElement("hr"); - } else { - // Verify the input was an hr - if (this._element.tagName !== "HR") { - throw new WinJS.ErrorFromName("WinJS.UI.MenuCommand.BadHrElement", strings.badHrElement); - } - } - }, - - _createButton: function MenuCommand_createButton() { - // Make sure there's an input element - if (!this._element) { - this._element = document.createElement("button"); - } else { - // Verify the input was a button - if (this._element.tagName !== "BUTTON") { - throw new WinJS.ErrorFromName("WinJS.UI.MenuCommand.BadButtonElement", strings.badButtonElement); - } - this._element.innerHTML = ""; - } - - // MenuCommand buttons need to look like this: - //// - this._element.type = "button"; - - // 'innertext' label is added later by caller - } - }); - }) - }); - -})(WinJS); - - -(function searchboxInit(global) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// - /// Enables the user to perform search queries and select suggestions. - /// - /// - /// - /// - /// - /// ]]> - /// Raised when user or app changes the query text. - /// Raised when user clicks on search glyph or presses Enter. - /// Raised when user clicks one of the displayed suggestions. - /// Raised when the system requests search suggestions from this app. - /// - /// Raised when the app automatically redirects focus to the search box. This event can only be raised when the focusOnKeyboardInput property is set to true. - /// - /// Styles the entire Search box control. - /// Styles the query input box. - /// Styles the search button. - /// Styles the result suggestions flyout. - /// Styles the result type suggestion. - /// Styles the query type suggestion. - /// - /// Styles the separator type suggestion. - /// - /// - /// Styles the currently selected suggestion. - /// - /// - /// - /// - SearchBox: WinJS.Namespace._lazy(function () { - var utilities = WinJS.Utilities; - var createEvent = WinJS.Utilities._createEventProperty; - - // Enums - var ClassName = { - searchBox: "win-searchbox", - searchBoxInput: "win-searchbox-input", - searchBoxButton: "win-searchbox-button", - searchBoxFlyout: "win-searchbox-flyout", - searchBoxSuggestionResult: "win-searchbox-suggestion-result", - searchBoxSuggestionQuery: "win-searchbox-suggestion-query", - searchBoxSuggestionSeparator: "win-searchbox-suggestion-separator", - searchBoxSuggestionSelected: "win-searchbox-suggestion-selected", - searchBoxFlyoutHighlightText: "win-searchbox-flyout-highlighttext", - searchBoxButtonInputFocus: "win-searchbox-button-input-focus", - searchBoxInputFocus: "win-searchbox-input-focus", - searchBoxSuggestionResultText: "win-searchbox-suggestion-result-text", - searchBoxSuggestionResultDetailedText: "win-searchbox-suggestion-result-detailed-text", - searchboxDisabled: "win-searchbox-disabled", - searchboxHitHighlightSpan: "win-searchbox-hithighlight-span", - }; - - var EventName = { - querychanged: "querychanged", - querysubmitted: "querysubmitted", - resultsuggestionchosen: "resultsuggestionchosen", - suggestionsrequested: "suggestionsrequested", - receivingfocusonkeyboardinput: "receivingfocusonkeyboardinput" - }; - - var SearchSuggestionKind = { - Query: 0, - Result: 1, - Separator: 2 - }; - - var strings = { - get duplicateConstruction() { return WinJS.Resources._getWinJSString("ui/duplicateConstruction").value; }, - get invalidSearchBoxSuggestionKind() { return WinJS.Resources._getWinJSString("ui/invalidSearchBoxSuggestionKind").value; }, - get ariaLabel() { return WinJS.Resources._getWinJSString("ui/searchBoxAriaLabel").value; }, - get ariaLabelInputNoPlaceHolder() { return WinJS.Resources._getWinJSString("ui/searchBoxAriaLabelInputNoPlaceHolder").value; }, - get ariaLabelInputPlaceHolder() { return WinJS.Resources._getWinJSString("ui/searchBoxAriaLabelInputPlaceHolder").value; }, - get ariaLabelButton() { return WinJS.Resources._getWinJSString("ui/searchBoxAriaLabelButton").value; }, - get ariaLabelQuery() { return WinJS.Resources._getWinJSString("ui/searchBoxAriaLabelQuery").value; }, - get ariaLabelSeparator() { return WinJS.Resources._getWinJSString("ui/searchBoxAriaLabelSeparator").value; }, - get ariaLabelResult() { return WinJS.Resources._getWinJSString("ui/searchBoxAriaLabelResult").value; } - }; - - var SearchBox = WinJS.Class.define(function SearchBox_ctor(element, options) { - /// - /// - /// Creates a new SearchBox. - /// - /// - /// The DOM element that hosts the SearchBox. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. - /// Each property of the options object corresponds to one of the control's properties or events. - /// Event names must begin with "on". For example, to provide a handler for the querychanged event, - /// add a property named "onquerychanged" to the options object and set its value to the event handler. - /// This parameter is optional. - /// - /// - /// The new SearchBox. - /// - /// - /// - - element = element || document.createElement("div"); - - if (element.winControl) { - throw new WinJS.ErrorFromName("WinJS.UI.SearchBox.DuplicateConstruction", strings.duplicateConstruction); - } - element.winControl = this; - - // Elements - this._domElement = null; - this._inputElement = null; - this._buttonElement = null; - this._flyout = null; - this._flyoutDivElement = null; - this._repeaterDivElement = null; - this._repeater = null; - - // Variables - this._disposed = false; - this._focusOnKeyboardInput = false; - this._chooseSuggestionOnEnter = false; - this._lastKeyPressLanguage = ""; - - // These are used to eliminate redundant query submitted events - this._prevQueryText = ""; - this._prevLinguisticDetails = this._createSearchQueryLinguisticDetails([], 0, 0, "", ""); - this._prevCompositionStart = 0; - this._prevCompositionLength = 0; - this._isProcessingDownKey = false; - this._isProcessingUpKey = false; - this._isProcessingTabKey = false; - this._isProcessingEnterKey = false; - this._isFlyoutPointerDown = false; - this._reflowImeOnPointerRelease = false; - - // Focus and selection related variables - this._currentFocusedIndex = -1; - this._currentSelectedIndex = -1; - - this._suggestionRendererBind = this._suggestionRenderer.bind(this); - this._requestingFocusOnKeyboardInputHandlerBind = this._requestingFocusOnKeyboardInputHandler.bind(this); - this._suggestionsRequestedHandlerBind = this._suggestionsRequestedHandler.bind(this); - this._suggestionsChangedHandlerBind = this._suggestionsChangedHandler.bind(this); - - // Find out if we are in local compartment and if search APIs are available. - this._searchSuggestionManager = null; - this._searchSuggestions = null; - - // Get the search suggestion provider if it is available - if ((window.Windows) && (Windows.ApplicationModel) && (Windows.ApplicationModel.Search) && (Windows.ApplicationModel.Search.Core) && (Windows.ApplicationModel.Search.Core.SearchSuggestionManager)) { - this._searchSuggestionManager = new Windows.ApplicationModel.Search.Core.SearchSuggestionManager(); - this._searchSuggestions = this._searchSuggestionManager.suggestions; - } - - this._hitFinder = null; - this._setElement(element); - WinJS.UI.setOptions(this, options); - this._setAccessibilityProperties(); - WinJS.Utilities.addClass(element, "win-disposable"); - }, { - - /// - element: { - get: function () { - return this._domElement; - } - }, - - /// - /// Gets or sets the placeholder text for the SearchBox. This text is displayed if there is no - /// other text in the input box. - /// - /// - placeholderText: { - get: function () { - return this._inputElement.placeholder; - }, - set: function (value) { - this._inputElement.placeholder = value; - this._updateInputElementAriaLabel(); - } - }, - - /// - /// Gets or sets the query text for the SearchBox. - /// - /// - queryText: { - get: function () { - return this._inputElement.value; - }, - set: function (value) { - this._inputElement.value = value; - } - }, - - /// - /// Gets or sets a value that specifies whether search history is disabled for the SearchBox. The default value is false. - /// - /// - searchHistoryDisabled: { - get: function () { - if (this._searchSuggestionManager) { - return !this._searchSuggestionManager.searchHistoryEnabled; - } else { - return true; - } - }, - set: function (value) { - if (this._searchSuggestionManager) { - this._searchSuggestionManager.searchHistoryEnabled = !value; - } - } - }, - - /// - /// Gets or sets the search history context for the SearchBox. The search history context string is used as a secondary key for storing search history. - /// (The primary key is the AppId.) An app can use the search history context string to store different search histories based on the context of the application. - /// If you don't set this property, the system assumes that all searches in your app occur in the same context. - /// If you update this property while the search pane is open with suggestions showing, the changes won't take effect until the user enters the next character. - /// - /// - searchHistoryContext: { - get: function () { - if (this._searchSuggestionManager) { - return this._searchSuggestionManager.searchHistoryContext; - } else { - return ""; - } - }, - set: function (value) { - if (this._searchSuggestionManager) { - this._searchSuggestionManager.searchHistoryContext = value; - } - } - }, - - /// - /// Enable automatically focusing the search box when the user types into the app window (off by default) While this is enabled, - /// input on the current thread will be intercepted and redirected to the search box. Only textual input will trigger the search box to focus. - /// The caller will continue to receive non-text keys (such as arrows, tab, etc - /// This will also not affect WIN/CTRL/ALT key combinations (except for Ctrl-V for paste). - /// If the client needs more to happen than just set focus in the box (make control visible, etc.), they will need to handle the event. - /// If enabled, the app must be sure to disable this if the user puts focus in some other edit field. - /// - /// - focusOnKeyboardInput: { - get: function () { - return this._focusOnKeyboardInput; - }, - set: function (value) { - if (this._focusOnKeyboardInput && !value) { - if (this._searchSuggestionManager) { - this._searchSuggestionManager.removeEventListener("requestingfocusonkeyboardinput", this._requestingFocusOnKeyboardInputHandlerBind); - } - } else if (!this._focusOnKeyboardInput && !!value) { - if (this._searchSuggestionManager) { - this._searchSuggestionManager.addEventListener("requestingfocusonkeyboardinput", this._requestingFocusOnKeyboardInputHandlerBind); - } - } - this._focusOnKeyboardInput = !!value; - } - }, - - /// - /// Gets or sets whether the first suggestion is chosen when the user presses Enter. - /// When set to true, as the user types in the search box, a focus rectangle is drawn on the first search suggestion - /// (if present and no IME composition in progress). Pressing enter will behave the same as if clicked on the focused suggestion, - /// and the down arrow key press will put real focus to the second suggestion and the up arrow key will remove focus. - /// - /// - chooseSuggestionOnEnter: { - get: function () { - return this._chooseSuggestionOnEnter; - }, - set: function (value) { - this._chooseSuggestionOnEnter = !!value; - this._updateSearchButtonClass(); - } - }, - - /// - /// Gets or sets a value that specifies whether the SearchBox is disabled. - /// - /// - disabled: { - get: function () { - return this._inputElement.disabled; - }, - set: function (value) { - if (this._inputElement.disabled === !!value) { - return; - } - - if (!value) { - // Enable control - this._inputElement.disabled = false; - this._buttonElement.disabled = false; - this._domElement.disabled = false; - utilities.removeClass(this.element, ClassName.searchboxDisabled); - if (document.activeElement === this.element) { - try { - this._inputElement.setActive(); - } catch (e) { - } - } - } else { - // Disable control - if (this._isFlyoutShown) { - this._hideFlyout(); - } - utilities.addClass(this.element, ClassName.searchboxDisabled); - this._inputElement.disabled = true; - this._buttonElement.disabled = true; - this._domElement.disabled = true; - } - } - }, - - // Methods - setLocalContentSuggestionSettings: function SearchBox_setLocalContentSuggestionSettings(settings) { - /// - /// - /// Specifies whether suggestions based on local files are automatically displayed in the search pane, and defines the criteria that - /// the system uses to locate and filter these suggestions. - /// - /// - /// The new settings for local content suggestions. - /// - /// - /// - if (this._searchSuggestionManager) { - this._searchSuggestionManager.setLocalContentSuggestionSettings(settings); - } - }, - - dispose: function SearchBox() { - /// - /// - /// Disposes this control. - /// - /// - /// - if (this._disposed) { - return; - } - - // Cancel pending promises. - if (this._flyoutOpenPromise) { - this._flyoutOpenPromise.cancel(); - } - - // Detach winrt events. - if (this._focusOnKeyboardInput) { - if (this._searchSuggestionManager) { - this._searchSuggestionManager.removeEventListener("requestingfocusonkeyboardinput", this._requestingFocusOnKeyboardInputHandlerBind); - } - } - - if (this._searchSuggestions) { - this._searchSuggestions.removeEventListener("vectorchanged", this._suggestionsChangedHandlerBind); - } - - if (this._searchSuggestionManager) { - this._searchSuggestionManager.removeEventListener("suggestionsrequested", this._suggestionsRequestedHandlerBind); - } - - this._searchSuggestionManager = null; - this._searchSuggestions = null; - this._hitFinder = null; - - this._disposed = true; - - }, - - /// - /// Raised when user or app changes the query text. - /// - /// - onquerychanged: createEvent(EventName.querychanged), - - /// - /// Raised when user clicks on search glyph or presses enter button. - /// - /// - onquerysubmitted: createEvent(EventName.querysubmitted), - - /// - /// Raised when user clicks on one of the suggestions displayed. - /// - /// - onresultsuggestionchosen: createEvent(EventName.resultsuggestionchosen), - - /// - /// Raised when Windows requests search suggestions from the app. - /// - /// - onsuggestionsrequested: createEvent(EventName.suggestionsrequested), - - // Private methods - _isFlyoutShown: function SearchBox_isFlyoutShown() { - return (this._flyoutDivElement.style.display !== "none"); - }, - - _isFlyoutBelow: function SearchBox_isFlyoutBelow() { - if (this._flyoutDivElement.getBoundingClientRect().top > this._inputElement.getBoundingClientRect().top) { - return true; - } - return false; - }, - - _getFlyoutTop: function SearchBox_getFlyoutTop() { - if (this._isFlyoutBelow()) { - return this._inputElement.getBoundingClientRect().bottom; - } - var popupHeight = this._flyoutDivElement.getBoundingClientRect().bottom - this._flyoutDivElement.getBoundingClientRect().top; - return this._inputElement.getBoundingClientRect().top - popupHeight; - }, - - _getFlyoutBottom: function SearchBox_getFlyoutBottom() { - if (this._isFlyoutBelow()) { - var popupHeight = this._flyoutDivElement.getBoundingClientRect().bottom - this._flyoutDivElement.getBoundingClientRect().top; - return this._inputElement.getBoundingClientRect().bottom + popupHeight; - } - return this._inputElement.getBoundingClientRect().top; - }, - - _updateFlyoutTopAndTouchAction: function SearchBox_updateFlyoutTopAndTouchAction() { - var popupHeight = this._flyoutDivElement.getBoundingClientRect().bottom - this._flyoutDivElement.getBoundingClientRect().top; - if (!this._isFlyoutBelow()) { - this._flyoutDivElement.style.top = "-" + popupHeight + "px"; - } - - // ms-scroll-chaining:none will still chain scroll parent element if child div does - // not have a scroll bar. Prevent this by setting and updating touch action - if (this._flyoutDivElement.scrollHeight > popupHeight) { - this._flyoutDivElement.style.touchAction = "pan-y"; - } else { - this._flyoutDivElement.style.touchAction = "none"; - } - }, - - _showFlyout: function SearchBox_showFlyout() { - - if (this._isFlyoutShown()) { - return; - } - - if (this._suggestionsData.length === 0) { - return; - } - - this._flyoutDivElement.style.display = "block"; - - // Display above vs below - var minPopupHeight = this._flyoutDivElement.clientHeight; - if (minPopupHeight < WinJS.UI.SearchBox._Constants.MIN_POPUP_HEIGHT) { - minPopupHeight = WinJS.UI.SearchBox._Constants.MIN_POPUP_HEIGHT; - } - var flyoutRect = this._flyoutDivElement.getBoundingClientRect(); - var searchBoxRect = this.element.getBoundingClientRect(); - var popupHeight = flyoutRect.bottom - flyoutRect.top; - var popupWidth = flyoutRect.right - flyoutRect.left; - var searchBoxWidth = searchBoxRect.right - searchBoxRect.left; - var documentClientHeight = document.documentElement.clientHeight; - var documentClientWidth = document.documentElement.clientWidth; - var searchBoxClientHeight = this.element.clientHeight; - var searchBoxClientLeft = this.element.clientLeft; - - var flyoutBelowSearchBox = true; - if ((searchBoxRect.bottom + minPopupHeight) <= documentClientHeight) { - // There is enough space below. Show below - this._flyoutDivElement.style.top = searchBoxClientHeight + "px"; - } else if ((searchBoxRect.top - minPopupHeight) >= 0) { - // There is enough space above. Show above - this._flyoutDivElement.style.top = "-" + popupHeight + "px"; - flyoutBelowSearchBox = false; - } else { - // Not enough space above or below. Show below. - this._flyoutDivElement.style.top = searchBoxClientHeight + "px"; - } - - // Align left vs right edge - var alignRight; - if (window.getComputedStyle(this._flyoutDivElement).direction === "rtl") { - // RTL: Align to the right edge if there is enough space to the left of the search box's - // right edge, or if there is not enough space to fit the flyout aligned to either edge. - alignRight = ((searchBoxRect.right - popupWidth) >= 0) || ((searchBoxRect.left + popupWidth) > documentClientWidth); - - } else { - // LTR: Align to the right edge if there isn't enough space to the right of the search box's - // left edge, but there is enough space to the left of the search box's right edge. - alignRight = ((searchBoxRect.left + popupWidth) > documentClientWidth) && ((searchBoxRect.right - popupWidth) >= 0); - } - - if (alignRight) { - this._flyoutDivElement.style.left = (searchBoxWidth - popupWidth - searchBoxClientLeft) + "px"; - } else { - this._flyoutDivElement.style.left = "-" + searchBoxClientLeft + "px"; - } - - // ms-scroll-chaining:none will still chain scroll parent element if child div does - // not have a scroll bar. Prevent this by setting and updating touch action - if (this._flyoutDivElement.scrollHeight > popupHeight) { - this._flyoutDivElement.style.touchAction = "pan-y"; - } else { - this._flyoutDivElement.style.touchAction = "none"; - } - - this._addFlyoutIMEPaddingIfRequired(); - - if (this._flyoutOpenPromise) { - this._flyoutOpenPromise.cancel(); - this._flyoutOpenPromise = null; - } - var animationKeyframe = flyoutBelowSearchBox ? "WinJS-flyoutBelowSearchBox-showPopup" : "WinJS-flyoutAboveSearchBox-showPopup"; - this._flyoutOpenPromise = WinJS.UI.Animation.showPopup(this._flyoutDivElement, { top: "0px", left: "0px", keyframe: animationKeyframe }); - }, - - _hideFlyout: function SearchBox_hideFlyout() { - if (this._isFlyoutShown()) { - this._flyoutDivElement.style.display = "none"; - this._updateSearchButtonClass(); - } - }, - - _addNewSpan: function SearchBox_addNewSpan(element, innerText, insertBefore) { - // Adds new span element with specified inner text as child to element, placed before insertBefore - var spanElement = document.createElement("span"); - spanElement.innerText = innerText; - spanElement.setAttribute("aria-hidden", "true"); - utilities.addClass(spanElement, ClassName.searchboxHitHighlightSpan); - element.insertBefore(spanElement, insertBefore) - return spanElement; - }, - - _addHitHighlightedText: function SearchBox_addHitHighlightedText(element, item, text) { - if (text) { - // Remove any existing hit highlighted text spans - utilities.query("." + ClassName.searchboxHitHighlightSpan, element).forEach(function (childElement) { - childElement.parentNode.removeChild(childElement); - }); - - // Insert spans at the front of element - var firstChild = element.firstChild; - - var hitsProvided = item.hits; - if ((!hitsProvided) && (this._hitFinder !== null) && (item.kind !== SearchSuggestionKind.Separator)) { - hitsProvided = this._hitFinder.find(text); - } - - var hits = WinJS.UI.SearchBox._sortAndMergeHits(hitsProvided); - - var lastPosition = 0; - for (var i = 0; i < hits.length; i++) { - var hit = hits[i]; - - // Add previous normal text - this._addNewSpan(element, text.substring(lastPosition, hit.startPosition), firstChild); - - lastPosition = hit.startPosition + hit.length; - - // Add hit highlighted text - var spanHitHighlightedText = this._addNewSpan(element, text.substring(hit.startPosition, lastPosition), firstChild); - utilities.addClass(spanHitHighlightedText, ClassName.searchBoxFlyoutHighlightText); - } - - // Add final normal text - if (lastPosition < text.length) { - this._addNewSpan(element, text.substring(lastPosition), firstChild); - } - } - }, - - _findSuggestionElementIndex: function SearchBox_findSuggestionElementIndex(curElement) { - if (curElement) { - for (var i = 0; i < this._suggestionsData.length; i++) { - if (this._repeater.elementFromIndex(i) === curElement) { - return i; - } - } - } - return -1; - }, - - _isSuggestionSelectable: function SearchBox_isSuggestionSelectable(suggestion) { - return ((suggestion.kind === SearchSuggestionKind.Query) || - (suggestion.kind === SearchSuggestionKind.Result)); - }, - - _findNextSuggestionElementIndex: function SearchBox_findNextSuggestionElementIndex(curIndex) { - // Returns -1 if there are no focusable elements after curIndex - // Returns first element if curIndex < 0 - var startIndex = curIndex + 1; - if (startIndex < 0) { - startIndex = 0; - } - - for (var i = startIndex; i < this._suggestionsData.length; i++) { - if ((this._repeater.elementFromIndex(i)) && (this._isSuggestionSelectable(this._suggestionsData.getAt(i)))) { - return i; - } - } - return -1; - }, - - _findPreviousSuggestionElementIndex: function SearchBox_findPreviousSuggestionElementIndex(curIndex) { - // Returns -1 if there are no focusable elements before curIndex - // Returns last element if curIndex >= suggestionsdata.length - var startIndex = curIndex - 1; - if (startIndex >= this._suggestionsData.length) { - startIndex = this._suggestionsData.length - 1; - } - - for (var i = startIndex; i >= 0; i--) { - if ((this._repeater.elementFromIndex(i)) && (this._isSuggestionSelectable(this._suggestionsData.getAt(i)))) { - return i; - } - } - return -1; - }, - - _trySetFocusOnSuggestionIndex: function SearchBox_trySetFocusOnSuggestionIndex(index) { - try { - this._repeater.elementFromIndex(index).focus(); - } catch (e) { - } - }, - - _updateFakeFocus: function SearchBox_updateFakeFocus() { - var firstElementIndex; - if (this._isFlyoutShown() && (this._chooseSuggestionOnEnter)) { - firstElementIndex = this._findNextSuggestionElementIndex(-1); - } else { - // This will clear the fake focus. - firstElementIndex = -1; - } - - this._selectSuggestionAtIndex(firstElementIndex); - }, - - _updateSearchButtonClass: function SearchBox_updateSearchButtonClass() { - if ((this._currentSelectedIndex !== -1) || (document.activeElement !== this._inputElement)) { - // Focus is not in input. remove class - utilities.removeClass(this._buttonElement, ClassName.searchBoxButtonInputFocus); - } else if (document.activeElement === this._inputElement) { - utilities.addClass(this._buttonElement, ClassName.searchBoxButtonInputFocus); - } - }, - - _selectSuggestionAtIndex: function SearchBox_selectSuggestionAtIndex(indexToSelect) { - // Sets focus on the specified element and removes focus from others. - // Clears selection if index is outside of suggestiondata index range. - var curElement = null; - for (var i = 0; i < this._suggestionsData.length; i++) { - curElement = this._repeater.elementFromIndex(i); - if (i !== indexToSelect) { - utilities.removeClass(curElement, ClassName.searchBoxSuggestionSelected); - curElement.setAttribute("aria-selected", "false"); - } else { - utilities.addClass(curElement, ClassName.searchBoxSuggestionSelected); - this._scrollToView(curElement); - curElement.setAttribute("aria-selected", "true"); - } - } - this._updateSearchButtonClass(); - this._currentSelectedIndex = indexToSelect; - if (curElement) { - this._inputElement.setAttribute("aria-activedescendant", this._repeaterDivElement.id + indexToSelect); - } else if (this._inputElement.hasAttribute("aria-activedescendant")) { - this._inputElement.removeAttribute("aria-activedescendant"); - } - }, - - _scrollToView: function SearchBox_scrollToView(targetElement) { - var popupHeight = this._flyoutDivElement.getBoundingClientRect().bottom - this._flyoutDivElement.getBoundingClientRect().top; - if ((targetElement.offsetTop + targetElement.offsetHeight) > (this._flyoutDivElement.scrollTop + popupHeight)) { - // Element to scroll is below popup visible area - var scrollDifference = (targetElement.offsetTop + targetElement.offsetHeight) - (this._flyoutDivElement.scrollTop + popupHeight); - this._flyoutDivElement.msZoomTo({ contentX: 0, contentY: (this._flyoutDivElement.scrollTop + scrollDifference), viewportX: 0, viewportY: 0 }); - } else if (targetElement.offsetTop < this._flyoutDivElement.scrollTop) { - // Element to scroll is above popup visible area - this._flyoutDivElement.msZoomTo({ contentX: 0, contentY: targetElement.offsetTop, viewportX: 0, viewportY: 0 }); - } - }, - - _querySuggestionRenderer: function SearchBox_querySuggestionRenderer(item) { - var root = document.createElement("div"); - - this._addHitHighlightedText(root, item, item.text); - root.title = item.text; - - utilities.addClass(root, ClassName.searchBoxSuggestionQuery); - - var that = this; - root.addEventListener('click', function (ev) { - that._inputElement.focus(); - that._processSuggestionChosen(item, ev); - }); - - root.setAttribute("role", "option"); - var ariaLabel = WinJS.Resources._formatString(strings.ariaLabelQuery, item.text); - root.setAttribute("aria-label", ariaLabel); - return root; - }, - - _separatorSuggestionRenderer: function SearchBox_separatorSuggestionRenderer(item) { - var root = document.createElement("div"); - if (item.text.length > 0) { - var textElement = document.createElement("div"); - textElement.innerText = item.text; - textElement.title = item.text; - textElement.setAttribute("aria-hidden", "true"); - root.appendChild(textElement); - } - root.insertAdjacentHTML("beforeend", "
    "); - utilities.addClass(root, ClassName.searchBoxSuggestionSeparator); - root.setAttribute("role", "separator"); - var ariaLabel = WinJS.Resources._formatString(strings.ariaLabelSeparator, item.text); - root.setAttribute("aria-label", ariaLabel); - return root; - }, - - _resultSuggestionRenderer: function SearchBox_resultSuggestionRenderer(item) { - var root = document.createElement("div"); - var image = new Image; - image.style.opacity = 0; - var loadImage = function (url) { - function onload() { - image.removeEventListener("load", onload, false); - WinJS.UI.Animation.fadeIn(image); - } - image.addEventListener("load", onload, false); - image.src = url; - }; - - if (item.image !== null) { - item.image.openReadAsync().then(function (streamWithContentType) { - if (streamWithContentType !== null) { - loadImage(URL.createObjectURL(streamWithContentType, { oneTimeOnly: true })); - } - }); - } else if (item.imageUrl != null) { - loadImage(item.imageUrl); - } - image.setAttribute("aria-hidden", "true"); - root.appendChild(image); - - var divElement = document.createElement("div"); - utilities.addClass(divElement, ClassName.searchBoxSuggestionResultText); - this._addHitHighlightedText(divElement, item, item.text); - divElement.title = item.text; - divElement.setAttribute("aria-hidden", "true"); - root.appendChild(divElement); - - var brElement = document.createElement("br"); - divElement.appendChild(brElement); - - var divDetailElement = document.createElement("span"); - utilities.addClass(divDetailElement, ClassName.searchBoxSuggestionResultDetailedText); - this._addHitHighlightedText(divDetailElement, item, item.detailText); - divDetailElement.title = item.detailText; - divDetailElement.setAttribute("aria-hidden", "true"); - divElement.appendChild(divDetailElement); - - utilities.addClass(root, ClassName.searchBoxSuggestionResult); - - var that = this; - root.addEventListener('click', function (ev) { - that._inputElement.focus(); - that._processSuggestionChosen(item, ev); - }); - - root.setAttribute("role", "option"); - var ariaLabel = WinJS.Resources._formatString(strings.ariaLabelResult, item.text, item.detailText); - root.setAttribute("aria-label", ariaLabel); - return root; - }, - - _suggestionRenderer: function SearchBox_suggestionRenderer(item) { - var root = null; - if (!item) { - return root; - } - if (item.kind === SearchSuggestionKind.Query) { - root = this._querySuggestionRenderer(item); - } else if (item.kind === SearchSuggestionKind.Separator) { - root = this._separatorSuggestionRenderer(item); - } else if (item.kind === SearchSuggestionKind.Result) { - root = this._resultSuggestionRenderer(item); - } else { - throw new WinJS.ErrorFromName("WinJS.UI.SearchBox.invalidSearchBoxSuggestionKind", strings.invalidSearchBoxSuggestionKind); - } - - return root; - }, - - _setElement: function SearchBox_setElement(element) { - this._domElement = element; - utilities.addClass(this._domElement, ClassName.searchBox); - - this._inputElement = document.createElement("input"); - this._inputElement.type = "search"; - utilities.addClass(this._inputElement, ClassName.searchBoxInput); - - this._buttonElement = document.createElement("div"); - this._buttonElement.tabIndex = -1; - utilities.addClass(this._buttonElement, ClassName.searchBoxButton); - - this._flyoutDivElement = document.createElement('div'); - utilities.addClass(this._flyoutDivElement, ClassName.searchBoxFlyout); - - this._repeaterDivElement = document.createElement('div'); - this._suggestionsData = new WinJS.Binding.List(); - this._repeater = new WinJS.UI.Repeater(this._repeaterDivElement, { data: this._suggestionsData, template: this._suggestionRendererBind }); - - this._domElement.appendChild(this._inputElement); - this._domElement.appendChild(this._buttonElement); - this._domElement.appendChild(this._flyoutDivElement); - this._flyoutDivElement.appendChild(this._repeaterDivElement); - this._hideFlyout(); - - this._wireupUserEvents(); - this._wireupWinRTEvents(); - this._wireupRepeaterEvents(); - }, - - _setAccessibilityProperties: function Searchbox_setAccessibilityProperties() { - // Set up accessibility properties - var label = this._domElement.getAttribute("aria-label"); - if (!label) { - this._domElement.setAttribute("aria-label", strings.ariaLabel); - } - this._domElement.setAttribute("role", "group"); - this._updateInputElementAriaLabel(); - this._inputElement.setAttribute("role", "textbox"); - this._buttonElement.setAttribute("role", "button"); - this._buttonElement.setAttribute("aria-label", strings.ariaLabelButton); - this._repeaterDivElement.setAttribute("role", "listbox"); - WinJS.UI._ensureId(this._repeaterDivElement); - this._inputElement.setAttribute("aria-controls", this._repeaterDivElement.id); - this._repeaterDivElement.setAttribute("aria-live", "polite"); - }, - - _updateInputElementAriaLabel: function Searchbox_updateInputElementAriaLabel() { - var ariaLabel = strings.ariaLabelInputNoPlaceHolder; - if (this._inputElement.placeholder && this._inputElement.placeholder) { - ariaLabel = WinJS.Resources._formatString(strings.ariaLabelInputPlaceHolder, this._inputElement.placeholder); - } - this._inputElement.setAttribute("aria-label", ariaLabel); - }, - - _submitQuery: function Searchbox_submitQuery(queryText, fillLinguisticDetails, event) { - if (this._disposed) { - return; - } - - // get the most up to date value of the input langauge from WinRT if available - if ((window.Windows) && (Windows.Globalization) && (Windows.Globalization.Language)) { - this._lastKeyPressLanguage = Windows.Globalization.Language.currentInputMethodLanguageTag; - } - - this._fireEvent(WinJS.UI.SearchBox._EventName.querysubmitted, { - language: this._lastKeyPressLanguage, - linguisticDetails: this._getLinguisticDetails(true /*useCache*/, fillLinguisticDetails), // allow caching, but generate empty linguistic details if suggestion is used - queryText: queryText, - keyModifiers: WinJS.UI.SearchBox._getKeyModifiers(event) - }); - - if (this._searchSuggestionManager) { - this._searchSuggestionManager.addToHistory( - this._inputElement.value, - this._lastKeyPressLanguage - ); - } - }, - - _processSuggestionChosen: function Searchbox_processSuggestionChosen(item, event) { - this.queryText = item.text; - if (item.kind === SearchSuggestionKind.Query) { - this._submitQuery(item.text, false /*fillLinguisticDetails*/, event); // force empty linguistic details since explicitly chosen suggestion from list - } else if (item.kind === SearchSuggestionKind.Result) { - this._fireEvent(WinJS.UI.SearchBox._EventName.resultsuggestionchosen, { - tag: item.tag, - keyModifiers: WinJS.UI.SearchBox._getKeyModifiers(event), - storageFile: null - }); - } - this._hideFlyout(); - }, - - _buttonClickHandler: function SearchBox_buttonClickHandler(event) { - this._inputElement.focus(); - this._submitQuery(this._inputElement.value, true /*fillLinguisticDetails*/, event); - this._hideFlyout(); - }, - - _inputOrImeChangeHandler: function SearchBox_inputImeChangeHandler(event) { - var isButtonDown = this._buttonElement.msMatchesSelector(":active"); - // swallow the IME change event that gets fired when composition is ended due to keyboarding down to the suggestion list & mouse down on the button - if (!this._isProcessingImeFocusLossKey() && !isButtonDown && !this._isFlyoutPointerDown) { - var linguisticDetails = this._getLinguisticDetails(false /*useCache*/, true /*createFilled*/); // never cache on explicit user changes - var hasLinguisticDetailsChanged = this._hasLinguisticDetailsChanged(linguisticDetails); // updates this._prevLinguisticDetails - - // Keep the previous composition cache up to date, execpt when composition ended with no text change and alternatives are kept. - // In that case, we need to use the cached values to correctly generate the query prefix/suffix for substituting alternatives, but still report to the client that the composition has ended (via start & length of composition of 0) - if ((this._inputElement.value !== this._prevQueryText) || (this._prevCompositionLength == 0) || (linguisticDetails.queryTextCompositionLength > 0)) { - this._prevCompositionStart = linguisticDetails.queryTextCompositionStart; - this._prevCompositionLength = linguisticDetails.queryTextCompositionLength; - } - - if ((this._prevQueryText === this._inputElement.value) && !hasLinguisticDetailsChanged) { - // Sometimes the input change is fired even if there is no change in input. - // Swallow event in those cases. - return; - } - this._prevQueryText = this._inputElement.value; - - // get the most up to date value of the input langauge from WinRT if available - if ((window.Windows) && (Windows.Globalization) && (Windows.Globalization.Language)) { - this._lastKeyPressLanguage = Windows.Globalization.Language.currentInputMethodLanguageTag; - } - - if ((window.Windows) && (Windows.Data) && (Windows.Data.Text) && (Windows.Data.Text.SemanticTextQuery)) { - if (this._inputElement.value !== "") { - this._hitFinder = new Windows.Data.Text.SemanticTextQuery(this._inputElement.value, this._lastKeyPressLanguage); - } else { - this._hitFinder = null; - } - } - - this._fireEvent(WinJS.UI.SearchBox._EventName.querychanged, { - language: this._lastKeyPressLanguage, - queryText: this._inputElement.value, - linguisticDetails: linguisticDetails - }); - var queryTextCompositionStart = null; - var queryTextCompositionLength = null; - var queryTextAlternatives = null; - if (this._searchSuggestionManager) { - this._searchSuggestionManager.setQuery( - this._inputElement.value, - this._lastKeyPressLanguage, - linguisticDetails - ); - } - } - }, - - _createSearchQueryLinguisticDetails: function SearchBox_createSearchQueryLinguisticDetails(compositionAlternatives, compositionStartOffset, compositionLength, queryTextPrefix, queryTextSuffix) { - var linguisticDetails = null; - - // The linguistic alternatives we receive are only for the composition string being composed. We need to provide the linguistic alternatives - // in the form of the full query text with alternatives embedded. - var fullCompositionAlternatives = []; - for (var i = 0; i < compositionAlternatives.length; i++) { - fullCompositionAlternatives[i] = queryTextPrefix + compositionAlternatives[i] + queryTextSuffix; - } - - if ((window.Windows) && (Windows.ApplicationModel) && (Windows.ApplicationModel.Search) && (Windows.ApplicationModel.Search.SearchQueryLinguisticDetails)) { - linguisticDetails = new Windows.ApplicationModel.Search.SearchQueryLinguisticDetails(fullCompositionAlternatives, compositionStartOffset, compositionLength); - } - else { - // If we're in web compartment, create a script version of the WinRT SearchQueryLinguisticDetails object - linguisticDetails = { - queryTextAlternatives: fullCompositionAlternatives, - queryTextCompositionStart: compositionStartOffset, - queryTextCompositionLength: compositionLength - }; - } - return linguisticDetails; - }, - - _getLinguisticDetails: function SearchBox_getLinguisticDetails(useCache, createFilled) { // createFilled=false always creates an empty linguistic details object, otherwise generate it or use the cache - var linguisticDetails = null; - if ((this._inputElement.value === this._prevQueryText) && useCache && this._prevLinguisticDetails && createFilled) { - linguisticDetails = this._prevLinguisticDetails; - } - else { - var compositionAlternatives = []; - var compositionStartOffset = 0; - var compositionLength = 0; - var queryTextPrefix = ""; - var queryTextSuffix = ""; - if (createFilled && this._inputElement.msGetInputContext && this._inputElement.msGetInputContext().getCompositionAlternatives) { - var context = this._inputElement.msGetInputContext(); - compositionAlternatives = context.getCompositionAlternatives(); - compositionStartOffset = context.compositionStartOffset; - compositionLength = context.compositionEndOffset - context.compositionStartOffset; - - if ((this._inputElement.value !== this._prevQueryText) || (this._prevCompositionLength == 0) || (compositionLength > 0)) { - queryTextPrefix = this._inputElement.value.substring(0, compositionStartOffset); - queryTextSuffix = this._inputElement.value.substring(compositionStartOffset + compositionLength); - } - else { - // composition ended, but alternatives have been kept, need to reuse the previous query prefix/suffix, but still report to the client that the composition has ended (start & length of composition of 0) - queryTextPrefix = this._inputElement.value.substring(0, this._prevCompositionStart); - queryTextSuffix = this._inputElement.value.substring(this._prevCompositionStart + this._prevCompositionLength); - } - } - linguisticDetails = this._createSearchQueryLinguisticDetails(compositionAlternatives, compositionStartOffset, compositionLength, queryTextPrefix, queryTextSuffix); - } - return linguisticDetails; - }, - - _handleTabKeyDown: function SearchBox_handleTabKeyDown(event) { - var closeFlyout = true; - if (event.shiftKey) { - // If focus is not in input - if (this._currentFocusedIndex !== -1) { - // Remove selection. - this._currentFocusedIndex = -1; - this._selectSuggestionAtIndex(this._currentFocusedIndex); - this._updateSearchButtonClass(); - event.preventDefault(); - event.stopPropagation(); - closeFlyout = false; - } - } else if (this._currentFocusedIndex === -1) { - if (this._isFlyoutBelow()) { - // Move to first element - this._currentFocusedIndex = this._findNextSuggestionElementIndex(this._currentFocusedIndex); - } else { - // Move to last element - this._currentFocusedIndex = this._findPreviousSuggestionElementIndex(this._suggestionsData.length); - } - if (this._currentFocusedIndex != -1) { - this._selectSuggestionAtIndex(this._currentFocusedIndex); - this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); - this._updateSearchButtonClass(); - event.preventDefault(); - event.stopPropagation(); - closeFlyout = false; - } - } - - if (closeFlyout) { - this._hideFlyout(); - } - }, - - _keyDownHandler: function SearchBox_keyDownHandler(event) { - this._lastKeyPressLanguage = event.locale; - if (event.key === "Tab") { - this._isProcessingTabKey = true; - } - else if (event.key === "Up") { - this._isProcessingUpKey = true; - } - else if (event.key === "Down") { - this._isProcessingDownKey = true; - } - else if ((event.key === "Enter") && (event.locale === "ko")) { - this._isProcessingEnterKey = true; - } - // Ignore keys handled by ime. - if (event.keyCode !== WinJS.UI.SearchBox._Constants.IME_HANDLED_KEYCODE) { - if (event.key === "Tab") { - this._handleTabKeyDown(event); - } else if (event.key === "Esc") { - // If focus is not in input - if (this._currentFocusedIndex !== -1) { - this.queryText = this._prevQueryText; - this._currentFocusedIndex = -1; - this._selectSuggestionAtIndex(this._currentFocusedIndex); - this._updateSearchButtonClass(); - event.preventDefault(); - event.stopPropagation(); - } else if (this.queryText !== "") { - this.queryText = ""; - this._inputOrImeChangeHandler(null); - this._updateSearchButtonClass(); - event.preventDefault(); - event.stopPropagation(); - } - } else if (event.key === "Up") { - var prevIndex; - if (this._currentSelectedIndex !== -1) { - prevIndex = this._findPreviousSuggestionElementIndex(this._currentSelectedIndex); - // Restore user entered query when user navigates back to input. - if (prevIndex === -1) { - this.queryText = this._prevQueryText; - } - } else { - prevIndex = this._findPreviousSuggestionElementIndex(this._suggestionsData.length); - } - this._currentFocusedIndex = prevIndex; - this._selectSuggestionAtIndex(prevIndex); - this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); - this._updateSearchButtonClass(); - event.preventDefault(); - event.stopPropagation(); - } else if (event.key === "Down") { - var nextIndex = this._findNextSuggestionElementIndex(this._currentSelectedIndex); - // Restore user entered query when user navigates back to input. - if ((this._currentSelectedIndex !== -1) && (nextIndex === -1)) { - this.queryText = this._prevQueryText; - } - this._currentFocusedIndex = nextIndex; - this._selectSuggestionAtIndex(nextIndex); - this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); - this._updateSearchButtonClass(); - event.preventDefault(); - event.stopPropagation(); - } else if (event.key === "Enter") { - if (this._currentSelectedIndex === -1) { - this._submitQuery(this._inputElement.value, true /*fillLinguisticDetails*/, event); - } else { - this._processSuggestionChosen(this._suggestionsData.getAt(this._currentSelectedIndex), event); - } - this._hideFlyout(); - } else if (WinJS.UI.SearchBox._isTypeToSearchKey(event)) { - // Type to search on suggestions scenario. - if (this._currentFocusedIndex !== -1) { - this._currentFocusedIndex = -1; - this._selectSuggestionAtIndex(-1); - this._updateFakeFocus(); - } - } - } - }, - - _keyPressHandler: function SearchBox_keyPressHandler(event) { - this._lastKeyPressLanguage = event.locale; - }, - - _keyUpHandler: function SearchBox_keyUpHandler(event) { - if (event.key === "Tab") { - this._isProcessingTabKey = false; - } - else if (event.key === "Up") { - this._isProcessingUpKey = false; - } - else if (event.key === "Down") { - this._isProcessingDownKey = false; - } - else if (event.key === "Enter") { - this._isProcessingEnterKey = false; - } - }, - - _searchBoxFocusInHandler: function SearchBox__searchBoxFocusInHandler(event) { - // Refresh hit highlighting if text has changed since focus was present - // This can happen if the user committed a suggestion previously. - if (this._inputElement.value !== this._prevQueryText) { - if ((window.Windows) && (Windows.Data) && (Windows.Data.Text) && (Windows.Data.Text.SemanticTextQuery)) { - if (this._inputElement.value !== "") { - this._hitFinder = new Windows.Data.Text.SemanticTextQuery(this._inputElement.value, this._inputElement.lang); - } else { - this._hitFinder = null; - } - } - } - - // If focus is returning to the input box from outside the search control, show the flyout and refresh the suggestions - if ((event.target === this._inputElement) && !this._isElementInSearchControl(event.relatedTarget)) { - this._showFlyout(); - // If focus is not in input - if (this._currentFocusedIndex !== -1) { - this._selectSuggestionAtIndex(this._currentFocusedIndex); - } else { - this._updateFakeFocus(); - } - - if (this._searchSuggestionManager) { - this._searchSuggestionManager.setQuery( - this._inputElement.value, - this._lastKeyPressLanguage, - this._getLinguisticDetails(true /*useCache*/, true /*createFilled*/) - ); - } - } - - utilities.addClass(this.element, ClassName.searchBoxInputFocus); - this._updateSearchButtonClass(); - }, - - _searchBoxFocusOutHandler: function SearchBox_searchBoxFocusOutHandler(event) { - this._hideFlyoutIfLeavingSearchControl(event.relatedTarget); - utilities.removeClass(this.element, ClassName.searchBoxInputFocus); - this._updateSearchButtonClass(); - this._isProcessingDownKey = false; - this._isProcessingUpKey = false; - this._isProcessingTabKey = false; - this._isProcessingEnterKey = false; - }, - - _isIMEOccludingFlyout: function SearchBox_isIMEOccludingFlyout(imeRect) { - var flyoutTop = this._getFlyoutTop(); - var flyoutBottom = this._getFlyoutBottom(); - if (((imeRect.top >= flyoutTop) && (imeRect.top <= flyoutBottom)) || - ((imeRect.bottom >= flyoutTop) && (imeRect.bottom <= flyoutBottom))) { - return true; - } - return false; - }, - - _addFlyoutIMEPaddingIfRequired: function SearchBox_addFlyoutIMEPaddingIfRequired() { - if (this._isFlyoutShown() && this._isFlyoutBelow() && this._inputElement.msGetInputContext && this._inputElement.msGetInputContext()) { - var context = this._inputElement.msGetInputContext(); - var rect = context.getCandidateWindowClientRect(); - if (this._isIMEOccludingFlyout(rect)) { - var animation = WinJS.UI.Animation.createRepositionAnimation(this._flyoutDivElement.children); - this._flyoutDivElement.style.paddingTop = (rect.bottom - rect.top) + "px"; - animation.execute(); - } - } - }, - - _msCandidateWindowShowHandler: function SearchBox_msCandidateWindowShowHandler(event) { - this._addFlyoutIMEPaddingIfRequired(); - this._reflowImeOnPointerRelease = false; - }, - - _msCandidateWindowHideHandler: function SearchBox_msCandidateWindowHideHandler(event) { - if (!this._isFlyoutPointerDown) { - var animation = WinJS.UI.Animation.createRepositionAnimation(this._flyoutDivElement.children); - this._flyoutDivElement.style.paddingTop = ""; - animation.execute(); - } - else { - this._reflowImeOnPointerRelease = true; - } - }, - - _wireupUserEvents: function SearchBox_wireupUserEvents() { - var inputOrImeChangeHandler = this._inputOrImeChangeHandler.bind(this); - this._buttonElement.addEventListener("click", this._buttonClickHandler.bind(this)); - this._inputElement.addEventListener("input", inputOrImeChangeHandler); - this._inputElement.addEventListener("keydown", this._keyDownHandler.bind(this)); - this._inputElement.addEventListener("keypress", this._keyPressHandler.bind(this)); - this._inputElement.addEventListener("keyup", this._keyUpHandler.bind(this)); - this._inputElement.addEventListener("pointerdown", this._inputPointerDownHandler.bind(this)); - this._flyoutDivElement.addEventListener("pointerdown", this._flyoutPointerDownHandler.bind(this)); - this._flyoutDivElement.addEventListener("pointerup", this._flyoutPointerReleasedHandler.bind(this)); - this._flyoutDivElement.addEventListener("pointercancel", this._flyoutPointerReleasedHandler.bind(this)); - this._flyoutDivElement.addEventListener("pointerout", this._flyoutPointerReleasedHandler.bind(this)); - this.element.addEventListener("focusin", this._searchBoxFocusInHandler.bind(this)); - this.element.addEventListener("focusout", this._searchBoxFocusOutHandler.bind(this)); - - this._inputElement.addEventListener("compositionstart", inputOrImeChangeHandler); - this._inputElement.addEventListener("compositionupdate", inputOrImeChangeHandler); - this._inputElement.addEventListener("compositionend", inputOrImeChangeHandler); - - if (this._inputElement.msGetInputContext && this._inputElement.msGetInputContext()) { - var context = this._inputElement.msGetInputContext(); - context.addEventListener("MSCandidateWindowShow", this._msCandidateWindowShowHandler.bind(this)); - context.addEventListener("MSCandidateWindowHide", this._msCandidateWindowHideHandler.bind(this)); - } - }, - - _repeaterChangedHandler: function SearchBox_repeaterChangedHandler(ev) { - this._updateFlyoutTopAndTouchAction(); - if (this._isFlyoutShown()) { - this._repeaterDivElement.style.display = "none"; - this._repeaterDivElement.style.display = "block"; - } - }, - - _wireupRepeaterEvents: function SearchBox_wireupRepeaterEvents() { - var repeaterChangeHandler = this._repeaterChangedHandler.bind(this); - this._repeater.addEventListener("itemchanged", repeaterChangeHandler); - this._repeater.addEventListener("iteminserted", repeaterChangeHandler); - this._repeater.addEventListener("itemremoved", repeaterChangeHandler); - this._repeater.addEventListener("itemsreloaded", repeaterChangeHandler); - }, - - _inputPointerDownHandler: function SearchBox_inputPointerDownHandler(ev) { - if ((document.activeElement === this._inputElement) && (this._currentSelectedIndex !== -1)) { - this._currentFocusedIndex = -1; - this._selectSuggestionAtIndex(this._currentFocusedIndex); - } - }, - - _flyoutPointerDownHandler: function SearchBox_flyoutPointerDownHandler(ev) { - this._isFlyoutPointerDown = true; - var srcElement = ev.srcElement; - while (srcElement && (srcElement.parentNode !== this._repeaterDivElement)) { - srcElement = srcElement.parentNode; - } - var index = this._findSuggestionElementIndex(srcElement); - if ((index >= 0) && (index < this._suggestionsData.length) && (this._currentFocusedIndex !== index)) { - if (this._isSuggestionSelectable(this._suggestionsData.getAt(index))) { - this._currentFocusedIndex = index; - this._selectSuggestionAtIndex(index); - this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); - } - } - // Prevent default so focus does not leave input element. - ev.preventDefault(); - }, - - _flyoutPointerReleasedHandler: function SearchBox_flyoutPointerReleasedHandler(ev) { - this._isFlyoutPointerDown = false; - - if (this._reflowImeOnPointerRelease) { - this._reflowImeOnPointerRelease = false; - var animation = WinJS.UI.Animation.createRepositionAnimation(this._flyoutDivElement.children); - this._flyoutDivElement.style.paddingTop = ""; - animation.execute(); - } - }, - - _isElementInSearchControl: function SearchBox_isElementInSearchControl(targetElement) { - return this.element.contains(targetElement) || (this.element === targetElement); - }, - - _hideFlyoutIfLeavingSearchControl: function SearchBox__hideFlyoutIfLeavingSearchControl(targetElement) { - if (!this._isFlyoutShown()) { - return; - } - if (!this._isElementInSearchControl(targetElement)) { - this._hideFlyout(); - } - }, - - _wireupWinRTEvents: function SearchBox_wireupWinRTEvents() { - if (this._searchSuggestions) { - this._searchSuggestions.addEventListener("vectorchanged", this._suggestionsChangedHandlerBind); - } - if (this._searchSuggestionManager) { - this._searchSuggestionManager.addEventListener("suggestionsrequested", this._suggestionsRequestedHandlerBind); - } - }, - - _suggestionsChangedHandler: function SearchBox_suggestionsChangedHandler(event) { - var collectionChange = event.collectionChange; - if (collectionChange === Windows.Foundation.Collections.CollectionChange.reset) { - if (this._isFlyoutShown()) { - this._hideFlyout(); - } - this._suggestionsData.splice(0, this._suggestionsData.length); - } else if (collectionChange === Windows.Foundation.Collections.CollectionChange.itemInserted) { - var index = event.index; - var suggestion = this._searchSuggestions[index]; - this._suggestionsData.splice(index, 0, suggestion); - - this._showFlyout(); - - } else if (collectionChange === Windows.Foundation.Collections.CollectionChange.itemRemoved) { - if ((this._suggestionsData.length === 1)) { - try { - this._inputElement.setActive(); - } catch (e) { - } - this._hideFlyout(); - } - var index = event.index; - this._suggestionsData.splice(index, 1); - } else if (collectionChange === Windows.Foundation.Collections.CollectionChange.itemChanged) { - var index = event.index; - var suggestion = this._searchSuggestions[index]; - if (suggestion !== this._suggestionsData.getAt(index)) { - this._suggestionsData.setAt(index, suggestion); - } else { - // If the suggestions manager gives us an identical item, it means that only the hit highlighted text has changed. - var existingElement = this._repeater.elementFromIndex(index); - if (utilities.hasClass(existingElement, ClassName.searchBoxSuggestionQuery)) { - this._addHitHighlightedText(existingElement, suggestion, suggestion.text); - } - else { - var resultSuggestionDiv = existingElement.querySelector("." + ClassName.searchBoxSuggestionResultText); - if (resultSuggestionDiv) { - this._addHitHighlightedText(resultSuggestionDiv, suggestion, suggestion.text); - var resultSuggestionDetailDiv = existingElement.querySelector("." + ClassName.searchBoxSuggestionResultDetailedText); - if (resultSuggestionDetailDiv) { - this._addHitHighlightedText(resultSuggestionDetailDiv, suggestion, suggestion.detailText); - } - } - } - } - } - - if (document.activeElement === this._inputElement) { - this._updateFakeFocus(); - } - }, - - _suggestionsRequestedHandler: function SearchBox_suggestionsRequestedHandler(event) { - // get the most up to date value of the input langauge from WinRT if available - if ((window.Windows) && (Windows.Globalization) && (Windows.Globalization.Language)) { - this._lastKeyPressLanguage = Windows.Globalization.Language.currentInputMethodLanguageTag; - } - - var suggestionsRequestedEventDetail = event; - var deferral; - this._fireEvent(WinJS.UI.SearchBox._EventName.suggestionsrequested, { - setPromise: function (promise) { - deferral = suggestionsRequestedEventDetail.request.getDeferral(); - promise.then(function () { - deferral.complete(); - }); - }, - searchSuggestionCollection: suggestionsRequestedEventDetail.request.searchSuggestionCollection, - language: this._lastKeyPressLanguage, - linguisticDetails: this._getLinguisticDetails(true /*useCache*/, true /*createFilled*/), - queryText: this._inputElement.value - }); - }, - - _fireEvent: function SearchBox_fireEvent(type, detail) { - // Returns true if ev.preventDefault() was not called - var event = document.createEvent("CustomEvent"); - event.initCustomEvent(type, true, true, detail); - return this.element.dispatchEvent(event); - }, - - _requestingFocusOnKeyboardInputHandler: function SearchBox_requestingFocusOnKeyboardInputHandler(event) { - this._fireEvent(WinJS.UI.SearchBox._EventName.receivingfocusonkeyboardinput, null); - if (document.activeElement !== this._inputElement) { - try { - this._inputElement.focus(); - } catch (e) { - } - } - }, - - _hasLinguisticDetailsChanged: function SearchBox_hasLinguisticDetailsChanged(newLinguisticDetails) { - var hasLinguisticDetailsChanged = false; - if ((this._prevLinguisticDetails.queryTextCompositionStart !== newLinguisticDetails.queryTextCompositionStart) || - (this._prevLinguisticDetails.queryTextCompositionLength !== newLinguisticDetails.queryTextCompositionLength) || - (this._prevLinguisticDetails.queryTextAlternatives.length !== newLinguisticDetails.queryTextAlternatives.length)) { - hasLinguisticDetailsChanged = true; - } - this._prevLinguisticDetails = newLinguisticDetails; - return hasLinguisticDetailsChanged; - }, - - _isProcessingImeFocusLossKey: function SearchBox_isProcessingImeFocusLossKey() { - return this._isProcessingDownKey || this._isProcessingUpKey || this._isProcessingTabKey || this._isProcessingEnterKey; - }, - - _updateQueryTextWithSuggestionText: function SearchBox_updateQueryTextWithSuggestionText(suggestionIndex) { - if ((suggestionIndex >= 0) && (suggestionIndex < this._suggestionsData.length)) { - this.queryText = this._suggestionsData.getAt(suggestionIndex).text; - } - } - - }, { - _EventName: { - querychanged: EventName.querychanged, - querysubmitted: EventName.querysubmitted, - resultsuggestionchosen: EventName.resultsuggestionchosen, - suggestionsrequested: EventName.suggestionsrequested, - receivingfocusonkeyboardinput: EventName.receivingfocusonkeyboardinput - }, - - _Constants: { - MIN_POPUP_HEIGHT: 152, - IME_HANDLED_KEYCODE: 229 - }, - - _getKeyModifiers: function SearchBox_getKeyModifiers(ev) { - - // Returns the same value as http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.system.virtualkeymodifiers - var VirtualKeys = { - ctrlKey: 1, - altKey: 2, - shiftKey: 4 - }; - - var keyModifiers = 0; - if (ev.ctrlKey) { - keyModifiers |= VirtualKeys.ctrlKey; - } - if (ev.altKey) { - keyModifiers |= VirtualKeys.altKey; - } - if (ev.shiftKey) { - keyModifiers |= VirtualKeys.shiftKey; - } - return keyModifiers; - }, - - _sortAndMergeHits: function searchBox_sortAndMergeHits(hitsProvided) { - var reducedHits = []; - if (hitsProvided) { - // Copy hitsprovided array as winrt objects are immutable. - var hits = new Array(hitsProvided.length); - for (var i = 0; i < hitsProvided.length; i++) { - hits.push({ startPosition: hitsProvided[i].startPosition, length: hitsProvided[i].length }); - } - hits.sort(WinJS.UI.SearchBox._hitStartPositionAscendingSorter); - hits.reduce(WinJS.UI.SearchBox._hitIntersectionReducer, reducedHits); - } - return reducedHits; - }, - - _hitStartPositionAscendingSorter: function searchBox_hitStartPositionAscendingSorter(firstHit, secondHit) { - var returnValue = 0; - if (firstHit.startPosition < secondHit.startPosition) { - returnValue = -1; - } else if (firstHit.startPosition > secondHit.startPosition) { - returnValue = 1; - } - return returnValue; - }, - - _hitIntersectionReducer: function searchBox_hitIntersectionReducer(reducedHits, nextHit, currentIndex, originalList) { - if (currentIndex === 0) { - reducedHits.push(nextHit); - } else { - var curHit = reducedHits[reducedHits.length - 1]; - var curHitEndPosition = curHit.startPosition + curHit.length; - //#DBG _ASSERT(nextHit.startPosition >= curHit.startPosition); - if (nextHit.startPosition <= curHitEndPosition) { - // The next hit intersects or is next to current hit. Merge it. - var nextHitEndPosition = nextHit.startPosition + nextHit.length; - if (nextHitEndPosition > curHitEndPosition) { - curHit.length = nextHitEndPosition - curHit.startPosition; - } - } else { - // No intersection, simply add to reduced list. - reducedHits.push(nextHit); - } - } - return reducedHits; - }, - - _isTypeToSearchKey: function searchBox__isTypeToSearchKey(event) { - if (event.shiftKey || event.ctrlKey || event.altKey) { - return false; - } - return true; - } - }); - WinJS.Class.mix(SearchBox, WinJS.UI.DOMEventMixin); - return SearchBox; - }) - }); - -})(this, WinJS); - -/// appbar,Flyout,Flyouts,registeredforsettings,SettingsFlyout,Statics,Syriac -(function settingsFlyoutInit(WinJS) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// Provides users with fast, in-context access to settings that affect the current app. - /// - /// - /// Settings Flyout - /// - /// - /// - ///
    - /// - ///
    Custom Settings
    - ///
    - ///
    - /// {Your Content Here} - ///
    - /// ]]>
    - /// Raised just before showing a SettingsFlyout. - /// Raised immediately after a SettingsFlyout is fully shown. - /// Raised just before hiding a SettingsFlyout. - /// Raised immediately after a SettingsFlyout is fully hidden. - /// The SettingsFlyout control itself. - /// - /// - /// - SettingsFlyout: WinJS.Namespace._lazy(function () { - var thisWinUI = WinJS.UI; - - var focusHasHitSettingsPaneOnce; - - // Class Names - var settingsFlyoutClass = "win-settingsflyout", - fullSettingsFlyoutClassName = "." + settingsFlyoutClass, - settingsFlyoutLightClass = "win-ui-light", - narrowClass = "win-narrow", - wideClass = "win-wide"; - - var firstDivClass = "win-firstdiv"; - var finalDivClass = "win-finaldiv"; - - // Constants for width - var settingsNarrow = "narrow", - settingsWide = "wide"; - - // Determine if the settings pane (system language) is RTL or not. - function _shouldAnimateFromLeft() { - if (WinJS.Utilities.hasWinRT && Windows.UI.ApplicationSettings.SettingsEdgeLocation) { - var appSettings = Windows.UI.ApplicationSettings; - return (appSettings.SettingsPane.edge === appSettings.SettingsEdgeLocation.left); - } else { - return false; - } - }; - - // Get the settings control by matching the settingsCommandId - // if no match we'll try to match element id - function _getChildSettingsControl(parentElement, id) { - var settingElements = parentElement.querySelectorAll(fullSettingsFlyoutClassName); - var retValue, - control; - for (var i = 0; i < settingElements.length; i++) { - control = settingElements[i].winControl; - if (control) { - if (control.settingsCommandId === id) { - retValue = control; - break; - } - if (settingElements[i].id === id) { - retValue = retValue || control; - } - } - } - - return retValue; - } - - var SettingsFlyout = WinJS.Class.derive(WinJS.UI._Overlay, function SettingsFlyout_ctor(element, options) { - /// - /// Creates a new SettingsFlyout control. - /// - /// The DOM element that will host the control. - /// - /// - /// The set of properties and values to apply to the new SettingsFlyout. - /// - /// The new SettingsFlyout control. - /// - /// - - // Make sure there's an input element - this._element = element || document.createElement("div"); - this._id = this._element.id || this._element.uniqueID; - this._writeProfilerMark("constructor,StartTM"); - - // Call the base overlay constructor helper - this._baseOverlayConstructor(this._element, options); - - this._addFirstDiv(); - this._addFinalDiv(); - - // Handle "esc" & "tab" key presses - this._element.addEventListener("keydown", this._handleKeyDown, true); - - // Make a click eating div - thisWinUI._Overlay._createClickEatingDivAppBar(); - - // Start settings hidden - this._element.style.visibilty = "hidden"; - this._element.style.display = "none"; - - // Attach our css class - WinJS.Utilities.addClass(this._element, settingsFlyoutClass); - - // apply the light theme styling to the win-content elements inside the SettingsFlyout - WinJS.Utilities.query("div.win-content", this._element). - forEach(function (e) { - if (!e.msMatchesSelector('.win-ui-dark, .win-ui-dark *')) { - WinJS.Utilities.addClass(e, settingsFlyoutLightClass); - } - }); - - // Make sure we have an ARIA role - var role = this._element.getAttribute("role"); - if (role === null || role === "" || role === undefined) { - this._element.setAttribute("role", "dialog"); - } - var label = this._element.getAttribute("aria-label"); - if (label === null || label === "" || label === undefined) { - this._element.setAttribute("aria-label", strings.ariaLabel); - } - - // Make sure _Overlay event handlers are hooked up - this._addOverlayEventHandlers(true); - - // Make sure animations are hooked up - this._currentAnimateIn = this._animateSlideIn; - this._currentAnimateOut = this._animateSlideOut; - this._writeProfilerMark("constructor,StopTM"); - }, { - // Public Properties - - /// - /// Width of the SettingsFlyout, "narrow", or "wide". - /// - /// SettingsFlyout.width may be altered or unavailable in future versions. Instead, style the CSS width property on elements with the .win-settingsflyout class. - /// - /// - /// - width: { - get: function () { - return this._width; - }, - - set: function (value) { - WinJS.Utilities._deprecated(strings.widthDeprecationMessage); - if (value === this._width) { - return; - } - // Get rid of old class - if (this._width === settingsNarrow) { - WinJS.Utilities.removeClass(this._element, narrowClass); - } else if (this._width === settingsWide) { - WinJS.Utilities.removeClass(this._element, wideClass); - } - this._width = value; - - // Attach our new css class - if (this._width === settingsNarrow) { - WinJS.Utilities.addClass(this._element, narrowClass); - } else if (this._width === settingsWide) { - WinJS.Utilities.addClass(this._element, wideClass); - } - } - }, - - /// - /// Define the settings command Id for the SettingsFlyout control. - /// - /// - settingsCommandId: { - get: function () { - return this._settingsCommandId; - }, - - set: function (value) { - this._settingsCommandId = value; - } - }, - - show: function () { - /// - /// - /// Shows the SettingsFlyout, if hidden. - /// - /// - /// - // Just call private version to make appbar flags happy - - // Don't do anything if disabled - if (this.disabled) { - return; - } - this._writeProfilerMark("show,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndShow(). - this._show(); - }, - - _dispose: function SettingsFlyout_dispose() { - WinJS.Utilities.disposeSubTree(this.element); - this._dismiss(); - }, - - _show: function SettingsFlyout_show() { - // We call our base "_baseShow" because SettingsFlyout overrides show - this._baseShow(); - // Need click-eating div to be visible, - // (even if now hiding, we'll show and need click eater) - thisWinUI._Overlay._showClickEatingDivAppBar(); - }, - - _endShow: function SettingsFlyout_endShow() { - // Clean up after showing - this._initAfterAnimation(); - }, - - _initAfterAnimation: function SettingsFlyout_initAfterAnimation() { - focusHasHitSettingsPaneOnce = 0; - - // Verify that the firstDiv and finalDiv are in the correct location. - // Move them to the correct location or add them if they are not. - if (!WinJS.Utilities.hasClass(this.element.children[0], firstDivClass)) { - var firstDiv = this.element.querySelectorAll(".win-first"); - if (firstDiv && firstDiv.length > 0) { - firstDiv.item(0).parentNode.removeChild(firstDiv.item(0)); - } - - this._addFirstDiv(); - } - - // Set focus to the firstDiv - if (this.element.children[0]) { - this.element.children[0].addEventListener("focusout", function () { focusHasHitSettingsPaneOnce = 1; }, false); - this.element.children[0].focus(); - } - - if (!WinJS.Utilities.hasClass(this.element.children[this.element.children.length - 1], finalDivClass)) { - var finalDiv = this.element.querySelectorAll(".win-final"); - if (finalDiv && finalDiv.length > 0) { - finalDiv.item(0).parentNode.removeChild(finalDiv.item(0)); - } - - this._addFinalDiv(); - } - - this._setBackButtonsAriaLabel(); - }, - - _setBackButtonsAriaLabel: function SettingsFlyout_setBackButtonsAriaLabel() { - var backbuttons = this.element.querySelectorAll(".win-backbutton"); - var label; - for (var i = 0; i < backbuttons.length; i++) { - label = backbuttons[i].getAttribute("aria-label"); - if (label === null || label === "" || label === undefined) { - backbuttons[i].setAttribute("aria-label", strings.backbuttonAriaLabel); - } - } - }, - - hide: function () { - /// - /// - /// Hides the SettingsFlyout, if visible, regardless of other state. - /// - /// - /// - // Just call private version to make appbar flags happy - this._writeProfilerMark("hide,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndHide(). - this._hide(); - }, - - _hide: function SettingsFlyout_hide() { - if (this._baseHide()) { - // Need click-eating div to be hidden - thisWinUI._Overlay._hideClickEatingDivAppBar(); - } - }, - - // SettingsFlyout animations - _animateSlideIn: function SettingsFlyout_animateSlideIn() { - var animateFromLeft = _shouldAnimateFromLeft(); - var offset = animateFromLeft ? "-100px" : "100px"; - WinJS.Utilities.query("div.win-content", this._element). - forEach(function (e) { WinJS.UI.Animation.enterPage(e, { left: offset }) }); - - var where, - width = this._element.offsetWidth; - // Slide in from right side or left side? - if (animateFromLeft) { - // RTL - where = { top: "0px", left: "-" + width + "px" }; - this._element.style.right = "auto"; - this._element.style.left = "0px"; - } else { - // From right side - where = { top: "0px", left: width + "px" }; - this._element.style.right = "0px"; - this._element.style.left = "auto"; - } - - this._element.style.opacity = 1; - this._element.style.visibility = "visible"; - - return WinJS.UI.Animation.showPanel(this._element, where); - }, - - _animateSlideOut: function SettingsFlyout_animateSlideOut() { - var where, - width = this._element.offsetWidth; - if (_shouldAnimateFromLeft()) { - // RTL - where = { top: "0px", left: width + "px" }; - this._element.style.right = "auto"; - this._element.style.left = "-" + width + "px"; - } else { - // From right side - where = { top: "0px", left: "-" + width + "px" }; - this._element.style.right = "-" + width + "px"; - this._element.style.left = "auto"; - } - - return WinJS.UI.Animation.showPanel(this._element, where); - }, - - _fragmentDiv: { - get: function SettingsFlyout_fragmentDiv_get() { - return this._fragDiv; - }, - - set: function SettingsFlyout_fragmentDiv_set(value) { - this._fragDiv = value; - } - }, - - _unloadPage: function SettingsFlyout_unloadPage(event) { - var settingsControl = event.currentTarget.winControl; - settingsControl.removeEventListener(thisWinUI._Overlay.afterHide, this._unloadPage, false); - - WinJS.Promise.as().then(function () { - if (settingsControl._fragmentDiv) { - document.body.removeChild(settingsControl._fragmentDiv); - settingsControl._fragmentDiv = null; - } - }); - }, - - _dismiss: function SettingsFlyout_dismiss() { - this.addEventListener(thisWinUI._Overlay.afterHide, this._unloadPage, false); - this._hide(); - }, - - _handleKeyDown: function SettingsFlyout_handleKeyDown(event) { - if (event.key === "Esc") { - event.preventDefault(); - event.stopPropagation(); - this.winControl._dismiss(); - } else if ((event.key === "Spacebar" || event.key === "Enter") - && (this.children[0] === document.activeElement)) { - event.preventDefault(); - event.stopPropagation(); - this.winControl._dismiss(); - } else if (event.shiftKey && event.key === "Tab" - && this.children[0] === document.activeElement) { - event.preventDefault(); - event.stopPropagation(); - var _elms = this.getElementsByTagName("*"); - - for (var i = _elms.length - 2; i >= 0; i--) { - _elms[i].focus(); - - if (_elms[i] === document.activeElement) { - break; - } - } - } - }, - - _focusOnLastFocusableElementFromParent: function SettingsFlyout_focusOnLastFocusableElementFromParent() { - var active = document.activeElement; - if (!focusHasHitSettingsPaneOnce || !active || !WinJS.Utilities.hasClass(active, firstDivClass)) { - return; - } - - var _elms = this.parentElement.getElementsByTagName("*"); - - // There should be at least 1 element in addition to the firstDiv & finalDiv - if (_elms.length <= 2) { - return; - } - - // Get the tabIndex set to the finalDiv (which is the highest) - var _highestTabIndex = _elms[_elms.length - 1].tabIndex; - - // If there are positive tabIndices, set focus to the element with the highest tabIndex. - // Otherwise set focus to the last focusable element in DOM order. - if (_highestTabIndex) { - for (var i = _elms.length - 2; i > 0; i--) { - if (_elms[i].tabIndex === _highestTabIndex) { - _elms[i].focus(); - break; - } - } - } else { - for (i = _elms.length - 2; i > 0; i--) { - // Skip
    with undefined tabIndex (To work around Win8 bug #622245) - if ((_elms[i].tagName !== "DIV") || (_elms[i].getAttribute("tabIndex") !== null)) { - _elms[i].focus(); - - if (_elms[i] === document.activeElement) { - break; - } - } - } - } - }, - - _focusOnFirstFocusableElementFromParent: function SettingsFlyout_focusOnFirstFocusableElementFromParent() { - var active = document.activeElement; - if (!active || !WinJS.Utilities.hasClass(active, finalDivClass)) { - return; - } - var _elms = this.parentElement.getElementsByTagName("*"); - - // There should be at least 1 element in addition to the firstDiv & finalDiv - if (_elms.length <= 2) { - return; - } - - // Get the tabIndex set to the firstDiv (which is the lowest) - var _lowestTabIndex = _elms[0].tabIndex; - - // If there are positive tabIndices, set focus to the element with the lowest tabIndex. - // Otherwise set focus to the first focusable element in DOM order. - if (_lowestTabIndex) { - for (var i = 1; i < _elms.length - 1; i++) { - if (_elms[i].tabIndex === _lowestTabIndex) { - _elms[i].focus(); - break; - } - } - } else { - for (i = 1; i < _elms.length - 1; i++) { - // Skip
    with undefined tabIndex (To work around Win8 bug #622245) - if ((_elms[i].tagName !== "DIV") || (_elms[i].getAttribute("tabIndex") !== null)) { - _elms[i].focus(); - - if (_elms[i] === document.activeElement) { - break; - } - } - } - } - }, - - // Create and add a new first div to the beginning of the list - _addFirstDiv: function SettingsFlyout_addFirstDiv() { - var _elms = this._element.getElementsByTagName("*"); - var _minTab = 0; - for (var i = 0; i < _elms.length; i++) { - if ((0 < _elms[i].tabIndex) && (_minTab === 0 || _elms[i].tabIndex < _minTab)) { - _minTab = _elms[i].tabIndex; - } - } - var firstDiv = document.createElement("div"); - firstDiv.className = firstDivClass; - firstDiv.style.display = "inline"; - firstDiv.setAttribute("role", "menuitem"); - firstDiv.setAttribute("aria-hidden", "true"); - firstDiv.tabIndex = _minTab; - firstDiv.addEventListener("focus", this._focusOnLastFocusableElementFromParent, false); - - this._element.insertAdjacentElement("AfterBegin", firstDiv); - }, - - // Create and add a new final div to the end of the list - _addFinalDiv: function SettingsFlyout_addFinalDiv() { - var _elms = this._element.getElementsByTagName("*"); - var _maxTab = 0; - for (var i = 0; i < _elms.length; i++) { - if (_elms[i].tabIndex > _maxTab) { - _maxTab = _elms[i].tabIndex; - } - } - var finalDiv = document.createElement("div"); - finalDiv.className = finalDivClass; - finalDiv.style.display = "inline"; - finalDiv.setAttribute("role", "menuitem"); - finalDiv.setAttribute("aria-hidden", "true"); - finalDiv.tabIndex = _maxTab; - finalDiv.addEventListener("focus", this._focusOnFirstFocusableElementFromParent, false); - - this._element.appendChild(finalDiv); - }, - - _writeProfilerMark: function SettingsFlyout_writeProfilerMark(text) { - msWriteProfilerMark("WinJS.UI.SettingsFlyout:" + this._id + ":" + text); - } - }); - - // Statics - SettingsFlyout.show = function () { - /// - /// - /// Shows the SettingsPane UI, if hidden, regardless of other states. - /// - /// - /// - if (WinJS.Utilities.hasWinRT) { - Windows.UI.ApplicationSettings.SettingsPane.show(); - } - // And hide the WWA one - var elements = document.querySelectorAll('div[data-win-control="WinJS.UI.SettingsFlyout"]'); - var len = elements.length; - for (var i = 0; i < len; i++) { - var settingsFlyout = elements[i].winControl; - if (settingsFlyout) { - settingsFlyout._dismiss(); - } - } - }; - - var _settingsEvent = { event: undefined }; - SettingsFlyout.populateSettings = function (e) { - /// - /// - /// Loads a portion of the SettingsFlyout. Your app calls this when the user invokes a settings command and the WinJS.Application.onsettings event occurs. - /// - /// - /// An object that contains information about the event, received from the WinJS.Application.onsettings event. The detail property of this object contains - /// the applicationcommands sub-property that you set to an array of settings commands. - /// - /// - /// - _settingsEvent.event = e.detail; - - if (_settingsEvent.event.applicationcommands) { - var n = Windows.UI.ApplicationSettings; - Object.keys(_settingsEvent.event.applicationcommands).forEach(function (name) { - var setting = _settingsEvent.event.applicationcommands[name]; - if (!setting.title) { setting.title = name; } - var command = new n.SettingsCommand(name, setting.title, thisWinUI.SettingsFlyout._onSettingsCommand); - _settingsEvent.event.e.request.applicationCommands.append(command); - }); - } - }; - - SettingsFlyout._onSettingsCommand = function (command) { - var id = command.id; - if (_settingsEvent.event.applicationcommands && _settingsEvent.event.applicationcommands[id]) { - thisWinUI.SettingsFlyout.showSettings(id, _settingsEvent.event.applicationcommands[id].href); - } - }; - - SettingsFlyout.showSettings = function (id, path) { - /// - /// - /// Show the SettingsFlyout using the settings element identifier (ID) and the path of the page that contains the settings element. - /// - /// - /// The ID of the settings element. - /// - /// - /// The path of the page that contains the settings element. - /// - /// - /// - var control = _getChildSettingsControl(document, id); - if (control) { - control.show(); - } else if (path) { - var divElement = document.createElement("div"); - divElement = document.body.appendChild(divElement); - WinJS.UI.Pages.render(path, divElement).then(function () { - control = _getChildSettingsControl(divElement, id); - if (control) { - control._fragmentDiv = divElement; - control.show(); - } else { - document.body.removeChild(divElement); - } - }); - } else { - throw new WinJS.ErrorFromName("WinJS.UI.SettingsFlyout.BadReference", strings.badReference); - } - }; - - var strings = { - get ariaLabel() { return WinJS.Resources._getWinJSString("ui/settingsFlyoutAriaLabel").value; }, - get badReference() { return WinJS.Resources._getWinJSString("ui/badReference").value; }, - get backbuttonAriaLabel() { return WinJS.Resources._getWinJSString("ui/backbuttonarialabel").value; }, - get widthDeprecationMessage() { return WinJS.Resources._getWinJSString("ui/settingsFlyoutWidthIsDeprecated").value; }, - }; - - return SettingsFlyout; - }) - }); - - -})(WinJS); - - -(function itemContainerInit(global, WinJS, undefined) { - "use strict"; - - var utilities = WinJS.Utilities; - var createEvent = utilities._createEventProperty; - var eventNames = { - invoked: "invoked", - selectionchanging: "selectionchanging", - selectionchanged: "selectionchanged" - }; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// Defines an item that can be pressed, swiped, and dragged. - /// - /// - /// - /// HTML content
    - /// ]]> - /// Raised when the user taps or clicks the item. - /// Raised before the item is selected or deselected. - /// Raised after the item is selected or deselected. - /// Main container for the selection item control. - /// The background of a selection checkmark. - /// A selection checkmark. - /// Used to display an outline when the main container has keyboard focus. - /// - /// - /// - ItemContainer: WinJS.Namespace._lazy(function () { - var strings = { - get duplicateConstruction() { return WinJS.Resources._getWinJSString("ui/duplicateConstruction").value; } - }; - - var ItemContainer = WinJS.Class.define(function ItemContainer_ctor(element, options) { - /// - /// - /// Creates a new ItemContainer control. - /// - /// - /// The DOM element that hosts the ItemContainer control. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. - /// Each property of the options object corresponds to one of the control's properties or events. - /// Event names must begin with "on". For example, to provide a handler for the selectionchanging event, - /// add a property named "onselectionchanging" to the options object and set its value to the event handler. - /// - /// - /// The new ItemContainer control. - /// - /// - element = element || document.createElement("DIV"); - this._id = element.id || element.uniqueID; - this._writeProfilerMark("constructor,StartTM"); - - options = options || {}; - - if (element.winControl) { - throw new WinJS.ErrorFromName("WinJS.UI.ItemContainer.DuplicateConstruction", strings.duplicateConstruction); - } - - // Attaching JS control to DOM element - element.winControl = this; - - this._element = element; - WinJS.Utilities.addClass(element, "win-disposable"); - this._selectionMode = WinJS.UI.SelectionMode.single; - this._draggable = false; - this._pressedEntity = { type: WinJS.UI.ObjectType.item, index: WinJS.UI._INVALID_INDEX }; - - this.tapBehavior = WinJS.UI.TapBehavior.invokeOnly; - this.swipeOrientation = WinJS.UI.Orientation.vertical; - this.swipeBehavior = WinJS.UI.SwipeBehavior.select; - - WinJS.Utilities.addClass(this.element, WinJS.UI.ItemContainer._ClassName.itemContainer + " " + WinJS.UI._containerClass); - - this._setupInternalTree(); - - this._selection = new WinJS.UI._SingleItemSelectionManager(element, this._itemBox); - this._setTabIndex(); - - WinJS.UI.setOptions(this, options); - - this._mutationObserver = new MutationObserver(this._itemPropertyChange.bind(this)); - this._mutationObserver.observe(element, { attributes: true, attributeFilter: ["aria-selected"] }); - this._setAriaRole(); - - var that = this; - if (!this.selectionDisabled) { - setImmediate(function () { - that._setDirectionClass(); - }); - } - this._itemEventsHandler = new WinJS.UI._ItemEventsHandler(Object.create({ - containerFromElement: function (element) { - return that.element; - }, - indexForItemElement: function (element) { - return that.element.uniqueID; - }, - indexForHeaderElement: function () { - return WinJS.UI._INVALID_INDEX; - }, - itemBoxAtIndex: function (index) { - return that._itemBox; - }, - itemAtIndex: function (index) { - return that.element; - }, - headerAtIndex: function (index) { - return null; - }, - containerAtIndex: function (index) { - return that.element; - }, - isZombie: function () { - return this._disposed; - }, - getItemPosition: function (index) { - return that._getItemPosition(); - }, - rtl: function () { - return that._rtl(); - }, - fireInvokeEvent: function (itemIndex, itemElement) { - that._fireInvokeEvent(); - }, - verifySelectionAllowed: function (index) { - return that._verifySelectionAllowed(); - }, - changeFocus: function (newFocus, skipSelection, ctrlKeyDown, skipEnsureVisible, keyboardFocused) { }, - selectRange: function (firstIndex, lastIndex, additive) { - return that._selection.set({ firstIndex: firstIndex, lastIndex: lastIndex }); - } - }, { - pressedEntity: { - get: function () { - return that._pressedEntity; - }, - set: function (value) { - that._pressedEntity = value; - } - }, - pressedElement: { - enumerable: true, - set: function (value) { - that._pressedElement = value; - } - }, - eventHandlerRoot: { - enumerable: true, - get: function () { - return that.element; - } - }, - swipeBehavior: { - enumerable: true, - get: function () { - return that._swipeBehavior; - } - }, - selectionMode: { - enumerable: true, - get: function () { - return that._selectionMode; - } - }, - accessibleItemClass: { - enumerable: true, - get: function () { - // CSS class of the element with the aria role - return WinJS.UI._containerClass; - } - }, - canvasProxy: { - enumerable: true, - get: function () { - return that._captureProxy; - } - }, - tapBehavior: { - enumerable: true, - get: function () { - return that._tapBehavior; - } - }, - draggable: { - enumerable: true, - get: function () { - return that._draggable; - } - }, - selection: { - enumerable: true, - get: function () { - return that._selection; - } - }, - horizontal: { - enumerable: true, - get: function () { - return that._swipeOrientation === WinJS.UI.Orientation.vertical; - } - }, - customFootprintParent: { - enumerable: true, - get: function () { - // Use the main container as the footprint - return null; - } - }, - skipPreventDefaultOnPointerDown: { - enumerable: true, - get: function () { - return true; - } - } - })); - - function eventHandler(eventName, caseSensitive, capture) { - return { - name: (caseSensitive ? eventName : eventName.toLowerCase()), - handler: function (eventObject) { - that["_on" + eventName](eventObject); - }, - capture: capture - }; - } - var events = [ - eventHandler("MSManipulationStateChanged", true, true), - eventHandler("PointerDown"), - eventHandler("Click"), - eventHandler("PointerUp"), - eventHandler("PointerCancel"), - eventHandler("LostPointerCapture"), - eventHandler("ContextMenu"), - eventHandler("MSHoldVisual", true), - eventHandler("Focus"), - eventHandler("Blur"), - eventHandler("DragStart"), - eventHandler("DragEnd"), - eventHandler("KeyDown") - ]; - events.forEach(function (eventHandler) { - that.element.addEventListener(eventHandler.name, eventHandler.handler, !!eventHandler.capture); - }); - - this._writeProfilerMark("constructor,StopTM"); - }, { - /// - element: { - get: function () { - return this._element; - } - }, - - /// - /// Gets or sets a value that specifies whether the item can be dragged. The default value is false. - /// - /// - draggable: { - get: function () { - return this._draggable; - }, - - set: function (value) { - if (this._draggable !== value) { - this._draggable = value; - this._updateDraggableAttribute(); - } - } - }, - - /// - /// Gets or sets a value that specifies whether the item is selected. - /// - selected: { - get: function () { - return this._selection.selected; - }, - - set: function (value) { - if (this._selection.selected !== value) { - this._selection.selected = value; - } - } - }, - - /// - /// Gets or sets the swipe orientation of the ItemContainer control. - /// The default value is "vertical". - /// - swipeOrientation: { - get: function () { - return this._swipeOrientation; - }, - set: function (value) { - if (value === WinJS.UI.Orientation.vertical) { - WinJS.Utilities.removeClass(this.element, WinJS.UI.ItemContainer._ClassName.horizontal); - WinJS.Utilities.addClass(this.element, WinJS.UI.ItemContainer._ClassName.vertical); - } else { - value = WinJS.UI.Orientation.horizontal; - WinJS.Utilities.removeClass(this.element, WinJS.UI.ItemContainer._ClassName.vertical); - WinJS.Utilities.addClass(this.element, WinJS.UI.ItemContainer._ClassName.horizontal); - } - this._swipeOrientation = value; - } - }, - - /// - /// Gets or sets how the ItemContainer control reacts when the user taps or clicks an item. - /// The tap or click can invoke the item, select it and invoke it, or have no effect. - /// Possible values: "toggleSelect", "invokeOnly", and "none". The default value is "invokeOnly". - /// - tapBehavior: { - get: function () { - return this._tapBehavior; - }, - set: function (value) { - this._tapBehavior = value; - this._setAriaRole(); - } - }, - - /// - /// Gets or sets how the ItemContainer control reacts to the swipe interaction. - /// The swipe gesture can select the item or it can have no effect on the current selection. - /// Possible values: "select", "none". The default value is: "select". - /// - /// - swipeBehavior: { - get: function () { - return this._swipeBehavior; - }, - set: function (value) { - this._swipeBehavior = value; - this._setSwipeClass(); - } - }, - - /// - /// Gets or sets whether the item selection is disabled. The default value is false. - /// - selectionDisabled: { - get: function () { - return this._selectionMode === WinJS.UI.SelectionMode.none; - }, - - set: function (value) { - if (value) { - this._selectionMode = WinJS.UI.SelectionMode.none; - } else { - this._setDirectionClass(); - this._selectionMode = WinJS.UI.SelectionMode.single; - } - this._setSwipeClass(); - this._setAriaRole(); - } - }, - - /// - /// Raised when the item is invoked. You can use the tapBehavior property to specify whether taps and clicks invoke the item. - /// - oninvoked: createEvent(eventNames.invoked), - - /// - /// Raised just before the item is selected or deselected. - /// - onselectionchanging: createEvent(eventNames.selectionchanging), - - /// - /// Raised after the item is selected or deselected. - /// - onselectionchanged: createEvent(eventNames.selectionchanged), - - forceLayout: function () { - /// - /// - /// Forces the ItemContainer control to update its layout. - /// Use this function when the reading direction of the app changes after the control has been initialized. - /// - /// - this._forceLayout(); - }, - - dispose: function () { - /// - /// - /// Disposes this control. - /// - /// - - if (this._disposed) { - return; - } - this._disposed = true; - - this._itemEventsHandler.dispose(); - WinJS.Utilities.disposeSubTree(this.element); - }, - - _onMSManipulationStateChanged: function ItemContainer_onMSManipulationStateChanged(eventObject) { - this._itemEventsHandler.onMSManipulationStateChanged(eventObject); - }, - - _onPointerDown: function ItemContainer_onPointerDown(eventObject) { - this._itemEventsHandler.onPointerDown(eventObject); - }, - - _onClick: function ItemContainer_onClick(eventObject) { - this._itemEventsHandler.onClick(eventObject); - }, - - _onPointerUp: function ItemContainer_onPointerUp(eventObject) { - if (utilities.hasClass(this._itemBox, WinJS.UI._itemFocusClass)) { - this._onBlur(eventObject); - } - this._itemEventsHandler.onPointerUp(eventObject); - }, - - _onPointerCancel: function ItemContainer_onPointerCancel(eventObject) { - this._itemEventsHandler.onPointerCancel(eventObject); - }, - - _onLostPointerCapture: function ItemContainer_onLostPointerCapture(eventObject) { - this._itemEventsHandler.onLostPointerCapture(eventObject); - }, - - _onContextMenu: function ItemContainer_onContextMenu(eventObject) { - this._itemEventsHandler.onContextMenu(eventObject); - }, - - _onMSHoldVisual: function ItemContainer_onMSHoldVisual(eventObject) { - this._itemEventsHandler.onMSHoldVisual(eventObject); - }, - - _onFocus: function ItemContainer_onFocus(eventObject) { - if (this._itemBox.querySelector("." + WinJS.UI._itemFocusOutlineClass) || !WinJS.UI._keyboardSeenLast) { - return; - } - utilities.addClass(this._itemBox, WinJS.UI._itemFocusClass); - var outline = document.createElement("div"); - outline.className = WinJS.UI._itemFocusOutlineClass; - this._itemBox.appendChild(outline); - }, - - _onBlur: function ItemContainer_onBlur(eventObject) { - utilities.removeClass(this._itemBox, WinJS.UI._itemFocusClass); - var outline = this._itemBox.querySelector("." + WinJS.UI._itemFocusOutlineClass); - if (outline) { - outline.parentNode.removeChild(outline); - } - }, - - _onDragStart: function ItemContainer_onDragStart(eventObject) { - // Drag shouldn't be initiated when the user holds down the mouse on a win-interactive element and moves. - // The problem is that the dragstart event's srcElement+target will both be an itembox (which has draggable=true), so we can't check for win-interactive in the dragstart event handler. - // The itemEventsHandler sets our _pressedElement field on PointerDown, so we use that instead when checking for interactive. - if (this._pressedElement && this._itemEventsHandler._isInteractive(this._pressedElement)) { - eventObject.preventDefault(); - } else { - this._dragging = true; - var that = this; - // We delay setting the win-dragsource CSS class so that IE has time to create a thumbnail before me make it opaque - setImmediate(function () { - if (that._dragging) { - utilities.addClass(that._itemBox, WinJS.UI._dragSourceClass); - } - }); - } - }, - - _onDragEnd: function ItemContainer_onDragEnd(eventObject) { - this._dragging = false; - utilities.removeClass(this._itemBox, WinJS.UI._dragSourceClass); - this._itemEventsHandler.resetPointerDownState(); - }, - - _onKeyDown: function ItemContainer_onKeyDown(eventObject) { - if (!this._itemEventsHandler._isInteractive(eventObject.srcElement)) { - var Key = utilities.Key, - keyCode = eventObject.keyCode, - swipeEnabled = this._swipeBehavior === WinJS.UI.SwipeBehavior.select; - - var handled = false; - if (!eventObject.ctrlKey && keyCode === Key.enter) { - var allowed = this._verifySelectionAllowed(); - if (allowed.canTapSelect) { - this.selected = !this.selected; - } - this._fireInvokeEvent(); - handled = true; - } else if (eventObject.ctrlKey && keyCode === Key.enter || - (swipeEnabled && eventObject.shiftKey && keyCode === Key.F10) || - (swipeEnabled && keyCode === Key.menu) || - keyCode === Key.space) { - if (!this.selectionDisabled) { - this.selected = !this.selected; - try { - this.element.setActive(); - } catch (e) { } - handled = true; - } - } else if (keyCode === Key.escape && this.selected) { - this.selected = false; - handled = true; - } - - if (handled) { - eventObject.stopPropagation(); - eventObject.preventDefault(); - } - } - }, - - _setTabIndex: function ItemContainer_setTabIndex() { - var currentTabIndex = this.element.getAttribute("tabindex"); - if (!currentTabIndex) { - // Set the tabindex to 0 only if the application did not already - // provide a tabindex - this.element.setAttribute("tabindex", "0") - } - }, - - _rtl: function ItemContainer_rtl() { - if (typeof this._cachedRTL !== "boolean") { - this._cachedRTL = window.getComputedStyle(this.element, null).direction === "rtl"; - } - return this._cachedRTL; - }, - - _setDirectionClass: function ItemContainer_setDirectionClass() { - utilities[this._rtl() ? "addClass" : "removeClass"](this.element, WinJS.UI._rtlListViewClass); - }, - - _forceLayout: function ItemContainer_forceLayout() { - this._cachedRTL = window.getComputedStyle(this.element, null).direction === "rtl"; - this._setDirectionClass(); - }, - - _getItemPosition: function ItemContainer_getItemPosition() { - var container = this.element; - if (container) { - return WinJS.Promise.wrap({ - left: (this._rtl() ? - container.offsetParent.offsetWidth - container.offsetLeft - container.offsetWidth : - container.offsetLeft), - top: container.offsetTop, - totalWidth: utilities.getTotalWidth(container), - totalHeight: utilities.getTotalHeight(container), - contentWidth: utilities.getContentWidth(container), - contentHeight: utilities.getContentHeight(container) - }); - } else { - return WinJS.Promise.cancel; - } - }, - - _itemPropertyChange: function ItemContainer_itemPropertyChange(list) { - if (this._disposed) { return; } - - var container = list[0].target; - var ariaSelected = container.getAttribute("aria-selected") === "true"; - - // Only respond to aria-selected changes coming from UIA. This check - // relies on the fact that, in renderSelection, we update the selection - // visual before aria-selected. - if (ariaSelected !== WinJS.UI._isSelectionRendered(this._itemBox)) { - if (this.selectionDisabled) { - // Revert the change made by UIA since the control has selection disabled - WinJS.UI._setAttribute(container, "aria-selected", !ariaSelected); - } else { - this.selected = ariaSelected; - // Revert the change because the update was prevented on the selectionchanging event - if (ariaSelected !== this.selected) { - WinJS.UI._setAttribute(container, "aria-selected", !ariaSelected); - } - } - } - }, - - _setSwipeClass: function ItemContainer_setSwipeClass() { - // We apply an -ms-touch-action style to block panning and swiping from occurring at the same time. - if ((this._swipeBehavior === WinJS.UI.SwipeBehavior.select && this._selectionMode !== WinJS.UI.SelectionMode.none) || this._draggable) { - utilities.addClass(this._element, WinJS.UI._swipeableClass); - } else { - utilities.removeClass(this._element, WinJS.UI._swipeableClass); - } - }, - - _updateDraggableAttribute: function ItemContainer_setSwipeClass() { - this._setSwipeClass(); - this._itemBox.setAttribute("draggable", this._draggable); - }, - - _verifySelectionAllowed: function ItemContainer_verifySelectionAllowed() { - if (this._selectionMode !== WinJS.UI.SelectionMode.none && (this._tapBehavior === WinJS.UI.TapBehavior.toggleSelect || this._swipeBehavior === WinJS.UI.SwipeBehavior.select)) { - var canSelect = this._selection.fireSelectionChanging(); - return { - canSelect: canSelect, - canTapSelect: canSelect && this._tapBehavior === WinJS.UI.TapBehavior.toggleSelect - }; - } else { - return { - canSelect: false, - canTapSelect: false - }; - } - }, - - _setupInternalTree: function ItemContainer_setupInternalTree() { - var item = document.createElement("div"); - item.className = WinJS.UI._itemClass; - this._captureProxy = document.createElement("div"); - this._itemBox = document.createElement("div"); - this._itemBox.className = WinJS.UI._itemBoxClass; - var child = this.element.firstChild; - while (child) { - var sibling = child.nextSibling; - item.appendChild(child); - child = sibling; - } - this.element.appendChild(this._itemBox); - this._itemBox.appendChild(item); - this.element.appendChild(this._captureProxy); - }, - - _fireInvokeEvent: function ItemContainer_fireInvokeEvent() { - if (this.tapBehavior !== WinJS.UI.TapBehavior.none) { - var eventObject = document.createEvent("CustomEvent"); - eventObject.initCustomEvent(eventNames.invoked, true, false, {}); - this.element.dispatchEvent(eventObject); - } - }, - - _setAriaRole: function ItemContainer_setAriaRole() { - if (!this.element.getAttribute("role") || this._usingDefaultItemRole) { - this._usingDefaultItemRole = true; - var defaultItemRole; - if (this.tapBehavior === WinJS.UI.TapBehavior.none && this.selectionDisabled) { - defaultItemRole = "listitem"; - } else { - defaultItemRole = "option"; - } - WinJS.UI._setAttribute(this.element, "role", defaultItemRole); - } - }, - - _writeProfilerMark: function ItemContainer_writeProfilerMark(text) { - var message = "WinJS.UI.ItemContainer:" + this._id + ":" + text; - msWriteProfilerMark(message); - WinJS.log && WinJS.log(message, null, "itemcontainerprofiler"); - } - }, { - // Names of classes used by the ItemContainer. - _ClassName: { - itemContainer: "win-itemcontainer", - vertical: "win-vertical", - horizontal: "win-horizontal", - } - }); - WinJS.Class.mix(ItemContainer, WinJS.UI.DOMEventMixin); - return ItemContainer; - }), - - _SingleItemSelectionManager: WinJS.Namespace._lazy(function () { - return WinJS.Class.define(function SingleItemSelectionManager_ctor(element, itemBox) { - this._selected = false; - this._element = element; - this._itemBox = itemBox; - }, { - selected: { - get: function () { - return this._selected; - }, - set: function (value) { - value = !!value; - if (this._selected !== value) { - if (this.fireSelectionChanging()) { - this._selected = value; - WinJS.UI._ItemEventsHandler.renderSelection(this._itemBox, this._element, value, true, this._element); - this.fireSelectionChanged(); - } - } - } - }, - - count: function SingleItemSelectionManager_count() { - return this._selected ? 1 : 0; - }, - - getIndices: function SingleItemSelectionManager_getIndices() { - // not used - }, - - getItems: function SingleItemSelectionManager_getItems() { - // not used - }, - - getRanges: function SingleItemSelectionManager_getRanges() { - // not used - }, - - isEverything: function SingleItemSelectionManager_isEverything() { - return false; - }, - - set: function SingleItemSelectionManager_set(items) { - this.selected = true; - }, - - clear: function SingleItemSelectionManager_clear() { - this.selected = false; - }, - - add: function SingleItemSelectionManager_add(items) { - this.selected = true; - }, - - remove: function SingleItemSelectionManager_remove(items) { - this.selected = false; - }, - - selectAll: function SingleItemSelectionManager_selectAll() { - // not used - }, - - fireSelectionChanging: function SingleItemSelectionManager_fireSelectionChanging() { - var eventObject = document.createEvent("CustomEvent"); - eventObject.initCustomEvent(eventNames.selectionchanging, true, true, {}); - return this._element.dispatchEvent(eventObject); - }, - - fireSelectionChanged: function ItemContainer_fireSelectionChanged() { - var eventObject = document.createEvent("CustomEvent"); - eventObject.initCustomEvent(eventNames.selectionchanged, true, false, {}); - this._element.dispatchEvent(eventObject); - }, - - _isIncluded: function SingleItemSelectionManager_isIncluded(index) { - return this._selected; - }, - - _getFocused: function SingleItemSelectionManager_getFocused(index) { - return { type: WinJS.UI.ObjectType.item, index: WinJS.UI._INVALID_INDEX }; - } - }) - }) - }); - -})(this, WinJS); - -(function KeyboardBehaviorInit(global, WinJS, undefined) { - "use strict"; - - // not supported in WebWorker - if (!global.document) { - return; - } - - WinJS.UI._keyboardSeenLast = false; - - window.addEventListener("pointerdown", function (ev) { - if (WinJS.UI._keyboardSeenLast) { - WinJS.UI._keyboardSeenLast = false; - } - }, true); - - window.addEventListener("keydown", function (ev) { - if (!WinJS.UI._keyboardSeenLast) { - WinJS.UI._keyboardSeenLast = true; - } - }, true); - - WinJS.Namespace.define("WinJS.UI", { - _WinKeyboard: function (element) { - // Win Keyboard behavior is a solution that would be similar to -ms-keyboard-focus. - // It monitors the last input (keyboard/mouse) and adds/removes a win-keyboard class - // so that you can style .foo.win-keyboard:focus vs .foo:focus to add a keyboard rect - // on an item only when the last input method was keyboard. - // Reminder: Touch edgy does not count as an input method. - element.addEventListener("pointerdown", function (ev) { - // In case pointer down came on the active element. - WinJS.Utilities.removeClass(ev.srcElement, "win-keyboard"); - }, true); - element.addEventListener("keydown", function (ev) { - WinJS.Utilities.addClass(ev.srcElement, "win-keyboard"); - }, true); - element.addEventListener("focusin", function (ev) { - WinJS.UI._keyboardSeenLast && WinJS.Utilities.addClass(ev.srcElement, "win-keyboard"); - }, true); - element.addEventListener("focusout", function (ev) { - WinJS.Utilities.removeClass(ev.srcElement, "win-keyboard"); - }, true); - }, - _KeyboardBehavior: WinJS.Namespace._lazy(function () { - return WinJS.Class.define(function KeyboardBehavior_ctor(element, options) { - // KeyboardBehavior allows you to easily convert a bunch of tabable elements into a single tab stop with - // navigation replaced by keyboard arrow (Up/Down/Left/Right) + Home + End + Custom keys. - // - // Example use cases: - // - // 1 Dimensional list: FixedDirection = height and FixedSize = 1; - // [1] [ 2 ] [ 3 ] [4] [ 5 ]... - // - // 2 Dimensional list: FixedDirection = height and FixedSize = 2; - // [1] [3] [5] [7] ... - // [2] [4] [6] [8] - // - // 1 Dimensional list: FixedDirection = width and FixedSize = 1; - // [ 1 ] - // - - - // | | - // | 2 | - // | | - // - - - // [ 3 ] - // [ 4 ] - // ... - // - // 2 Dimensional list: FixedDirection = width and FixedSize = 2; - // [1][2] - // [3][4] - // [5][6] - // ... - // - // Currently it is a "behavior" instead of a "control" so it can be attached to the same element as a - // winControl. The main scenario for this would be to attach it to the same element as a repeater. - // - // It also blocks "Portaling" where you go off the end of one column and wrap around to the other - // column. It also blocks "Carousel" where you go from the end of the list to the beginning. - // - // Keyboarding behavior supports nesting. It supports your tab stops having sub tab stops. If you want - // an interactive element within the tab stop you need to use the win-interactive classname or during the - // keydown event stop propogation so that the event is skipped. - // - // If you have custom keyboarding the getAdjacent API is provided. This can be used to enable keyboarding - // in multisize 2d lists or custom keyboard commands. PageDown and PageUp are the most common since this - // behavior does not detect scrollers. - // - // It also allows developers to show/hide keyboard focus rectangles themselves. - // - // It has an API called currentIndex so that Tab (or Shift+Tab) or a developer imitating Tab will result in - // the correct item having focus. - // - // It also allows an element to be represented as 2 arrow stops (commonly used for a split button) by calling - // the _getFocusInto API on the child element's winControl if it exists. - - element = element || document.createElement("DIV"); - options = options || {}; - - element._keyboardBehavior = this; - this._element = element; - - this._fixedDirection = WinJS.UI._KeyboardBehavior.FixedDirection.width; - this._fixedSize = 1; - this._currentIndex = 0; - - WinJS.UI.setOptions(this, options); - - this._element.addEventListener('keydown', this._keyDownHandler.bind(this)); - this._element.addEventListener('pointerdown', this._MSPointerDownHandler.bind(this)); - this._element.addEventListener("beforeactivate", this._beforeActivateHandler.bind(this)); - }, { - element: { - get: function () { - return this._element; - } - }, - - fixedDirection: { - get: function () { - return this._fixedDirection; - }, - set: function (value) { - this._fixedDirection = value; - } - }, - - fixedSize: { - get: function () { - return this._fixedSize; - }, - set: function (value) { - if (+value === value) { - value = Math.max(1, value); - this._fixedSize = value; - } - } - }, - - currentIndex: { - get: function () { - if (this._element.children.length > 0) { - return this._currentIndex; - } - return -1; - }, - set: function (value) { - if (+value === value) { - var length = this._element.children.length; - value = Math.max(0, Math.min(length - 1, value)); - this._currentIndex = value; - } - } - }, - - getAdjacent: { - get: function () { - return this._getAdjacent - }, - set: function (value) { - this._getAdjacent = value; - } - }, - - _keyDownHandler: function _KeyboardBehavior_keyDownHandler(ev) { - if (!ev.altKey) { - if (ev.srcElement.msMatchesSelector(".win-interactive, .win-interactive *")) { - return; - } - var blockScrolling = false; - - var newIndex = this.currentIndex; - var maxIndex = this._element.children.length - 1; - var minIndex = 0; - - var rtl = getComputedStyle(this._element).direction === "rtl"; - var leftStr = rtl ? "Right" : "Left"; - var rightStr = rtl ? "Left" : "Right"; - - var targetIndex = this.getAdjacent && this.getAdjacent(newIndex, ev.key); - if (+targetIndex === targetIndex) { - blockScrolling = true; - newIndex = targetIndex; - } else { - var modFixedSize = newIndex % this.fixedSize; - - if (ev.key === leftStr) { - blockScrolling = true; - if (this.fixedDirection === WinJS.UI._KeyboardBehavior.FixedDirection.width) { - if (modFixedSize !== 0) { - newIndex--; - } - } else { - if (newIndex >= this.fixedSize) { - newIndex -= this.fixedSize; - } - } - } else if (ev.key === rightStr) { - blockScrolling = true; - if (this.fixedDirection === WinJS.UI._KeyboardBehavior.FixedDirection.width) { - if (modFixedSize !== this.fixedSize - 1) { - newIndex++; - } - } else { - if (newIndex + this.fixedSize - modFixedSize <= maxIndex) { - newIndex += this.fixedSize; - } - } - } else if (ev.key === "Up") { - blockScrolling = true; - if (this.fixedDirection === WinJS.UI._KeyboardBehavior.FixedDirection.height) { - if (modFixedSize !== 0) { - newIndex--; - } - } else { - if (newIndex >= this.fixedSize) { - newIndex -= this.fixedSize; - } - } - } else if (ev.key === "Down") { - blockScrolling = true; - if (this.fixedDirection === WinJS.UI._KeyboardBehavior.FixedDirection.height) { - if (modFixedSize !== this.fixedSize - 1) { - newIndex++; - } - } else { - if (newIndex + this.fixedSize - modFixedSize <= maxIndex) { - newIndex += this.fixedSize; - } - } - } else if (ev.key === "Home") { - blockScrolling = true; - newIndex = 0; - } else if (ev.key === "End") { - blockScrolling = true; - newIndex = this._element.children.length - 1; - } else if (ev.key === "PageUp") { - blockScrolling = true; - } else if (ev.key === "PageDown") { - blockScrolling = true; - } - } - - newIndex = Math.max(0, Math.min(this._element.children.length - 1, newIndex)); - - if (newIndex !== this.currentIndex) { - this._focus(newIndex, ev.key); - - // Allow KeyboardBehavior to be nested - if (ev.key === leftStr || ev.key === rightStr || ev.key === "Up" || ev.key === "Down") { - ev.stopPropagation(); - } - } - - if (blockScrolling) { - ev.preventDefault(); - } - } - }, - - _focus: function _KeyboardBehavior_focus(index, key) { - index = (+index === index) ? index : this.currentIndex; - - var elementToFocus = this._element.children[index]; - if (elementToFocus) { - if (elementToFocus.winControl && elementToFocus.winControl._getFocusInto) { - elementToFocus = elementToFocus.winControl._getFocusInto(key); - } - - this.currentIndex = index; - - try { - elementToFocus.setActive(); - } catch (e) { - } - } - }, - - _MSPointerDownHandler: function _KeyboardBehavior_MSPointerDownHandler(ev) { - var srcElement = ev.srcElement; - if (srcElement === this.element) { - return; - } - - while (srcElement.parentNode !== this.element) { - srcElement = srcElement.parentNode; - } - - var index = -1; - while (srcElement) { - index++; - srcElement = srcElement.previousElementSibling; - } - - this.currentIndex = index; - }, - - _beforeActivateHandler: function _KeyboardBehavior_beforeActivateHandler(ev) { - var allowActivate = false; - if (this._element.children.length) { - var currentItem = this._element.children[this.currentIndex]; - if (currentItem === ev.srcElement || currentItem.contains(ev.srcElement)) { - allowActivate = true; - } - } - - if (!allowActivate) { - ev.stopPropagation(); - ev.preventDefault(); - } - } - }, { - FixedDirection: { - height: "height", - width: "width" - } - }) - }) - }); - -})(this, WinJS); -(function NavBarInit(global, WinJS, undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// - /// Displays navigation commands in a toolbar that the user can show or hide. - /// - /// - /// - /// - /// - /// - ///
    - ///
    - ///
    - ///
    ]]> - /// Raised just before showing the NavBar. - /// Raised immediately after an NavBar is fully shown. - /// Raised just before hiding the NavBar. - /// Raised immediately after the NavBar is fully hidden. - /// Fired when children of NavBar control have been processed from a WinJS.UI.processAll call. - /// Styles the entire NavBar. - /// - /// - /// - NavBar: WinJS.Namespace._lazy(function () { - var childrenProcessedEventName = "childrenprocessed"; - var createEvent = WinJS.Utilities._createEventProperty; - - return WinJS.Class.derive(WinJS.UI.AppBar, function NavBar_ctor(element, options) { - /// - /// - /// Creates a new NavBar. - /// - /// - /// The DOM element that will host the new NavBar control. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. Each property of the options object corresponds to one of the control's - /// properties or events. - /// - /// - /// The new NavBar control. - /// - /// - /// - - options = options || {}; - - // Shallow copy object so we can modify it. - options = WinJS.Utilities._shallowCopy(options); - - // Default to Placement = Top and Layout = Custom - options.placement = options.placement || "top"; - options.layout = "custom"; - - WinJS.UI.AppBar.call(this, element, options); - - this._element.addEventListener("beforeshow", this._handleBeforeShow.bind(this)); - - WinJS.Utilities.addClass(this.element, WinJS.UI.NavBar._ClassName.navbar); - - if (window.Windows && Windows.ApplicationModel && Windows.ApplicationModel.DesignMode && Windows.ApplicationModel.DesignMode.designModeEnabled) { - this._processChildren(); - } else { - WinJS.Utilities.Scheduler.schedule(this._processChildren.bind(this), WinJS.Utilities.Scheduler.Priority.idle, null, "WinJS.UI.NavBar.processChildren"); - } - }, { - // Block others from setting the layout property. - - /// - /// The layout of the NavBar contents. - /// - /// - layout: { - value: "custom", - writable: false - }, - - /// - /// Raised when children of NavBar control have been processed by a WinJS.UI.processAll call. - /// - /// - onchildrenprocessed: createEvent(childrenProcessedEventName), - - _processChildren: function NavBar_processChildren() { - // The NavBar control schedules processAll on its children at idle priority to avoid hurting startup - // performance. If the NavBar is shown before the scheduler gets to the idle job, the NavBar will - // immediately call processAll on its children. If your app needs the children to be processed before - // the scheduled job executes, you may call processChildren to force the processAll call. - if (!this._processed) { - this._processed = true; - - this._writeProfilerMark("processChildren,StartTM"); - var that = this; - var processed = WinJS.Promise.as(); - if (this._processors) { - this._processors.forEach(function (processAll) { - for (var i = 0, len = that.element.children.length; i < len; i++) { - (function (child) { - processed = processed.then(function () { - processAll(child); - }); - }(that.element.children[i])); - } - }); - } - return processed.then( - function () { - that._writeProfilerMark("processChildren,StopTM"); - that._fireEvent(WinJS.UI.NavBar._EventName.childrenProcessed); - }, - function () { - that._writeProfilerMark("processChildren,StopTM"); - that._fireEvent(WinJS.UI.NavBar._EventName.childrenProcessed); - } - ); - } - return WinJS.Promise.wrap(); - }, - - _show: function NavBar_show() { - // Override _show to call processChildren first. - // - if (this.disabled) { - return; - } - var that = this; - this._processChildren().then(function () { - WinJS.UI.AppBar.prototype._show.call(that); - }); - }, - - _handleBeforeShow: function NavBar_handleBeforeShow() { - // Navbar needs to ensure its elements to have their correct height and width after AppBar changes display="none" - // to display="" and AppBar needs the elements to have their final height before it measures its own element height - // to do the slide in animation over the correct amount of pixels. - if (this._disposed) { - return; - } - - var navbarcontainerEls = this.element.querySelectorAll('.win-navbarcontainer'); - for (var i = 0; i < navbarcontainerEls.length; i++) { - navbarcontainerEls[i].winControl.forceLayout(); - } - }, - - _fireEvent: function NavBar_fireEvent(type, detail) { - var event = document.createEvent("CustomEvent"); - event.initCustomEvent(type, true, false, detail || {}); - this.element.dispatchEvent(event); - }, - - _writeProfilerMark: function NavBar_writeProfilerMark(text) { - msWriteProfilerMark("WinJS.UI.NavBar:" + this._id + ":" + text); - } - }, { - _ClassName: { - navbar: "win-navbar" - }, - _EventName: { - childrenProcessed: childrenProcessedEventName - }, - isDeclarativeControlContainer: WinJS.Utilities.markSupportedForProcessing(function (navbar, callback) { - if (navbar._processed) { - for (var i = 0, len = navbar.element.children.length; i < len; i++) { - callback(navbar.element.children[i]); - } - } else { - navbar._processors = navbar._processors || []; - navbar._processors.push(callback); - } - }) - }); - }) - }); - -})(this, WinJS); - -(function NavBarContainerInit(global, WinJS, undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// - /// Contains a group of NavBarCommand objects in a NavBar. - /// - /// - /// - /// - /// - /// - ///
    - /// ]]>
    - /// Raised when a NavBarCommand is invoked. - /// Raised when the split button on a NavBarCommand is toggled. - /// Styles the entire NavBarContainer control. - /// - /// Styles the page indication for the NavBarContainer. - /// - /// Styles the page indication for each page. - /// - /// Styles the indication of the current page. - /// - /// Styles the area that contains items for the NavBarContainer. - /// Styles left and right navigation arrows. - /// Styles the left navigation arrow. - /// Styles the right navigation arrow. - /// - /// - /// - NavBarContainer: WinJS.Namespace._lazy(function () { - var buttonFadeDelay = 3000; - var PT_TOUCH = MSPointerEvent.MSPOINTER_TYPE_TOUCH || "touch"; - var MS_MANIPULATION_STATE_STOPPED = 0; - - var createEvent = WinJS.Utilities._createEventProperty; - var eventNames = { - invoked: "invoked", - splittoggle: "splittoggle" - }; - - var strings = { - get duplicateConstruction() { return WinJS.Resources._getWinJSString("ui/duplicateConstruction").value; }, - get navBarContainerViewportAriaLabel() { return WinJS.Resources._getWinJSString("ui/navBarContainerViewportAriaLabel").value; } - }; - - var NavBarContainer = WinJS.Class.define(function NavBarContainer_ctor(element, options) { - /// - /// - /// Creates a new NavBarContainer. - /// - /// - /// The DOM element that will host the NavBarContainer control. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. - /// Each property of the options object corresponds to one of the control's properties or events. - /// Event names must begin with "on". - /// - /// - /// The new NavBarContainer. - /// - /// - /// - - element = element || document.createElement("DIV"); - this._id = element.id || element.uniqueID; - this._writeProfilerMark("constructor,StartTM"); - - options = options || {}; - - if (element.winControl) { - throw new WinJS.ErrorFromName("WinJS.UI.NavBarContainer.DuplicateConstruction", strings.duplicateConstruction); - } - - // Attaching JS control to DOM element - element.winControl = this; - this._element = element; - WinJS.Utilities.addClass(this.element, WinJS.UI.NavBarContainer._ClassName.navbarcontainer); - WinJS.Utilities.addClass(this.element, "win-disposable"); - - this._currentManipulationState = MS_MANIPULATION_STATE_STOPPED; - - this._fixedSize = false; - this._maxRows = 1; - this._sizes = {}; - - this._setupTree(); - - this._duringConstructor = true; - - this._dataChangingBound = this._dataChanging.bind(this); - this._dataChangedBound = this._dataChanged.bind(this); - - this._navigatedBound = this._navigated.bind(this); - - WinJS.Navigation.addEventListener('navigated', this._navigatedBound); - - // Don't use set options for the properties so we can control the ordering to avoid rendering multiple times. - this.layout = options.layout || WinJS.UI.Orientation.horizontal; - if (options.maxRows) { - this.maxRows = options.maxRows; - } - if (options.template) { - this.template = options.template; - } - if (options.data) { - this.data = options.data; - } - if (options.fixedSize) { - this.fixedSize = options.fixedSize; - } - - // Events only - WinJS.UI._setOptions(this, options, true); - - this._duringConstructor = false; - - if (options.currentIndex) { - this.currentIndex = options.currentIndex; - } - - this._updatePageUI(); - - this._writeProfilerMark("constructor,StopTM"); - }, { - /// - element: { - get: function () { - return this._element; - } - }, - - /// - /// Gets or sets a Template or custom rendering function that defines the HTML of each item within the NavBarContainer. - /// - /// - template: { - get: function () { - return this._template; - }, - set: function (value) { - this._template = value; - if (this._repeater) { - var hadFocus = this.element.contains(document.activeElement); - - if (!this._duringConstructor) { - this._closeSplitIfOpen(); - } - - // the repeater's template is wired up to this._render() so just resetting it will rebuild the tree. - this._repeater.template = this._repeater.template; - - if (!this._duringConstructor) { - this._measured = false; - this._sizes.itemMeasured = false; - this._reset(); - if (hadFocus) { - this._keyboardBehavior._focus(0); - } - } - } - } - }, - - _render: function NavBarContainer_render(item, wrapperElement) { - var navbarCommandEl = document.createElement('div'); - - var template = this._template; - if (template) { - if (template.render) { - template.render(item, navbarCommandEl); - } else if (template.winControl && template.winControl.render) { - template.winControl.render(item, navbarCommandEl); - } else { - navbarCommandEl.appendChild(template(item)); - } - } - - // Create the NavBarCommand after calling render so that the reparenting in navbarCommand works. - var navbarCommand = new WinJS.UI.NavBarCommand(navbarCommandEl, item); - return navbarCommandEl; - }, - - /// - /// Gets or sets the WinJS.Binding.List that provides the NavBarContainer with items to display. - /// - /// - data: { - get: function () { - return this._repeater && this._repeater.data; - }, - set: function (value) { - if (!value) { - value = new WinJS.Binding.List(); - } - - if (!this._duringConstructor) { - this._closeSplitIfOpen(); - } - - this._removeDataChangingEvents(); - this._removeDataChangedEvents(); - - var hadFocus = this.element.contains(document.activeElement); - - if (!this._repeater) { - this._surfaceEl.innerHTML = ""; - this._repeater = new WinJS.UI.Repeater(this._surfaceEl, { - template: this._render.bind(this) - }); - } - - this._addDataChangingEvents(value); - this._repeater.data = value; - this._addDataChangedEvents(value); - - if (!this._duringConstructor) { - this._measured = false; - this._sizes.itemMeasured = false; - this._reset(); - if (hadFocus) { - this._keyboardBehavior._focus(0); - } - } - } - }, - - /// - /// Gets or sets the number of rows allowed to be used before items are placed on additional pages. - /// - /// - maxRows: { - get: function () { - return this._maxRows; - }, - set: function (value) { - value = (+value === value) ? value : 1; - this._maxRows = Math.max(1, value); - - if (!this._duringConstructor) { - this._closeSplitIfOpen(); - - this._measured = false; - this._reset(); - } - } - }, - - /// - /// Gets or sets a value that specifies whether the NavBarContainer has a horizontal or vertical layout. The default is "horizontal". - /// - /// - layout: { - get: function () { - return this._layout; - }, - set: function (value) { - if (value === WinJS.UI.Orientation.vertical) { - this._layout = WinJS.UI.Orientation.vertical; - WinJS.Utilities.removeClass(this.element, WinJS.UI.NavBarContainer._ClassName.horizontal); - WinJS.Utilities.addClass(this.element, WinJS.UI.NavBarContainer._ClassName.vertical); - } else { - this._layout = WinJS.UI.Orientation.horizontal; - WinJS.Utilities.removeClass(this.element, WinJS.UI.NavBarContainer._ClassName.vertical); - WinJS.Utilities.addClass(this.element, WinJS.UI.NavBarContainer._ClassName.horizontal); - } - - this._viewportEl.style.msScrollSnapType = ""; - this._zooming = false; - - if (!this._duringConstructor) { - this._measured = false; - this._sizes.itemMeasured = false; - this._ensureVisible(this._keyboardBehavior.currentIndex, true); - this._updatePageUI(); - this._closeSplitIfOpen(); - } - } - }, - - /// - currentIndex: { - get: function () { - return this._keyboardBehavior.currentIndex; - }, - set: function (value) { - if (value === +value) { - var hadFocus = this.element.contains(document.activeElement); - - this._keyboardBehavior.currentIndex = value; - if (this._surfaceEl.children.length > 0) { - this._surfaceEl.children[this._keyboardBehavior.currentIndex].winControl._splitButtonActive = false; - } - - this._ensureVisible(this._keyboardBehavior.currentIndex, true); - - if (hadFocus) { - this._keyboardBehavior._focus(); - } - } - } - }, - - /// - /// Gets or sets a value that specifies whether child NavBarCommand objects should be a fixed width when there are multiple pages. A value of true indicates - /// that the NavBarCommand objects use a fixed width; a value of false indicates that they use a dynamic width. - /// - /// - fixedSize: { - get: function () { - return this._fixedSize; - }, - set: function (value) { - this._fixedSize = !!value; - - if (!this._duringConstructor) { - this._closeSplitIfOpen(); - - if (!this._measured) { - this._measure(); - } else if (this._surfaceEl.children.length > 0) { - this._updateGridStyles(); - } - } - } - }, - - /// - /// Raised when a NavBarCommand has been invoked. - /// - /// - oninvoked: createEvent(eventNames.invoked), - - /// - /// Raised when the split button on a NavBarCommand is toggled. - /// - /// - onsplittoggle: createEvent(eventNames.splittoggle), - - forceLayout: function NavBarContainer_forceLayout() { - /// - /// - /// Forces the NavBarContainer to update scroll positions and if there are internal pending measurements, it will also re-measure. - /// Use this function when making the NavBarContainer visible again after you set its style.display property to "none". - /// - /// - /// - if (this._measured) { - if (this.layout === WinJS.UI.Orientation.horizontal) { - this._scrollPosition = this._viewportEl.scrollLeft; - } else { - this._scrollPosition = this._viewportEl.scrollTop; - } - } - - this._duringForceLayout = true; - this._ensureVisible(this._keyboardBehavior.currentIndex, true); - this._updatePageUI(); - this._duringForceLayout = false; - }, - - _navigated: function NavBarContainer_navigated() { - this._closeSplitIfOpen(); - this._reset(); - }, - - _dataChanging: function NavBarContainer_dataChanging(ev) { - // Store the element that was active so that we can detect - // if the focus went away because of the data change. - this._elementHadFocus = document.activeElement; - - if (this._currentSplitNavItem && this._currentSplitNavItem.splitOpened) { - if (ev.type === "itemremoved") { - if (this._surfaceEl.children[ev.detail.index].winControl === this._currentSplitNavItem) { - this._closeSplitIfOpen(); - } - } else if (ev.type === "itemchanged") { - if (this._surfaceEl.children[ev.detail.index].winControl === this._currentSplitNavItem) { - this._closeSplitIfOpen(); - } - } else if (ev.type === "itemmoved") { - if (this._surfaceEl.children[ev.detail.oldIndex].winControl === this._currentSplitNavItem) { - this._closeSplitIfOpen(); - } - } else if (ev.type === "reload") { - this._closeSplitIfOpen(); - } - } - }, - - _dataChanged: function NavBarContainer_dataChanged(ev) { - this._measured = false; - - if (ev.type === "itemremoved") { - if (ev.detail.index < this._keyboardBehavior.currentIndex) { - this._keyboardBehavior.currentIndex--; - } else if (ev.detail.index === this._keyboardBehavior.currentIndex) { - // This clamps if the item being removed was the last item in the list - this._keyboardBehavior.currentIndex = this._keyboardBehavior.currentIndex; - if (document.activeElement === null && this._elementHadFocus) { - this._keyboardBehavior._focus(); - } - } - } else if (ev.type === "itemchanged") { - if (ev.detail.index === this._keyboardBehavior.currentIndex) { - if (document.activeElement === null && this._elementHadFocus) { - this._keyboardBehavior._focus(); - } - } - } else if (ev.type === "iteminserted") { - if (ev.detail.index <= this._keyboardBehavior.currentIndex) { - this._keyboardBehavior.currentIndex++; - } - } else if (ev.type === "itemmoved") { - if (ev.detail.oldIndex === this._keyboardBehavior.currentIndex) { - this._keyboardBehavior.currentIndex = ev.detail.newIndex; - if (document.activeElement === null && this._elementHadFocus) { - this._keyboardBehavior._focus(); - } - } - } else if (ev.type === "reload") { - this._keyboardBehavior.currentIndex = 0; - if (document.activeElement === null && this._elementHadFocus) { - this._keyboardBehavior._focus(); - } - } - - this._ensureVisible(this._keyboardBehavior.currentIndex, true); - this._updatePageUI(); - }, - - _reset: function NavBarContainer_reset() { - this._keyboardBehavior.currentIndex = 0; - if (this._surfaceEl.children.length > 0) { - this._surfaceEl.children[this._keyboardBehavior.currentIndex].winControl._splitButtonActive = false; - } - - if (this.element.contains(document.activeElement)) { - this._keyboardBehavior._focus(0); - } - - this._viewportEl.style.msScrollSnapType = ""; - this._zooming = false; - - this._ensureVisible(0, true); - this._updatePageUI(); - }, - - _removeDataChangedEvents: function NavBarContainer_removeDataChangedEvents() { - if (this._repeater) { - this._repeater.data.removeEventListener("itemchanged", this._dataChangedBound); - this._repeater.data.removeEventListener("iteminserted", this._dataChangedBound); - this._repeater.data.removeEventListener("itemmoved", this._dataChangedBound); - this._repeater.data.removeEventListener("itemremoved", this._dataChangedBound); - this._repeater.data.removeEventListener("reload", this._dataChangedBound); - } - }, - - _addDataChangedEvents: function NavBarContainer_addDataChangedEvents(bindingList) { - if (this._repeater) { - this._repeater.data.addEventListener("itemchanged", this._dataChangedBound); - this._repeater.data.addEventListener("iteminserted", this._dataChangedBound); - this._repeater.data.addEventListener("itemmoved", this._dataChangedBound); - this._repeater.data.addEventListener("itemremoved", this._dataChangedBound); - this._repeater.data.addEventListener("reload", this._dataChangedBound); - } - }, - - _removeDataChangingEvents: function NavBarContainer_removeDataChangingEvents() { - if (this._repeater) { - this._repeater.data.removeEventListener("itemchanged", this._dataChangingBound); - this._repeater.data.removeEventListener("iteminserted", this._dataChangingBound); - this._repeater.data.removeEventListener("itemmoved", this._dataChangingBound); - this._repeater.data.removeEventListener("itemremoved", this._dataChangingBound); - this._repeater.data.removeEventListener("reload", this._dataChangingBound); - } - }, - - _addDataChangingEvents: function NavBarContainer_addDataChangingEvents(bindingList) { - bindingList.addEventListener("itemchanged", this._dataChangingBound); - bindingList.addEventListener("iteminserted", this._dataChangingBound); - bindingList.addEventListener("itemmoved", this._dataChangingBound); - bindingList.addEventListener("itemremoved", this._dataChangingBound); - bindingList.addEventListener("reload", this._dataChangingBound); - }, - - _mouseleave: function NavBarContainer_mouseleave(ev) { - if (this._mouseInViewport) { - this._mouseInViewport = false; - this._updateArrows(); - } - }, - - _MSPointerDown: function NavBarContainer_MSPointerDown(ev) { - if (ev.pointerType === PT_TOUCH) { - if (this._mouseInViewport) { - this._mouseInViewport = false; - this._updateArrows(); - } - } - }, - - _MSPointerMove: function NavBarContainer_MSPointerMove(ev) { - if (ev.pointerType !== PT_TOUCH) { - if (!this._mouseInViewport) { - this._mouseInViewport = true; - this._updateArrows(); - } - } - }, - - _setupTree: function NavBarContainer_setupTree() { - this._animateNextPreviousButtons = WinJS.Promise.wrap(); - this._element.addEventListener('mouseleave', this._mouseleave.bind(this)); - this._element.addEventListener('pointerdown', this._MSPointerDown.bind(this)); - this._element.addEventListener('pointermove', this._MSPointerMove.bind(this)); - this._element.addEventListener("focus", this._focusHandler.bind(this), true); - - this._pageindicatorsEl = document.createElement('div'); - WinJS.Utilities.addClass(this._pageindicatorsEl, WinJS.UI.NavBarContainer._ClassName.pageindicators); - this._element.appendChild(this._pageindicatorsEl); - - this._ariaStartMarker = document.createElement("div"); - this._element.appendChild(this._ariaStartMarker); - - this._viewportEl = document.createElement('div'); - WinJS.Utilities.addClass(this._viewportEl, WinJS.UI.NavBarContainer._ClassName.viewport); - this._element.appendChild(this._viewportEl); - this._viewportEl.setAttribute("role", "group"); - this._viewportEl.setAttribute("aria-label", strings.navBarContainerViewportAriaLabel); - - this._boundResizeHandler = this._resizeHandler.bind(this); - window.addEventListener("resize", this._boundResizeHandler); - this._viewportEl.addEventListener("mselementresize", this._resizeHandler.bind(this)); - this._viewportEl.addEventListener("scroll", this._scrollHandler.bind(this)); - this._viewportEl.addEventListener("MSManipulationStateChanged", this._MSManipulationStateChangedHandler.bind(this)); - - this._ariaEndMarker = document.createElement("div"); - this._element.appendChild(this._ariaEndMarker); - - this._surfaceEl = document.createElement('div'); - WinJS.Utilities.addClass(this._surfaceEl, WinJS.UI.NavBarContainer._ClassName.surface); - this._viewportEl.appendChild(this._surfaceEl); - - this._surfaceEl.addEventListener("_invoked", this._navbarCommandInvokedHandler.bind(this)); - this._surfaceEl.addEventListener("_splittoggle", this._navbarCommandSplitToggleHandler.bind(this)); - this._surfaceEl.addEventListener("focus", this._itemsFocusHandler.bind(this), true); - this._surfaceEl.addEventListener("keydown", this._keyDownHandler.bind(this)); - - // Reparent NavBarCommands which were in declarative markup - var tempEl = this.element.firstElementChild; - while (tempEl !== this._pageindicatorsEl) { - this._surfaceEl.appendChild(tempEl); - WinJS.UI.process(tempEl); - tempEl = this.element.firstElementChild; - } - - this._leftArrowEl = document.createElement('div'); - WinJS.Utilities.addClass(this._leftArrowEl, WinJS.UI.NavBarContainer._ClassName.navleftarrow); - WinJS.Utilities.addClass(this._leftArrowEl, WinJS.UI.NavBarContainer._ClassName.navarrow); - this._element.appendChild(this._leftArrowEl); - this._leftArrowEl.addEventListener('click', this._goLeft.bind(this)); - this._leftArrowEl.style.opacity = 0; - this._leftArrowEl.style.visibility = 'hidden'; - this._leftArrowFadeOut = WinJS.Promise.wrap(); - - this._rightArrowEl = document.createElement('div'); - WinJS.Utilities.addClass(this._rightArrowEl, WinJS.UI.NavBarContainer._ClassName.navrightarrow); - WinJS.Utilities.addClass(this._rightArrowEl, WinJS.UI.NavBarContainer._ClassName.navarrow); - this._element.appendChild(this._rightArrowEl); - this._rightArrowEl.addEventListener('click', this._goRight.bind(this)); - this._rightArrowEl.style.opacity = 0; - this._rightArrowEl.style.visibility = 'hidden'; - this._rightArrowFadeOut = WinJS.Promise.wrap(); - - this._keyboardBehavior = new WinJS.UI._KeyboardBehavior(this._surfaceEl); - this._winKeyboard = new WinJS.UI._WinKeyboard(this._surfaceEl); - }, - - _goRight: function NavBarContainer_goRight() { - if (this._sizes.rtl) { - this._goPrev(); - } else { - this._goNext(); - } - }, - - _goLeft: function NavBarContainer_goLeft() { - if (this._sizes.rtl) { - this._goNext(); - } else { - this._goPrev(); - } - }, - - _goNext: function NavBarContainer_goNext() { - this._measure(); - var itemsPerPage = this._sizes.rowsPerPage * this._sizes.columnsPerPage; - var targetPage = Math.min(Math.floor(this._keyboardBehavior.currentIndex / itemsPerPage) + 1, this._sizes.pages - 1); - this._keyboardBehavior.currentIndex = Math.min(itemsPerPage * targetPage, this._surfaceEl.children.length); - this._keyboardBehavior._focus(); - }, - - _goPrev: function NavBarContainer_goPrev() { - this._measure(); - var itemsPerPage = this._sizes.rowsPerPage * this._sizes.columnsPerPage; - var targetPage = Math.max(0, Math.floor(this._keyboardBehavior.currentIndex / itemsPerPage) - 1); - this._keyboardBehavior.currentIndex = Math.max(itemsPerPage * targetPage, 0); - this._keyboardBehavior._focus(); - }, - - _currentPage: { - get: function () { - if (this.layout === WinJS.UI.Orientation.horizontal) { - this._measure(); - if (this._sizes.viewportOffsetWidth > 0) { - return Math.min(this._sizes.pages - 1, Math.round(this._scrollPosition / this._sizes.viewportOffsetWidth)); - } - } - return 0; - } - }, - - _resizeHandler: function NavBarContainer_resizeHandler() { - if (this._disposed) { - return; - } - if (this._measured) { - this._measured = false; - - if (!this._pendingResize) { - this._pendingResize = true; - - this._resizeImplBound = this._resizeImplBound || this._resizeImpl.bind(this); - - if (!this._appBarEl || !this._appBarEl.contains(this.element)) { - if (this._appBarEl) { - this._appBarEl.removeEventListener('beforeshow', this._resizeImplBound); - } - - var appBarEl = this.element.parentNode; - while (appBarEl && !WinJS.Utilities.hasClass(appBarEl, 'win-appbar')) { - appBarEl = appBarEl.parentNode; - } - - this._appBarEl = appBarEl; - } - - if (this._appBarEl && this._appBarEl.winControl && this._appBarEl.winControl.hidden) { - // Do resize lazily. - WinJS.Utilities.Scheduler.schedule(this._resizeImplBound, WinJS.Utilities.Scheduler.Priority.idle, null, "WinJS.UI.NavBarContainer._resizeImpl"); - this._appBarEl.addEventListener('beforeshow', this._resizeImplBound); - } else { - // Do resize now - this._resizeImpl(); - } - } - } - }, - - _resizeImpl: function NavBarContainer_resizeImpl() { - if (!this._disposed && this._pendingResize) { - this._pendingResize = false; - if (this._appBarEl) { - this._appBarEl.removeEventListener('beforeshow', this._resizeImplBound); - } - - this._keyboardBehavior.currentIndex = 0; - if (this._surfaceEl.children.length > 0) { - this._surfaceEl.children[0].winControl._splitButtonActive = false; - } - if (this.element.contains(document.activeElement)) { - this._keyboardBehavior._focus(this._keyboardBehavior.currentIndex); - } - this._closeSplitIfOpen(); - this._ensureVisible(this._keyboardBehavior.currentIndex, true); - this._updatePageUI(); - } - }, - - _keyDownHandler: function NavBarContainer_keyDownHandler(ev) { - var key = ev.key - if (!ev.altKey && (key === "PageUp" || key === "PageDown")) { - var srcElement = ev.srcElement; - if (srcElement.msMatchesSelector(".win-interactive, .win-interactive *")) { - return; - } - - var index = this._keyboardBehavior.currentIndex; - this._measure(); - - var sizes = this._sizes; - var page = Math.floor(index / (sizes.columnsPerPage * sizes.rowsPerPage)); - - var scrollPositionTarget = null; - if (key === "PageUp") { - if (this.layout === WinJS.UI.Orientation.horizontal) { - var indexOfFirstItemOnPage = page * sizes.columnsPerPage * sizes.rowsPerPage; - if (index === indexOfFirstItemOnPage && this._surfaceEl.children[index].winControl._buttonEl === document.activeElement) { - // First item on page so go back 1 page. - index = index - sizes.columnsPerPage * sizes.rowsPerPage; - } else { - // Not first item on page so go to the first item on page. - index = indexOfFirstItemOnPage; - } - } else { - var currentItem = this._surfaceEl.children[index]; - var top = currentItem.offsetTop; - var bottom = top + currentItem.offsetHeight; - var scrollPosition = this._zooming ? this._zoomPosition : this._scrollPosition; - - if (top >= scrollPosition && bottom < scrollPosition + sizes.viewportOffsetHeight) { - // current item is fully on screen. - while (index > 0 && - this._surfaceEl.children[index - 1].offsetTop > scrollPosition) { - index--; - } - } - - if (this._keyboardBehavior.currentIndex === index) { - var scrollPositionForOnePageAboveItem = bottom - sizes.viewportOffsetHeight; - index = Math.max(0, index - 1); - while (index > 0 && - this._surfaceEl.children[index - 1].offsetTop > scrollPositionForOnePageAboveItem) { - index--; - } - if (index > 0) { - scrollPositionTarget = this._surfaceEl.children[index].offsetTop - this._sizes.itemMarginTop; - } else { - scrollPositionTarget = 0; - } - } - } - - index = Math.max(index, 0); - this._keyboardBehavior.currentIndex = index; - - var element = this._surfaceEl.children[index].winControl._buttonEl; - this._surfaceEl.children[index].winControl._splitButtonActive = false; - - if (scrollPositionTarget !== null) { - this._scrollTo(scrollPositionTarget); - } - - try { - element.setActive(); - } catch (e) { - } - } else { - if (this.layout === WinJS.UI.Orientation.horizontal) { - var indexOfLastItemOnPage = (page + 1) * sizes.columnsPerPage * sizes.rowsPerPage - 1; - - if (index === indexOfLastItemOnPage) { - // Last item on page so go forward 1 page. - index = index + sizes.columnsPerPage * sizes.rowsPerPage; - } else { - // Not Last item on page so go to last item on page. - index = indexOfLastItemOnPage; - } - } else { - var currentItem = this._surfaceEl.children[this._keyboardBehavior.currentIndex]; - var top = currentItem.offsetTop; - var bottom = top + currentItem.offsetHeight; - var scrollPosition = this._zooming ? this._zoomPosition : this._scrollPosition; - - if (top >= scrollPosition && bottom < scrollPosition + sizes.viewportOffsetHeight) { - // current item is fully on screen. - while (index < this._surfaceEl.children.length - 1 && - this._surfaceEl.children[index + 1].offsetTop + this._surfaceEl.children[index + 1].offsetHeight < scrollPosition + sizes.viewportOffsetHeight) { - index++; - } - } - - if (index === this._keyboardBehavior.currentIndex) { - var scrollPositionForOnePageBelowItem = top + sizes.viewportOffsetHeight; - index = Math.min(this._surfaceEl.children.length - 1, index + 1); - while (index < this._surfaceEl.children.length - 1 && - this._surfaceEl.children[index + 1].offsetTop + this._surfaceEl.children[index + 1].offsetHeight < scrollPositionForOnePageBelowItem) { - index++; - } - - if (index < this._surfaceEl.children.length - 1) { - scrollPositionTarget = this._surfaceEl.children[index + 1].offsetTop - this._sizes.viewportOffsetHeight; - } else { - scrollPositionTarget = this._scrollLength - this._sizes.viewportOffsetHeight; - } - } - } - - index = Math.min(index, this._surfaceEl.children.length - 1); - this._keyboardBehavior.currentIndex = index; - - var element = this._surfaceEl.children[index].winControl._buttonEl; - this._surfaceEl.children[index].winControl._splitButtonActive = false; - - if (scrollPositionTarget !== null) { - this._scrollTo(scrollPositionTarget); - } - - try { - element.setActive(); - } catch (e) { - } - } - } - }, - - _focusHandler: function NavBarContainer_focusHandler(ev) { - var srcElement = ev.srcElement; - if (!this._surfaceEl.contains(srcElement)) { - // Forward focus from NavBarContainer, viewport or surface to the currentIndex. - this._skipEnsureVisible = true; - this._keyboardBehavior._focus(this._keyboardBehavior.currentIndex); - } - }, - - _itemsFocusHandler: function NavBarContainer_itemsFocusHandler(ev) { - // Find the item which is being focused and scroll it to view. - var srcElement = ev.srcElement; - if (srcElement === this._surfaceEl) { - return; - } - - while (srcElement.parentNode !== this._surfaceEl) { - srcElement = srcElement.parentNode; - } - - var index = -1; - while (srcElement) { - index++; - srcElement = srcElement.previousSibling; - } - - if (this._skipEnsureVisible) { - this._skipEnsureVisible = false; - } else { - this._ensureVisible(index); - } - }, - - _ensureVisible: function NavBarContainer_ensureVisible(index, withoutAnimation) { - this._measure(); - - if (this.layout === WinJS.UI.Orientation.horizontal) { - var page = Math.floor(index / (this._sizes.rowsPerPage * this._sizes.columnsPerPage)); - this._scrollTo(page * this._sizes.viewportOffsetWidth, withoutAnimation); - } else { - var element = this._surfaceEl.children[index]; - var maxScrollPosition; - if (index > 0) { - maxScrollPosition = element.offsetTop - this._sizes.itemMarginTop; - } else { - maxScrollPosition = 0; - } - var minScrollPosition; - if (index < this._surfaceEl.children.length - 1) { - minScrollPosition = this._surfaceEl.children[index + 1].offsetTop - this._sizes.viewportOffsetHeight; - } else { - minScrollPosition = this._scrollLength - this._sizes.viewportOffsetHeight; - } - - var newScrollPosition = this._zooming ? this._zoomPosition : this._scrollPosition; - newScrollPosition = Math.max(newScrollPosition, minScrollPosition); - newScrollPosition = Math.min(newScrollPosition, maxScrollPosition); - this._scrollTo(newScrollPosition, withoutAnimation); - } - }, - - _scrollTo: function NavBarContainer_scrollTo(targetScrollPosition, withoutAnimation) { - this._measure(); - if (this.layout === WinJS.UI.Orientation.horizontal) { - targetScrollPosition = Math.max(0, Math.min(this._scrollLength - this._sizes.viewportOffsetWidth, targetScrollPosition)); - } else { - targetScrollPosition = Math.max(0, Math.min(this._scrollLength - this._sizes.viewportOffsetHeight, targetScrollPosition)); - } - - if (withoutAnimation) { - if (Math.abs(this._scrollPosition - targetScrollPosition) > 1) { - this._zooming = false; - - this._scrollPosition = targetScrollPosition; - this._updatePageUI(); - if (!this._duringForceLayout) { - this._closeSplitIfOpen(); - } - - if (this.layout === WinJS.UI.Orientation.horizontal) { - this._viewportEl.scrollLeft = targetScrollPosition; - } else { - this._viewportEl.scrollTop = targetScrollPosition; - } - } - } else { - if ((!this._zooming && Math.abs(this._scrollPosition - targetScrollPosition) > 1) || (this._zooming && Math.abs(this._zoomPosition - targetScrollPosition) > 1)) { - this._zoomPosition = targetScrollPosition; - - this._zooming = true; - - if (this.layout === WinJS.UI.Orientation.horizontal) { - this._viewportEl.style.msScrollSnapType = "none"; - this._viewportEl.msZoomTo({ contentX: targetScrollPosition, contentY: 0, viewportX: 0, viewportY: 0 }); - } else { - this._viewportEl.msZoomTo({ contentX: 0, contentY: targetScrollPosition, viewportX: 0, viewportY: 0 }); - } - - this._closeSplitIfOpen(); - } - } - }, - - _MSManipulationStateChangedHandler: function NavBarContainer_MSManipulationStateChangedHandler(e) { - this._currentManipulationState = e.currentState; - - if (e.currentState === e.MS_MANIPULATION_STATE_ACTIVE) { - this._viewportEl.style.msScrollSnapType = ""; - this._zooming = false; - } - - clearTimeout(this._manipulationStateTimeoutId); - // The extra stop event is firing when an msZoomTo is called during another msZoomTo and - // also the first msZoomTo after a resize. - if (e.currentState === e.MS_MANIPULATION_STATE_STOPPED) { - this._manipulationStateTimeoutId = setTimeout(function () { - this._viewportEl.style.msScrollSnapType = ""; - this._zooming = false; - this._updateCurrentIndexIfPageChanged(); - }.bind(this), 100); - } - }, - - _scrollHandler: function NavBarContainer_scrollHandler() { - this._measured = false; - if (!this._checkingScroll) { - var that = this; - this._checkingScroll = requestAnimationFrame(function () { - that._checkingScroll = null; - - var newScrollPosition; - if (that.layout === WinJS.UI.Orientation.horizontal) { - newScrollPosition = that._viewportEl.scrollLeft; - } else { - newScrollPosition = that._viewportEl.scrollTop; - } - if (newScrollPosition !== that._scrollPosition) { - that._scrollPosition = newScrollPosition; - that._closeSplitIfOpen(); - } - that._updatePageUI(); - - if (!that._zooming && this._currentManipulationState === MS_MANIPULATION_STATE_STOPPED) { - that._updateCurrentIndexIfPageChanged(); - } - }); - } - }, - - _updateCurrentIndexIfPageChanged: function NavBarContainer_updateCurrentIndexIfPageChanged() { - // If you change pages via pagination arrows, mouse wheel, or panning we need to update the current - // item to be the first item on the new page. - if (this.layout === WinJS.UI.Orientation.horizontal) { - this._measure(); - var currentPage = this._currentPage; - var firstIndexOnPage = currentPage * this._sizes.rowsPerPage * this._sizes.columnsPerPage; - var lastIndexOnPage = (currentPage + 1) * this._sizes.rowsPerPage * this._sizes.columnsPerPage - 1; - - if (this._keyboardBehavior.currentIndex < firstIndexOnPage || this._keyboardBehavior.currentIndex > lastIndexOnPage) { - // Page change occurred. - this._keyboardBehavior.currentIndex = firstIndexOnPage; - if (this._surfaceEl.children.length > 0) { - this._surfaceEl.children[this._keyboardBehavior.currentIndex].winControl._splitButtonActive = false; - } - - if (this.element.contains(document.activeElement)) { - this._keyboardBehavior._focus(this._keyboardBehavior.currentIndex); - } - } - } - }, - - _measure: function NavBarContainer_measure() { - if (!this._measured) { - this._resizeImpl(); - this._writeProfilerMark("measure,StartTM"); - - var sizes = this._sizes; - - sizes.rtl = getComputedStyle(this._element).direction === "rtl"; - - var itemCount = this._surfaceEl.children.length; - if (itemCount > 0) { - if (!this._sizes.itemMeasured) { - this._writeProfilerMark("measureItem,StartTM"); - - var elementToMeasure = this._surfaceEl.firstElementChild; - // Clear inline margins set by NavBarContainer before measuring. - elementToMeasure.style.margin = ""; - elementToMeasure.style.width = ""; - var elementComputedStyle = getComputedStyle(elementToMeasure); - sizes.itemOffsetWidth = parseFloat(getComputedStyle(elementToMeasure).width); - if (elementToMeasure.offsetWidth === 0) { - sizes.itemOffsetWidth = 0; - } - sizes.itemMarginLeft = parseFloat(elementComputedStyle.marginLeft); - sizes.itemMarginRight = parseFloat(elementComputedStyle.marginRight); - sizes.itemWidth = sizes.itemOffsetWidth + sizes.itemMarginLeft + sizes.itemMarginRight; - sizes.itemOffsetHeight = parseFloat(getComputedStyle(elementToMeasure).height); - if (elementToMeasure.offsetHeight === 0) { - sizes.itemOffsetHeight = 0; - } - sizes.itemMarginTop = parseFloat(elementComputedStyle.marginTop); - sizes.itemMarginBottom = parseFloat(elementComputedStyle.marginBottom); - sizes.itemHeight = sizes.itemOffsetHeight + sizes.itemMarginTop + sizes.itemMarginBottom; - if (sizes.itemOffsetWidth > 0 && sizes.itemOffsetHeight > 0) { - sizes.itemMeasured = true; - } - this._writeProfilerMark("measureItem,StopTM"); - } - - sizes.viewportOffsetWidth = parseFloat(getComputedStyle(this._viewportEl).width); - if (this._viewportEl.offsetWidth === 0) { - sizes.viewportOffsetWidth = 0; - } - sizes.viewportOffsetHeight = parseFloat(getComputedStyle(this._viewportEl).height); - if (this._viewportEl.offsetHeight === 0) { - sizes.viewportOffsetHeight = 0; - } - - if (sizes.viewportOffsetWidth === 0 || sizes.itemOffsetHeight === 0) { - this._measured = false; - } else { - this._measured = true; - } - - if (this.layout === WinJS.UI.Orientation.horizontal) { - this._scrollPosition = this._viewportEl.scrollLeft; - - sizes.leadingEdge = this._leftArrowEl.offsetWidth + parseInt(getComputedStyle(this._leftArrowEl).marginLeft) + parseInt(getComputedStyle(this._leftArrowEl).marginRight); - var usableSpace = sizes.viewportOffsetWidth - sizes.leadingEdge * 2; - sizes.maxColumns = sizes.itemWidth ? Math.max(1, Math.floor(usableSpace / sizes.itemWidth)) : 1; - sizes.rowsPerPage = Math.min(this.maxRows, Math.ceil(itemCount / sizes.maxColumns)); - sizes.columnsPerPage = Math.min(sizes.maxColumns, itemCount); - sizes.pages = Math.ceil(itemCount / (sizes.columnsPerPage * sizes.rowsPerPage)); - sizes.trailingEdge = sizes.leadingEdge; - sizes.extraSpace = usableSpace - (sizes.columnsPerPage * sizes.itemWidth); - - this._scrollLength = sizes.viewportOffsetWidth * sizes.pages; - - this._keyboardBehavior.fixedSize = sizes.rowsPerPage; - this._keyboardBehavior.fixedDirection = WinJS.UI._KeyboardBehavior.FixedDirection.height; - - this._surfaceEl.style.height = (sizes.itemHeight * sizes.rowsPerPage) + "px"; - this._surfaceEl.style.width = this._scrollLength + "px"; - } else { - this._scrollPosition = this._viewportEl.scrollTop; - - sizes.leadingEdge = 0; - sizes.rowsPerPage = itemCount; - sizes.columnsPerPage = 1; - sizes.pages = 1; - sizes.trailingEdge = 0; - - // Reminder there is margin collapsing so just use scrollHeight instead of itemHeight * itemCount - this._scrollLength = this._viewportEl.scrollHeight; - - this._keyboardBehavior.fixedSize = sizes.columnsPerPage; - this._keyboardBehavior.fixedDirection = WinJS.UI._KeyboardBehavior.FixedDirection.width; - - this._surfaceEl.style.height = ""; - this._surfaceEl.style.width = ""; - } - - this._updateGridStyles(); - } else { - sizes.pages = 1; - this._hasPreviousContent = false; - this._hasNextContent = false; - this._surfaceEl.style.height = ""; - this._surfaceEl.style.width = ""; - } - - this._writeProfilerMark("measure,StopTM"); - } - }, - - _updateGridStyles: function NavBarContainer_updateGridStyles() { - var sizes = this._sizes; - var itemCount = this._surfaceEl.children.length; - - for (var index = 0; index < itemCount; index++) { - var itemEl = this._surfaceEl.children[index]; - - var marginRight; - var marginLeft; - var cssRow; - var cssColumn; - var width = ""; - - if (this.layout === WinJS.UI.Orientation.horizontal) { - var row = Math.floor(index % sizes.rowsPerPage); - var column = Math.floor(index / sizes.rowsPerPage); - var isFirstColumnOnPage = column % sizes.columnsPerPage === 0; - var isLastColumnOnPage = column % sizes.columnsPerPage === sizes.columnsPerPage - 1; - - var extraTrailingMargin = sizes.trailingEdge; - if (this.fixedSize) { - extraTrailingMargin += sizes.extraSpace; - } else { - var spaceToDistribute = sizes.extraSpace - (sizes.maxColumns - sizes.columnsPerPage) * sizes.itemWidth; - width = (sizes.itemOffsetWidth + (spaceToDistribute / sizes.maxColumns)) + "px"; - } - - cssRow = row + 1; - cssColumn = column + 1; - var extraMarginRight; - var extraMarginLeft; - - if (sizes.rtl) { - extraMarginRight = (isFirstColumnOnPage ? sizes.leadingEdge : 0); - extraMarginLeft = (isLastColumnOnPage ? extraTrailingMargin : 0); - } else { - extraMarginRight = (isLastColumnOnPage ? extraTrailingMargin : 0); - extraMarginLeft = (isFirstColumnOnPage ? sizes.leadingEdge : 0); - } - - marginRight = extraMarginRight + sizes.itemMarginRight + "px"; - marginLeft = extraMarginLeft + sizes.itemMarginLeft + "px"; - } else { - cssRow = ""; - cssColumn = ""; - marginRight = ""; - marginLeft = ""; - } - - if (itemEl.style.msGridRow !== cssRow) { - itemEl.style.msGridRow = cssRow; - } - if (itemEl.style.msGridColumn !== cssColumn) { - itemEl.style.msGridColumn = cssColumn; - } - if (itemEl.style.marginRight !== marginRight) { - itemEl.style.marginRight = marginRight; - } - if (itemEl.style.marginLeft !== marginLeft) { - itemEl.style.marginLeft = marginLeft; - } - if (itemEl.style.width !== width) { - itemEl.style.width = width; - } - } - }, - - _updatePageUI: function NavBarContainer_updatePageUI() { - this._measure(); - var currentPage = this._currentPage; - - this._hasPreviousContent = (currentPage !== 0); - this._hasNextContent = (currentPage < this._sizes.pages - 1); - this._updateArrows(); - - // Always output the pagination indicators so they reserves up space. - if (this._indicatorCount !== this._sizes.pages) { - this._indicatorCount = this._sizes.pages; - this._pageindicatorsEl.innerHTML = new Array(this._sizes.pages + 1).join(''); - } - - for (var i = 0; i < this._pageindicatorsEl.children.length; i++) { - if (i === currentPage) { - WinJS.Utilities.addClass(this._pageindicatorsEl.children[i], WinJS.UI.NavBarContainer._ClassName.currentindicator); - } else { - WinJS.Utilities.removeClass(this._pageindicatorsEl.children[i], WinJS.UI.NavBarContainer._ClassName.currentindicator); - } - } - - if (this._sizes.pages > 1) { - this._viewportEl.style.overflowX = ""; - this._pageindicatorsEl.style.visibility = ""; - } else { - this._viewportEl.style.overflowX = "hidden"; - this._pageindicatorsEl.style.visibility = "hidden"; - } - - if (this._sizes.pages <= 1 || this._layout !== WinJS.UI.Orientation.horizontal) { - this._ariaStartMarker.removeAttribute("aria-flowto"); - this._ariaEndMarker.removeAttribute("x-ms-aria-flowfrom"); - } else { - var firstIndexOnCurrentPage = currentPage * this._sizes.rowsPerPage * this._sizes.columnsPerPage; - var firstItem = this._surfaceEl.children[firstIndexOnCurrentPage].winControl._buttonEl; - WinJS.UI._ensureId(firstItem); - this._ariaStartMarker.setAttribute("aria-flowto", firstItem.id); - - var lastIndexOnCurrentPage = Math.min(this._surfaceEl.children.length - 1, (currentPage + 1) * this._sizes.rowsPerPage * this._sizes.columnsPerPage - 1); - var lastItem = this._surfaceEl.children[lastIndexOnCurrentPage].winControl._buttonEl; - WinJS.UI._ensureId(lastItem); - this._ariaEndMarker.setAttribute("x-ms-aria-flowfrom", lastItem.id); - } - }, - - _closeSplitIfOpen: function NavBarContainer_closeSplitIfOpen() { - if (this._currentSplitNavItem) { - if (this._currentSplitNavItem.splitOpened) { - this._currentSplitNavItem._toggleSplit(); - } - this._currentSplitNavItem = null; - } - }, - - _updateArrows: function NavBarContainer_updateArrows() { - var hasLeftContent = this._sizes.rtl ? this._hasNextContent : this._hasPreviousContent; - var hasRightContent = this._sizes.rtl ? this._hasPreviousContent : this._hasNextContent; - - var that = this; - // Previous and next are the arrows, not states. On mouse hover the arrows fade in immediately. If you - // mouse out the arrows fade out after a delay. When you reach the last/first page, the corresponding - // arrow fades out immediately as well. - if (this._mouseInViewport && hasLeftContent) { - this._leftArrowWaitingToFadeOut && this._leftArrowWaitingToFadeOut.cancel(); - this._leftArrowWaitingToFadeOut = null; - this._leftArrowFadeOut && this._leftArrowFadeOut.cancel(); - this._leftArrowFadeOut = null; - this._leftArrowEl.style.visibility = ''; - this._leftArrowFadeIn = this._leftArrowFadeIn || WinJS.UI.Animation.fadeIn(this._leftArrowEl); - } else { - if (hasLeftContent) { - // If we need a delayed fade out and we are already running a delayed fade out just use that one, don't extend it. - // Otherwise create a delayed fade out. - this._leftArrowWaitingToFadeOut = this._leftArrowWaitingToFadeOut || WinJS.Promise.timeout(buttonFadeDelay); - } else { - // If we need a immediate fade out and already have a delayed fade out cancel that one and create an immediate one. - this._leftArrowWaitingToFadeOut && this._leftArrowWaitingToFadeOut.cancel(); - this._leftArrowWaitingToFadeOut = WinJS.Promise.wrap(); - } - this._leftArrowWaitingToFadeOut.then(function () { - // After the delay cancel any fade in if running. If we already were fading out continue it otherwise start the fade out. - this._leftArrowFadeIn && this._leftArrowFadeIn.cancel(); - this._leftArrowFadeIn = null; - this._leftArrowFadeOut = this._leftArrowFadeOut || WinJS.UI.Animation.fadeOut(this._leftArrowEl).then(function () { - that._leftArrowEl.style.visibility = 'hidden'; - }); - }.bind(this)); - } - - // Same pattern for Next arrow. - if (this._mouseInViewport && hasRightContent) { - this._rightArrowWaitingToFadeOut && this._rightArrowWaitingToFadeOut.cancel(); - this._rightArrowWaitingToFadeOut = null; - this._rightArrowFadeOut && this._rightArrowFadeOut.cancel(); - this._rightArrowFadeOut = null; - this._rightArrowEl.style.visibility = ''; - this._rightArrowFadeIn = this._rightArrowFadeIn || WinJS.UI.Animation.fadeIn(this._rightArrowEl); - } else { - if (hasRightContent) { - this._rightArrowWaitingToFadeOut = this._rightArrowWaitingToFadeOut || WinJS.Promise.timeout(buttonFadeDelay); - } else { - this._rightArrowWaitingToFadeOut && this._rightArrowWaitingToFadeOut.cancel(); - this._rightArrowWaitingToFadeOut = WinJS.Promise.wrap(); - } - this._rightArrowWaitingToFadeOut.then(function () { - this._rightArrowFadeIn && this._rightArrowFadeIn.cancel(); - this._rightArrowFadeIn = null; - this._rightArrowFadeOut = this._rightArrowFadeOut || WinJS.UI.Animation.fadeOut(this._rightArrowEl).then(function () { - that._rightArrowEl.style.visibility = 'hidden'; - }); - }.bind(this)); - } - }, - - _navbarCommandInvokedHandler: function NavBarContainer_navbarCommandInvokedHandler(ev) { - var srcElement = ev.srcElement; - var index = -1; - while (srcElement) { - index++; - srcElement = srcElement.previousSibling; - } - - this._fireEvent(WinJS.UI.NavBarContainer._EventName.invoked, { - index: index, - navbarCommand: ev.srcElement.winControl, - data: this._repeater ? this._repeater.data.getAt(index) : null - }); - }, - - _navbarCommandSplitToggleHandler: function NavBarContainer_navbarCommandSplitToggleHandler(ev) { - var srcElement = ev.srcElement; - var index = -1; - while (srcElement) { - index++; - srcElement = srcElement.previousSibling; - } - - var navbarCommand = ev.srcElement.winControl; - - this._closeSplitIfOpen(); - - if (navbarCommand.splitOpened) { - this._currentSplitNavItem = navbarCommand; - } - - this._fireEvent(WinJS.UI.NavBarContainer._EventName.splitToggle, { - opened: navbarCommand.splitOpened, - index: index, - navbarCommand: navbarCommand, - data: this._repeater ? this._repeater.data.getAt(index) : null - }); - }, - - _fireEvent: function NavBarContainer_fireEvent(type, detail) { - var event = document.createEvent("CustomEvent"); - event.initCustomEvent(type, true, false, detail); - this.element.dispatchEvent(event); - }, - - _writeProfilerMark: function NavBarContainer_writeProfilerMark(text) { - var message = "WinJS.UI.NavBarContainer:" + this._id + ":" + text; - msWriteProfilerMark(message); - WinJS.log && WinJS.log(message, null, "navbarcontainerprofiler"); - }, - - dispose: function NavBarContainer_dispose() { - /// - /// - /// Disposes this control. - /// - /// - /// - if (this._disposed) { - return; - } - this._disposed = true; - - if (this._appBarEl) { - this._appBarEl.removeEventListener('beforeshow', this._resizeImplBound); - } - - WinJS.Navigation.removeEventListener('navigated', this._navigatedBound); - - this._leftArrowWaitingToFadeOut && this._leftArrowWaitingToFadeOut.cancel(); - this._leftArrowFadeOut && this._leftArrowFadeOut.cancel(); - this._leftArrowFadeIn && this._leftArrowFadeIn.cancel(); - this._rightArrowWaitingToFadeOut && this._rightArrowWaitingToFadeOut.cancel(); - this._rightArrowFadeOut && this._rightArrowFadeOut.cancel(); - this._rightArrowFadeIn && this._rightArrowFadeIn.cancel(); - - window.removeEventListener("resize", this._boundResizeHandler); - - this._removeDataChangingEvents(); - this._removeDataChangedEvents(); - } - }, { - // Names of classes used by the NavBarContainer. - _ClassName: { - navbarcontainer: "win-navbarcontainer", - pageindicators: "win-navbarcontainer-pageindicator-box", - indicator: "win-navbarcontainer-pageindicator", - currentindicator: "win-navbarcontainer-pageindicator-current", - vertical: "win-navbarcontainer-vertical", - horizontal: "win-navbarcontainer-horizontal", - viewport: "win-navbarcontainer-viewport", - surface: "win-navbarcontainer-surface", - navarrow: "win-navbarcontainer-navarrow", - navleftarrow: "win-navbarcontainer-navleft", - navrightarrow: "win-navbarcontainer-navright" - }, - _EventName: { - invoked: eventNames.invoked, - splitToggle: eventNames.splittoggle - } - }); - WinJS.Class.mix(NavBarContainer, WinJS.UI.DOMEventMixin); - return NavBarContainer; - }) - }); - -})(this, WinJS); - -(function NavBarCommandInit(global, WinJS, undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - _WinPressed: WinJS.Namespace._lazy(function () { - return WinJS.Class.define(function _WinPressed_ctor(element) { - // WinPressed is the combination of :hover:active - // :hover is delayed by trident for touch by 300ms so if you want :hover:active to work quickly you need to - // use this behavior. - // :active does not bubble to its parent like :hover does so this is also useful for that scenario. - this._element = element; - this._element.addEventListener("pointerdown", this._MSPointerDownButtonHandler.bind(this)); - }, { - _MSPointerDownButtonHandler: function _WinPressed_MSPointerDownButtonHandler(ev) { - if (!this._pointerUpBound) { - this._pointerUpBound = this._MSPointerUpHandler.bind(this); - this._pointerCancelBound = this._MSPointerCancelHandler.bind(this); - this._pointerOverBound = this._MSPointerOverHandler.bind(this); - this._pointerOutBound = this._MSPointerOutHandler.bind(this); - } - - if (ev.isPrimary) { - if (this._pointerId) { - this._resetPointer(); - } - - if (!ev.srcElement.msMatchesSelector(".win-interactive, .win-interactive *")) { - this._pointerId = ev.pointerId; - - window.addEventListener("pointerup", this._pointerUpBound, true); - window.addEventListener("pointercancel", this._pointerCancelBound), true; - this._element.addEventListener("pointerover", this._pointerOverBound, true); - this._element.addEventListener("pointerout", this._pointerOutBound, true); - - WinJS.Utilities.addClass(this._element, WinJS.UI._WinPressed.winPressed); - } - } - }, - - _MSPointerOverHandler: function _WinPressed_MSPointerOverHandler(ev) { - if (this._pointerId === ev.pointerId) { - WinJS.Utilities.addClass(this._element, WinJS.UI._WinPressed.winPressed); - } - }, - - _MSPointerOutHandler: function _WinPressed_MSPointerOutHandler(ev) { - if (this._pointerId === ev.pointerId) { - WinJS.Utilities.removeClass(this._element, WinJS.UI._WinPressed.winPressed); - } - }, - - _MSPointerCancelHandler: function _WinPressed_MSPointerCancelHandler(ev) { - if (this._pointerId === ev.pointerId) { - this._resetPointer(); - } - }, - - _MSPointerUpHandler: function _WinPressed_MSPointerUpHandler(ev) { - if (this._pointerId === ev.pointerId) { - this._resetPointer(); - } - }, - - _resetPointer: function _WinPressed_resetPointer() { - this._pointerId = null; - - window.removeEventListener("pointerup", this._pointerUpBound, true); - window.removeEventListener("pointercancel", this._pointerCancelBound, true); - this._element.removeEventListener("pointerover", this._pointerOverBound, true); - this._element.removeEventListener("pointerout", this._pointerOutBound, true); - - WinJS.Utilities.removeClass(this._element, WinJS.UI._WinPressed.winPressed); - }, - - dispose: function _WinPressed_dispose() { - if (this._disposed) { - return; - } - this._disposed = true; - - this._resetPointer(); - } - }, { - winPressed: "win-pressed" - }) - }), - /// - /// - /// Represents a navigation command in an NavBarContainer. - /// - /// - /// - /// - /// - /// ]]> - /// Styles the entire NavBarCommand control. - /// Styles the main button in a NavBarCommand. - /// Styles the split button in a NavBarCommand - /// Styles the icon in the main button of a NavBarCommand. - /// Styles the label in the main button of a NavBarCommand. - /// - /// - /// - NavBarCommand: WinJS.Namespace._lazy(function () { - var strings = { - get duplicateConstruction() { return WinJS.Resources._getWinJSString("ui/duplicateConstruction").value; } - }; - - var NavBarCommand = WinJS.Class.define(function NavBarCommand_ctor(element, options) { - /// - /// - /// Creates a new NavBarCommand. - /// - /// - /// The DOM element that will host the new NavBarCommand control. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. - /// Each property of the options object corresponds to one of the control's properties or events. - /// Event names must begin with "on". - /// - /// - /// The new NavBarCommand. - /// - /// - /// - element = element || document.createElement("DIV"); - options = options || {}; - - if (element.winControl) { - throw new WinJS.ErrorFromName("WinJS.UI.NavBarCommand.DuplicateConstruction", strings.duplicateConstruction); - } - - // Attaching JS control to DOM element - element.winControl = this; - this._element = element; - WinJS.Utilities.addClass(this.element, WinJS.UI.NavBarCommand._ClassName.navbarcommand); - WinJS.Utilities.addClass(this.element, "win-disposable"); - - this._tooltip = null; - this._splitOpened = false; - this._buildDom(); - element.addEventListener('keydown', this._keydownHandler.bind(this)); - - WinJS.UI.setOptions(this, options); - }, { - /// - element: { - get: function () { - return this._element; - } - }, - - /// - /// Gets or sets the label of the NavBarCommand. - /// - /// - label: { - get: function () { - return this._label; - }, - set: function (value) { - this._label = value; - this._labelEl.textContent = value; - } - }, - - /// - /// Gets or sets the tooltip of the NavBarCommand. - /// - /// - tooltip: { - get: function () { - return this._tooltip; - }, - set: function (value) { - this._tooltip = value; - if (this._tooltip || this._tooltip === "") { - this._element.setAttribute('title', this._tooltip); - } else { - this._element.removeAttribute('title'); - } - } - }, - - /// - /// Gets or sets the icon of the NavBarCommand. This value is either one of the values of the AppBarIcon enumeration or the path of a custom PNG file. - /// - /// - icon: { - get: function () { - return this._icon; - }, - set: function (value) { - this._icon = (WinJS.UI.AppBarIcon[value] || value); - - // If the icon's a single character, presume a glyph - if (this._icon && this._icon.length === 1) { - // Set the glyph - this._imageSpan.innerText = this._icon; - this._imageSpan.style.backgroundImage = ""; - this._imageSpan.style.msHighContrastAdjust = ""; - this._imageSpan.style.display = ""; - } else if (this._icon && this._icon.length > 1) { - // Must be an image, set that - this._imageSpan.innerText = ""; - this._imageSpan.style.backgroundImage = this._icon; - this._imageSpan.style.msHighContrastAdjust = "none"; - this._imageSpan.style.display = ""; - } else { - this._imageSpan.innerText = ""; - this._imageSpan.style.backgroundImage = ""; - this._imageSpan.style.msHighContrastAdjust = ""; - this._imageSpan.style.display = "none"; - } - } - }, - - /// - /// Gets or sets the command's target location. - /// - /// - location: { - get: function () { - return this._location; - }, - set: function (value) { - this._location = value; - } - }, - - /// - /// Gets or sets the state value used for navigation. The command passes this object to the WinJS.Navigation.navigate function. - /// - /// - state: { - get: function () { - return this._state; - }, - set: function (value) { - this._state = value; - } - }, - - /// - /// Gets or sets a value that specifies whether the NavBarCommand has a split button. - /// - /// - splitButton: { - get: function () { - return this._split; - }, - set: function (value) { - this._split = value; - if (this._split) { - this._splitButtonEl.style.display = "flex"; - } else { - this._splitButtonEl.style.display = "none"; - } - } - }, - - /// - splitOpened: { - get: function () { - return this._splitOpened; - }, - set: function (value) { - if (this._splitOpened !== !!value) { - this._toggleSplit(); - } - } - }, - - _toggleSplit: function NavBarCommand_toggleSplit() { - this._splitOpened = !this._splitOpened; - if (this._splitOpened) { - WinJS.Utilities.addClass(this._splitButtonEl, WinJS.UI.NavBarCommand._ClassName.navbarcommandsplitbuttonopened); - this._splitButtonEl.setAttribute("aria-expanded", "true"); - } else { - WinJS.Utilities.removeClass(this._splitButtonEl, WinJS.UI.NavBarCommand._ClassName.navbarcommandsplitbuttonopened); - this._splitButtonEl.setAttribute("aria-expanded", "false"); - } - this._fireEvent(WinJS.UI.NavBarCommand._EventName._splitToggle); - }, - - _rtl: { - get: function () { - return window.getComputedStyle(this.element).direction === "rtl"; - } - }, - - _keydownHandler: function NavBarCommand_keydownHandler(ev) { - if (ev.srcElement.msMatchesSelector(".win-interactive, .win-interactive *")) { - return; - } - - var leftStr = this._rtl ? "Right" : "Left"; - var rightStr = this._rtl ? "Left" : "Right"; - - if (!ev.altKey && (ev.key === leftStr || ev.key === "Home" || ev.key === "End") && ev.srcElement === this._splitButtonEl) { - this._splitButtonActive = false; - try { - this._buttonEl.setActive(); - } catch (e) { - } - if (ev.key === leftStr) { - ev.stopPropagation(); - } - ev.preventDefault(); - } else if (!ev.altKey && ev.key === rightStr && this.splitButton && (ev.srcElement === this._buttonEl || this._buttonEl.contains(ev.srcElement))) { - this._splitButtonActive = true; - try { - this._splitButtonEl.setActive(); - } catch (e) { - } - if (ev.key === rightStr) { - ev.stopPropagation(); - } - ev.preventDefault(); - } else if ((ev.key === "Spacebar" || ev.key === "Enter") && (ev.srcElement === this._buttonEl || this._buttonEl.contains(ev.srcElement))) { - if (this.location) { - WinJS.Navigation.navigate(this.location, this.state); - } - this._fireEvent(WinJS.UI.NavBarCommand._EventName._invoked); - } else if ((ev.key === "Spacebar" || ev.key === "Enter") && ev.srcElement === this._splitButtonEl) { - this._toggleSplit(); - } - }, - - _getFocusInto: function NavBarCommand_getFocusInto(key) { - var leftStr = this._rtl ? "Right" : "Left"; - if ((key === leftStr) && this.splitButton) { - this._splitButtonActive = true; - return this._splitButtonEl; - } else { - this._splitButtonActive = false; - return this._buttonEl; - } - }, - - _buildDom: function NavBarCommand_buildDom() { - var markup = - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - ''; - this.element.insertAdjacentHTML("afterBegin", markup); - - this._buttonEl = this.element.firstElementChild; - this._buttonPressedBehavior = new WinJS.UI._WinPressed(this._buttonEl); - this._contentEl = this._buttonEl.firstElementChild; - this._imageSpan = this._contentEl.firstElementChild; - this._imageSpan.style.display = "none"; - this._labelEl = this._imageSpan.nextElementSibling; - this._splitButtonEl = this._buttonEl.nextElementSibling; - this._splitButtonPressedBehavior = new WinJS.UI._WinPressed(this._splitButtonEl); - this._splitButtonEl.style.display = "none"; - - WinJS.UI._ensureId(this._buttonEl); - this._splitButtonEl.setAttribute("aria-labelledby", this._buttonEl.id); - - this._buttonEl.addEventListener("click", this._handleButtonClick.bind(this)); - this._buttonEl.addEventListener("beforeactivate", this._beforeactivateButtonHandler.bind(this)); - this._buttonEl.addEventListener("pointerdown", this._MSPointerDownButtonHandler.bind(this)); - - var mutationObserver = new MutationObserver(this._splitButtonAriaExpandedPropertyChangeHandler.bind(this)); - mutationObserver.observe(this._splitButtonEl, { attributes: true, attributeFilter: ["aria-expanded"] }); - this._splitButtonEl.addEventListener("click", this._handleSplitButtonClick.bind(this)); - this._splitButtonEl.addEventListener("beforeactivate", this._beforeactivateSplitButtonHandler.bind(this)); - this._splitButtonEl.addEventListener("pointerdown", this._MSPointerDownSplitButtonHandler.bind(this)); - - // reparent any other elements. - var tempEl = this._splitButtonEl.nextSibling; - while (tempEl) { - this._buttonEl.insertBefore(tempEl, this._contentEl); - if (tempEl.nodeName !== "#text") { - WinJS.UI.processAll(tempEl); - } - tempEl = this._splitButtonEl.nextSibling; - } - }, - - _MSPointerDownButtonHandler: function NavBarCommand_MSPointerDownButtonHandler(ev) { - this._splitButtonActive = false; - }, - - _MSPointerDownSplitButtonHandler: function NavBarCommand_MSPointerDownSplitButtonHandler(ev) { - this._splitButtonActive = true; - }, - - _handleButtonClick: function NavBarCommand_handleButtonClick(ev) { - var srcElement = ev.srcElement; - if (!srcElement.msMatchesSelector(".win-interactive, .win-interactive *")) { - if (this.location) { - WinJS.Navigation.navigate(this.location, this.state); - } - this._fireEvent(WinJS.UI.NavBarCommand._EventName._invoked); - } - }, - - _splitButtonAriaExpandedPropertyChangeHandler: function NavBarCommand_splitButtonAriaExpandedPropertyChangeHandler() { - if ((this._splitButtonEl.getAttribute("aria-expanded") === "true") !== this._splitOpened) { - this._toggleSplit(); - } - }, - - _handleSplitButtonClick: function NavBarCommand_handleSplitButtonClick(ev) { - this._toggleSplit(); - }, - - _beforeactivateSplitButtonHandler: function NavBarCommand_beforeactivateSplitButtonHandler(ev) { - if (!this._splitButtonActive) { - ev.stopPropagation(); - ev.preventDefault(); - } - }, - - _beforeactivateButtonHandler: function NavBarCommand_beforeactivateButtonHandler(ev) { - if (this._splitButtonActive) { - ev.stopPropagation(); - ev.preventDefault(); - } - }, - - _fireEvent: function NavBarCommand_fireEvent(type, detail) { - var event = document.createEvent("CustomEvent"); - event.initCustomEvent(type, true, false, detail); - this.element.dispatchEvent(event); - }, - - dispose: function NavBarCommand_dispose() { - /// - /// - /// Disposes this control. - /// - /// - /// - if (this._disposed) { - return; - } - this._disposed = true; - - this._buttonPressedBehavior.dispose(); - this._splitButtonPressedBehavior.dispose(); - } - }, { - _ClassName: { - navbarcommand: "win-navbarcommand", - navbarcommandbutton: "win-navbarcommand-button", - navbarcommandbuttoncontent: "win-navbarcommand-button-content", - navbarcommandsplitbutton: "win-navbarcommand-splitbutton", - navbarcommandsplitbuttonopened: "win-navbarcommand-splitbutton-opened", - navbarcommandicon: "win-navbarcommand-icon", - navbarcommandlabel: "win-navbarcommand-label" - }, - _EventName: { - _invoked: "_invoked", - _splitToggle: "_splittoggle" - } - }); - WinJS.Class.mix(NavBarCommand, WinJS.UI.DOMEventMixin); - return NavBarCommand; - }) - }); - -})(this, WinJS); - -(function tooltipInit(global) { - "use strict"; - - // Tooltip control implementation - WinJS.Namespace.define("WinJS.UI", { - /// - /// - /// Displays a tooltip that can contain images and formatting. - /// - /// - /// - /// - /// - /// ]]> - /// Raised when the tooltip is about to appear. - /// Raised when the tooltip is showing. - /// Raised when the tooltip is about to become hidden. - /// Raised when the tooltip is hidden. - /// The entire Tooltip control. - /// - /// - /// - Tooltip: WinJS.Namespace._lazy(function () { - var lastCloseTime = 0; - var utilities = WinJS.Utilities; - var animation = WinJS.UI.Animation; - - // Constants definition - var DEFAULT_PLACEMENT = "top"; - var DELAY_INITIAL_TOUCH_SHORT = 400; - var DELAY_INITIAL_TOUCH_LONG = 1200; - var DEFAULT_MOUSE_HOVER_TIME = 400; // 0.4 second - var DEFAULT_MESSAGE_DURATION = 5000; // 5 secs - var DELAY_RESHOW_NONINFOTIP_TOUCH = 0; - var DELAY_RESHOW_NONINFOTIP_NONTOUCH = 600; - var DELAY_RESHOW_INFOTIP_TOUCH = 400; - var DELAY_RESHOW_INFOTIP_NONTOUCH = 600; - var RESHOW_THRESHOLD = 200; - var HIDE_DELAY_MAX = 300000; // 5 mins - var OFFSET_KEYBOARD = 12; - var OFFSET_MOUSE = 20; - var OFFSET_TOUCH = 45; - var OFFSET_PROGRAMMATIC_TOUCH = 20; - var OFFSET_PROGRAMMATIC_NONTOUCH = 12; - var SAFETY_NET_GAP = 1; // We set a 1-pixel gap between the right or bottom edge of the tooltip and the viewport to avoid possible re-layout - var PT_TOUCH = MSPointerEvent.MSPOINTER_TYPE_TOUCH || "touch"; // pointer type to indicate a touch event - - var EVENTS_INVOKE = { "keyup": "", "pointerover": "" }, - EVENTS_UPDATE = { "pointermove": "" }, - EVENTS_DISMISS = { "pointerdown": "", "keydown": "", "blur": "", "pointerout": "", "pointercancel": "", "pointerup": "" }, - EVENTS_BY_CHILD = { "pointerover": "", "pointerout": "" }; - - // CSS class names - var msTooltip = "win-tooltip", - msTooltipPhantom = "win-tooltip-phantom"; - - // Global attributes - var mouseHoverTime = DEFAULT_MOUSE_HOVER_TIME, - nonInfoTooltipNonTouchShowDelay = 2 * mouseHoverTime, - infoTooltipNonTouchShowDelay = 2.5 * mouseHoverTime, - messageDuration = DEFAULT_MESSAGE_DURATION, - isLeftHanded = false; - - var hasInitWinRTSettings = false; - - var createEvent = WinJS.Utilities._createEventProperty; - - return WinJS.Class.define(function Tooltip_ctor(anchorElement, options) { - /// - /// - /// Creates a new Tooltip. - /// - /// - /// The DOM element that hosts the Tooltip. - /// - /// - /// An object that contains one or more property/value pairs to apply to the new control. - /// Each property of the options object corresponds to one of the control's properties or events. - /// Event names must begin with "on". For example, to provide a handler for the opened event, - /// add a property named "onopened" to the options object and set its value to the event handler. - /// This parameter is optional. - /// - /// - /// The new Tooltip. - /// - /// - /// - anchorElement = anchorElement || document.createElement("div"); - - var tooltip = utilities.data(anchorElement).tooltip; - if (tooltip) { - return tooltip; - } - - // Set system attributes if it is in WWA, otherwise, use the default values - if (!hasInitWinRTSettings && WinJS.Utilities.hasWinRT) { // in WWA - var uiSettings = new Windows.UI.ViewManagement.UISettings(); - mouseHoverTime = uiSettings.mouseHoverTime; - nonInfoTooltipNonTouchShowDelay = 2 * mouseHoverTime; - infoTooltipNonTouchShowDelay = 2.5 * mouseHoverTime; - messageDuration = uiSettings.messageDuration * 1000; // uiSettings.messageDuration is in seconds. - var handedness = uiSettings.handPreference; - isLeftHanded = (handedness == Windows.UI.ViewManagement.HandPreference.leftHanded); - } - hasInitWinRTSettings = true; - - // Need to initialize properties - this._disposed = false; - this._placement = DEFAULT_PLACEMENT; - this._infotip = false; - this._innerHTML = null; - this._contentElement = null; - this._extraClass = null; - this._lastContentType = "html"; - this._anchorElement = anchorElement; - this._domElement = null; - this._phantomDiv = null; - this._triggerByOpen = false; - this._eventListenerRemoveStack = []; - - // To handle keyboard navigation - this._lastKeyOrBlurEvent = null; - this._currentKeyOrBlurEvent = null; - - // Remember ourselves - anchorElement.winControl = this; - WinJS.Utilities.addClass(anchorElement, "win-disposable"); - - // If anchor element's title is defined, set as the default tooltip content - if (anchorElement.title) { - this._innerHTML = this._anchorElement.title; - this._anchorElement.removeAttribute("title"); - } - - WinJS.UI.setOptions(this, options); - this._events(); - utilities.data(anchorElement).tooltip = this; - }, { - /// - /// Gets or sets the HTML content of the Tooltip. - /// - /// - innerHTML: { - get: function () { - return this._innerHTML; - }, - set: function (value) { - this._innerHTML = value; - if (this._domElement) { - // If we set the innerHTML to null or "" while tooltip is up, we should close it - if (!this._innerHTML || this._innerHTML === "") { - this._onDismiss(); - return; - } - this._domElement.innerHTML = value; - this._position(); - } - this._lastContentType = "html"; - } - }, - - /// - element: { - get: function () { - return this._anchorElement; - } - }, - - /// - /// Gets or sets the DOM element that is the content for the ToolTip. - /// - /// - contentElement: { - get: function () { - return this._contentElement; - }, - set: function (value) { - this._contentElement = value; - if (this._domElement) { - // If we set the contentElement to null while tooltip is up, we should close it - if (!this._contentElement) { - this._onDismiss(); - return; - } - this._domElement.innerHTML = ""; - this._domElement.appendChild(this._contentElement); - this._position(); - } - this._lastContentType = "element"; - } - }, - - /// - /// Gets or sets the position for the Tooltip relative to its target element: top, bottom, left or right. - /// - /// - placement: { - get: function () { - return this._placement; - }, - set: function (value) { - if (value !== "top" && value !== "bottom" && value !== "left" && value !== "right") { - value = DEFAULT_PLACEMENT; - } - this._placement = value; - if (this._domElement) { - this._position(); - } - } - }, - - /// - /// Gets or sets a value that specifies whether the Tooltip is an infotip, a tooltip that contains - /// a lot of info and should be displayed for longer than a typical Tooltip. - /// The default value is false. - /// - /// - infotip: { - get: function () { - return this._infotip; - }, - set: function (value) { - this._infotip = !!value; //convert the value to boolean - } - }, - - /// - /// Gets or sets additional CSS classes to apply to the Tooltip control's host element. - /// - /// - extraClass: { - get: function () { - return this._extraClass; - }, - set: function (value) { - this._extraClass = value; - } - }, - - /// - /// Raised just before the Tooltip appears. - /// - /// - onbeforeopen: createEvent("beforeopen"), - - /// - /// Raised when the Tooltip is shown. - /// - /// - onopened: createEvent("opened"), - - /// - /// Raised just before the Tooltip is hidden. - /// - /// - onbeforeclose: createEvent("beforeclose"), - - /// - /// Raised when the Tooltip is no longer displayed. - /// - /// - onclosed: createEvent("closed"), - - dispose: function () { - /// - /// - /// Disposes this Tooltip. - /// - /// - /// - if (this._disposed) { - return; - } - - this._disposed = true; - WinJS.Utilities.disposeSubTree(this.element); - for (var i = 0, len = this._eventListenerRemoveStack.length; i < len; i++) { - this._eventListenerRemoveStack[i](); - } - this._onDismiss(); - var data = utilities.data(this._anchorElement); - if (data) { - delete data.tooltip; - } - }, - - addEventListener: function (eventName, eventCallBack, capture) { - /// - /// - /// Registers an event handler for the specified event. - /// - /// The name of the event. - /// The event handler function to associate with this event. - /// Set to true to register the event handler for the capturing phase; set to false to register for the bubbling phase. - /// - /// - - if (this._anchorElement) { - this._anchorElement.addEventListener(eventName, eventCallBack, capture); - - var that = this; - this._eventListenerRemoveStack.push(function () { - that._anchorElement.removeEventListener(eventName, eventCallBack, capture); - }); - } - }, - - removeEventListener: function (eventName, eventCallBack, capture) { - /// - /// - /// Unregisters an event handler for the specified event. - /// - /// The name of the event. - /// The event handler function to remove. - /// Set to true to unregister the event handler for the capturing phase; otherwise, set to false to unregister the event handler for the bubbling phase. - /// - /// - - if (this._anchorElement) { - this._anchorElement.removeEventListener(eventName, eventCallBack, capture); - } - }, - - open: function (type) { - /// - /// - /// Shows the Tooltip. - /// - /// The type of tooltip to show: "touch", "mouseover", "mousedown", or "keyboard". The default value is "mousedown". - /// - /// - - // Open takes precedence over other triggering events - // Once tooltip is opened using open(), it can only be closed by time out(mouseover or keyboard) or explicitly by close(). - this._triggerByOpen = true; - - if (type !== "touch" && type !== "mouseover" && type !== "mousedown" && type !== "keyboard") { - type = "default"; - } - - switch (type) { - case "touch": - this._onInvoke("touch", "never"); - break; - case "mouseover": - this._onInvoke("mouse", "auto"); - break; - case "keyboard": - this._onInvoke("keyboard", "auto"); - break; - case "mousedown": - case "default": - this._onInvoke("nodelay", "never"); - break; - } - - }, - - close: function () { - /// - /// - /// Hids the Tooltip. - /// - /// - /// - - this._onDismiss(); - }, - - _cleanUpDOM: function () { - if (this._domElement) { - WinJS.Utilities.disposeSubTree(this._domElement); - document.body.removeChild(this._domElement); - this._domElement = null; - - document.body.removeChild(this._phantomDiv); - this._phantomDiv = null; - } - }, - - _createTooltipDOM: function () { - this._cleanUpDOM(); - - this._domElement = document.createElement("div"); - - var id = this._domElement.uniqueID; - this._domElement.setAttribute("id", id); - - // Set the direction of tooltip according to anchor element's - var computedStyle = document.defaultView.getComputedStyle(this._anchorElement, null); - var elemStyle = this._domElement.style; - elemStyle.direction = computedStyle.direction; - elemStyle.writingMode = computedStyle["writing-mode"]; // must use CSS name, not JS name - - // Make the tooltip non-focusable - this._domElement.setAttribute("tabindex", -1); - - // Set the aria tags for accessibility - this._domElement.setAttribute("role", "tooltip"); - this._anchorElement.setAttribute("aria-describedby", id); - - // Set the tooltip content - if (this._lastContentType === "element") { // Last update through contentElement option - this._domElement.appendChild(this._contentElement); - } else { // Last update through innerHTML option - this._domElement.innerHTML = this._innerHTML; - } - - document.body.appendChild(this._domElement); - utilities.addClass(this._domElement, msTooltip); - - // In the event of user-assigned classes, add those too - if (this._extraClass) { - utilities.addClass(this._domElement, this._extraClass); - } - - // Create a phantom div on top of the tooltip div to block all interactions - this._phantomDiv = document.createElement("div"); - this._phantomDiv.setAttribute("tabindex", -1); - document.body.appendChild(this._phantomDiv); - utilities.addClass(this._phantomDiv, msTooltipPhantom); - var zIndex = document.defaultView.getComputedStyle(this._domElement, null).zIndex + 1; - this._phantomDiv.style.zIndex = zIndex; - }, - - _raiseEvent: function (type, eventProperties) { - if (this._anchorElement) { - var customEvent = document.createEvent("CustomEvent"); - customEvent.initCustomEvent(type, false, false, eventProperties); - this._anchorElement.dispatchEvent(customEvent); - } - }, - - // Support for keyboard navigation - _captureLastKeyBlurOrPointerOverEvent: function (event, listener) { - listener._lastKeyOrBlurEvent = listener._currentKeyOrBlurEvent; - switch (event.type) { - case "keyup": - if (event.key === "Shift") { - listener._currentKeyOrBlurEvent = null; - } else { - listener._currentKeyOrBlurEvent = "keyboard"; - } - break; - case "blur": - //anchor elment no longer in focus, clear up the stack - listener._currentKeyOrBlurEvent = null; - break; - default: - break; - - } - }, - - _registerEventToListener: function (element, eventType, listener) { - var handler = function (event) { - listener._captureLastKeyBlurOrPointerOverEvent(event, listener); - listener._handleEvent(event); - }; - element.addEventListener(eventType, handler, false); - - this._eventListenerRemoveStack.push(function () { - element.removeEventListener(eventType, handler, false); - }); - }, - - _events: function () { - for (var eventType in EVENTS_INVOKE) { - this._registerEventToListener(this._anchorElement, eventType, this); - } - for (var eventType in EVENTS_UPDATE) { - this._registerEventToListener(this._anchorElement, eventType, this); - } - for (eventType in EVENTS_DISMISS) { - this._registerEventToListener(this._anchorElement, eventType, this); - } - - - }, - - _handleEvent: function (event) { - var eventType = event.type; - if (!this._triggerByOpen) { - // If the anchor element has children, we should ignore events that are caused within the anchor element - // Please note that we are not using event.target here as in bubbling phases from the child, the event target - // is usually the child - if (eventType in EVENTS_BY_CHILD) { - var elem = event.relatedTarget; - - while (elem && elem !== this._anchorElement && elem !== document.body) { - try { - elem = elem.parentNode; - } - catch (e) { - if (e instanceof Error && e.message === 'Permission denied') { - //Permission denied error, if we can't access the node's - //information, we should not handle the event - //Put this guard prior Bug 484666 is fixed - return; - } - else { - throw e; - } - } - } - if (elem === this._anchorElement) { - return; - } - } - if (eventType in EVENTS_INVOKE) { - if (event.pointerType == PT_TOUCH) { - this._onInvoke("touch", "never", event); - this._showTrigger = "touch"; - } else { - var type = eventType.substring(0, 3) === "key" ? "keyboard" : "mouse"; - this._onInvoke(type, "auto", event); - this._showTrigger = type; - } - } else if (eventType in EVENTS_UPDATE) { - this._contactPoint = { x: event.clientX, y: event.clientY }; - } else if (eventType in EVENTS_DISMISS) { - var eventTrigger; - if (event.pointerType == PT_TOUCH) { - if (eventType == "pointerdown") { - return; - } - eventTrigger = "touch"; - } - else { - eventTrigger = eventType.substring(0, 3) === "key" ? "keyboard" : "mouse"; - } - if (eventType != "blur" && eventTrigger != this._showTrigger) { - return; - } - this._onDismiss(); - } - } - }, - - _onShowAnimationEnd: function () { - if (this._shouldDismiss || this._disposed) { - return; - } - this._raiseEvent("opened"); - if (this._domElement) { - if (this._hideDelay !== "never") { - var that = this; - var delay = this._infotip ? Math.min(3 * messageDuration, HIDE_DELAY_MAX) : messageDuration; - this._hideDelayTimer = setTimeout(function () { - that._onDismiss(); - }, delay); - } - } - }, - - - _onHideAnimationEnd: function () { - document.body.removeEventListener("DOMNodeRemoved", this._removeTooltip, false); - this._cleanUpDOM(); - // Once we remove the tooltip from the DOM, we should remove the aria tag from the anchor - if (this._anchorElement) { - this._anchorElement.removeAttribute("aria-describedby"); - } - lastCloseTime = (new Date()).getTime(); - this._triggerByOpen = false; - if (!this._disposed) { - this._raiseEvent("closed"); - } - }, - - _decideOnDelay: function (type) { - var value; - this._useAnimation = true; - - if (type == "nodelay") { - value = 0; - this._useAnimation = false; - } - else { - var curTime = (new Date()).getTime(); - // If the mouse is moved immediately from another anchor that has - // tooltip open, we should use a shorter delay - if (curTime - lastCloseTime <= RESHOW_THRESHOLD) { - if (type == "touch") { - value = this._infotip ? DELAY_RESHOW_INFOTIP_TOUCH : DELAY_RESHOW_NONINFOTIP_TOUCH; - } - else { - value = this._infotip ? DELAY_RESHOW_INFOTIP_NONTOUCH : DELAY_RESHOW_NONINFOTIP_NONTOUCH; - } - this._useAnimation = false; - } else if (type == "touch") { - value = this._infotip ? DELAY_INITIAL_TOUCH_LONG : DELAY_INITIAL_TOUCH_SHORT; - } else { - value = this._infotip ? infoTooltipNonTouchShowDelay : nonInfoTooltipNonTouchShowDelay; - } - } - return value; - }, - - // This function returns the anchor element's position in the Window coordinates. - _getAnchorPositionFromElementWindowCoord: function () { - var rect = this._anchorElement.getBoundingClientRect(); - - return { - x: rect.left, - y: rect.top, - width: rect.width, - height: rect.height - }; - }, - - _getAnchorPositionFromPointerWindowCoord: function (contactPoint) { - return { - x: contactPoint.x, - y: contactPoint.y, - width: 1, - height: 1 - }; - }, - - _canPositionOnSide: function (placement, viewport, anchor, tip) { - var availWidth = 0, availHeight = 0; - - switch (placement) { - case "top": - availWidth = tip.width + this._offset; - availHeight = anchor.y; - break; - case "bottom": - availWidth = tip.width + this._offset; - availHeight = viewport.height - anchor.y - anchor.height; - break; - case "left": - availWidth = anchor.x; - availHeight = tip.height + this._offset; - break; - case "right": - availWidth = viewport.width - anchor.x - anchor.width; - availHeight = tip.height + this._offset; - break; - } - return ((availWidth >= tip.width + this._offset) && (availHeight >= tip.height + this._offset)); - }, - - _positionOnSide: function (placement, viewport, anchor, tip) { - var left = 0, top = 0; - - switch (placement) { - case "top": - case "bottom": - // Align the tooltip to the anchor's center horizontally - left = anchor.x + anchor.width / 2 - tip.width / 2; - - // If the left boundary is outside the window, set it to 0 - // If the right boundary is outside the window, set it to align with the window right boundary - left = Math.min(Math.max(left, 0), viewport.width - tip.width - SAFETY_NET_GAP); - - top = (placement == "top") ? anchor.y - tip.height - this._offset : anchor.y + anchor.height + this._offset; - break; - case "left": - case "right": - // Align the tooltip to the anchor's center vertically - top = anchor.y + anchor.height / 2 - tip.height / 2; - - // If the top boundary is outside the window, set it to 0 - // If the bottom boundary is outside the window, set it to align with the window bottom boundary - top = Math.min(Math.max(top, 0), viewport.height - tip.height - SAFETY_NET_GAP); - - left = (placement == "left") ? anchor.x - tip.width - this._offset : anchor.x + anchor.width + this._offset; - break; - } - - // Actually set the position - this._domElement.style.left = left + "px"; - this._domElement.style.top = top + "px"; - - // Set the phantom's position and size - this._phantomDiv.style.left = left + "px"; - this._phantomDiv.style.top = top + "px"; - this._phantomDiv.style.width = tip.width + "px"; - this._phantomDiv.style.height = tip.height + "px"; - }, - - _position: function (contactType) { - var viewport = { width: 0, height: 0 }; - var anchor = { x: 0, y: 0, width: 0, height: 0 }; - var tip = { width: 0, height: 0 }; - - viewport.width = document.documentElement.clientWidth; - viewport.height = document.documentElement.clientHeight; - if (document.defaultView.getComputedStyle(document.body, null)["writing-mode"] === "tb-rl") { - viewport.width = document.documentElement.clientHeight; - viewport.height = document.documentElement.clientWidth; - } - - if (this._contactPoint && (contactType === "touch" || contactType === "mouse")) { - anchor = this._getAnchorPositionFromPointerWindowCoord(this._contactPoint); - } - else { - // keyboard or programmatic is relative to element - anchor = this._getAnchorPositionFromElementWindowCoord(); - } - tip.width = this._domElement.offsetWidth; - tip.height = this._domElement.offsetHeight; - var fallback_order = { - "top": ["top", "bottom", "left", "right"], - "bottom": ["bottom", "top", "left", "right"], - "left": ["left", "right", "top", "bottom"], - "right": ["right", "left", "top", "bottom"] - }; - if (isLeftHanded) { - fallback_order.top[2] = "right"; - fallback_order.top[3] = "left"; - fallback_order.bottom[2] = "right"; - fallback_order.bottom[3] = "left"; - } - - // Try to position the tooltip according to the placement preference - // We use this order: - // 1. Try the preferred placement - // 2. Try the opposite placement - // 3. If the preferred placement is top or bottom, we should try left - // and right (or right and left if left handed) - // If the preferred placement is left or right, we should try top and bottom - var order = fallback_order[this._placement]; - var length = order.length; - for (var i = 0; i < length; i++) { - if (i == length - 1 || this._canPositionOnSide(order[i], viewport, anchor, tip)) { - this._positionOnSide(order[i], viewport, anchor, tip); - break; - } - } - return order[i]; - }, - - _showTooltip: function (contactType) { - // Give a chance to dismiss the tooltip before it starts to show - if (this._shouldDismiss) { - return; - } - this._isShown = true; - this._raiseEvent("beforeopen"); - - // If the anchor is not in the DOM tree, we don't create the tooltip - if (!document.body.contains(this._anchorElement)) { - return; - } - if (this._shouldDismiss) { - return; - } - - // If the contentElement is set to null or innerHTML set to null or "", we should NOT show the tooltip - if (this._lastContentType === "element") { // Last update through contentElement option - if (!this._contentElement) { - this._isShown = false; - return; - } - } else { // Last update through innerHTML option - if (!this._innerHTML || this._innerHTML === "") { - this._isShown = false; - return; - } - } - - var that = this; - this._removeTooltip = function (event) { - var current = that._anchorElement; - while (current) { - if (event.target == current) { - document.body.removeEventListener("DOMNodeRemoved", that._removeTooltip, false); - that._cleanUpDOM(); - break; - } - current = current.parentNode; - } - }; - - document.body.addEventListener("DOMNodeRemoved", this._removeTooltip, false); - this._createTooltipDOM(); - var pos = this._position(contactType); - var that = this; - if (this._useAnimation) { - animation.fadeIn(this._domElement) - .then(this._onShowAnimationEnd.bind(this)); - } else { - this._onShowAnimationEnd(); - } - }, - - _onInvoke: function (type, hide, event) { - // Reset the dismiss flag - this._shouldDismiss = false; - - // If the tooltip is already shown, ignore the current event - if (this._isShown) { - return; - } - - // To handle keyboard support, we only want to display tooltip on the first tab key event only - if (event && event.type === "keyup") { - if (this._lastKeyOrBlurEvent == "keyboard" || - !this._lastKeyOrBlurEvent && event.key !== "Tab") { - return; - } - } - - // Set the hide delay, - this._hideDelay = hide; - - this._contactPoint = null; - if (event) { // Open through interaction - this._contactPoint = { x: event.clientX, y: event.clientY }; - // Tooltip display offset differently for touch events and non-touch events - if (type == "touch") { - this._offset = OFFSET_TOUCH; - } else if (type === "keyboard") { - this._offset = OFFSET_KEYBOARD; - } else { - this._offset = OFFSET_MOUSE; - } - } else { // Open Programmatically - if (type == "touch") { - this._offset = OFFSET_PROGRAMMATIC_TOUCH; - } else { - this._offset = OFFSET_PROGRAMMATIC_NONTOUCH; - } - } - - clearTimeout(this._delayTimer); - clearTimeout(this._hideDelayTimer); - - // Set the delay time - var delay = this._decideOnDelay(type); - if (delay > 0) { - var that = this; - this._delayTimer = setTimeout(function () { - that._showTooltip(type); - }, delay); - } else { - this._showTooltip(type); - } - }, - - _onDismiss: function () { - // Set the dismiss flag so that we don't miss dismiss events - this._shouldDismiss = true; - - // If the tooltip is already dismissed, ignore the current event - if (!this._isShown) { - return; - } - - this._isShown = false; - - // Reset tooltip state - this._showTrigger = "mouse"; - - if (this._domElement) { - this._raiseEvent("beforeclose"); - if (this._useAnimation) { - animation.fadeOut(this._domElement) - .then(this._onHideAnimationEnd.bind(this)); - } else { - this._onHideAnimationEnd(); - } - } else { - this._raiseEvent("beforeclose"); - this._raiseEvent("closed"); - } - } - }); - }) - }); - -})(this, WinJS); -// ViewBox control -(function viewboxInit(global, undefined) { - "use strict"; - - WinJS.Namespace.define("WinJS.UI", { - /// - /// Scales a single child element to fill the available space without - /// resizing it. This control reacts to changes in the size of the container as well as - /// changes in size of the child element. For example, a media query may result in - /// a change in aspect ratio. - /// - /// View Box - /// - /// - ///
    ViewBox
    ]]>
    - /// - /// - /// - ViewBox: WinJS.Namespace._lazy(function () { - var Scheduler = WinJS.Utilities.Scheduler; - - var strings = { - get invalidViewBoxChildren() { return WinJS.Resources._getWinJSString("ui/invalidViewBoxChildren").value; }, - }; - - function onresize(control) { - if (control && !control._resizing) { - control._resizing = control._resizing || 0; - control._resizing++; - try { - control._updateLayout(); - } finally { - control._resizing--; - } - } - } - - function onresizeBox(ev) { - if (ev.srcElement) { - onresize(ev.srcElement.winControl); - } - } - - function onresizeSizer(ev) { - if (ev.srcElement) { - onresize(ev.srcElement.parentElement.winControl); - } - } - - var ViewBox = WinJS.Class.define(function ViewBox_ctor(element, options) { - /// - /// Initializes a new instance of the ViewBox control - /// - /// The DOM element that functions as the scaling box. This element fills 100% of the width and height allotted to it. - /// - /// - /// The set of options to be applied initially to the ViewBox control. - /// - /// A constructed ViewBox control. - /// - this._disposed = false; - - this._element = element || document.createElement("div"); - var box = this.element; - box.winControl = this; - WinJS.Utilities.addClass(box, "win-disposable"); - WinJS.Utilities.addClass(box, "win-viewbox"); - this.forceLayout(); - }, { - _sizer: null, - _element: null, - - /// - element: { - get: function () { return this._element; } - }, - - _rtl: { - get: function () { - return window.getComputedStyle(this.element).direction === "rtl"; - } - }, - - _initialize: function () { - var box = this.element; - if (box.firstElementChild !== this._sizer) { - if (WinJS.validation) { - if (box.childElementCount != 1) { - throw new WinJS.ErrorFromName("WinJS.UI.ViewBox.InvalidChildren", strings.invalidViewBoxChildren); - } - } - if (this._sizer) { - this._sizer.onresize = null; - } - var sizer = box.firstElementChild; - this._sizer = sizer; - if (sizer) { - box.addEventListener("mselementresize", onresizeBox); - sizer.addEventListener("mselementresize", onresizeSizer); - } - if (box.clientWidth === 0 && box.clientHeight === 0) { - var that = this; - // Wait for the viewbox to get added to the DOM. It should be added - // in the synchronous block in which _initialize was called. - Scheduler.schedule(function () { - that._updateLayout(); - }, Scheduler.Priority.normal, null, "WinJS.UI.ViewBox._updateLayout") - } - } - }, - _updateLayout: function () { - var sizer = this._sizer; - if (sizer) { - var box = this.element; - var w = sizer.clientWidth; - var h = sizer.clientHeight; - var bw = box.clientWidth; - var bh = box.clientHeight; - var wRatio = bw / w; - var hRatio = bh / h; - var mRatio = Math.min(wRatio, hRatio); - var transX = Math.abs(bw - (w * mRatio)) / 2; - var transY = Math.abs(bh - (h * mRatio)) / 2; - var rtl = this._rtl; - this._sizer.style["transform"] = "translate(" + (rtl ? "-" : "") + transX + "px," + transY + "px) scale(" + mRatio + ")"; - this._sizer.style["transform-origin"] = rtl ? "top right" : "top left"; - } - }, - - dispose: function () { - /// - /// - /// Disposes this ViewBox. - /// - /// - if (this._disposed) { - return; - } - - this._disposed = true; - WinJS.Utilities.disposeSubTree(this._element); - }, - - forceLayout: function () { - this._initialize(); - this._updateLayout(); - } - }); - WinJS.Class.mix(ViewBox, WinJS.UI.DOMEventMixin); - return ViewBox; - }) - }); - -}(this)); - -msWriteProfilerMark("Microsoft.WinJS.2.0 1.0.9600.17018.winblue_gdr.140204-1946 ui.js,StopTM"); - diff --git a/shared/html/reader.html b/shared/html/reader.html index 41ddff7..fd81c5f 100644 --- a/shared/html/reader.html +++ b/shared/html/reader.html @@ -8,13 +8,15 @@ - + +