├── i
├── about
│ ├── box.png
│ ├── dots.png
│ ├── info.png
│ ├── pass.png
│ ├── top.png
│ ├── wild.png
│ ├── bottom.png
│ ├── corner.png
│ ├── empty.png
│ ├── start.png
│ ├── influence.png
│ └── white_to_play.png
├── dot_clear.gif
├── ghost-black.png
├── ghost-white.png
├── in_progress.gif
├── simple-black.png
├── simple-white.png
├── tools
│ ├── help_20.png
│ ├── help_30.png
│ ├── home_20.png
│ ├── home_30.png
│ ├── info_20.png
│ ├── info_30.png
│ ├── update_20.png
│ ├── update_30.png
│ ├── hey-text-green.png
│ ├── subscribe_20.png
│ ├── subscribe_30.png
│ └── empty-text-green.png
├── ajax-loader-black.gif
├── board
│ └── temporary
│ │ ├── tile0.png
│ │ ├── tile0c.png
│ │ ├── tile0e.png
│ │ ├── tile0n.png
│ │ ├── tile0s.png
│ │ ├── tile0w.png
│ │ ├── tile1.png
│ │ ├── tile1d.png
│ │ ├── tile1e.png
│ │ ├── tile1l.png
│ │ ├── tile1n.png
│ │ ├── tile1s.png
│ │ ├── tile1w.png
│ │ ├── tile2.png
│ │ ├── tile2d.png
│ │ ├── tile2e.png
│ │ ├── tile2l.png
│ │ ├── tile2n.png
│ │ ├── tile2s.png
│ │ ├── tile2w.png
│ │ ├── tile0ne.png
│ │ ├── tile0nw.png
│ │ ├── tile0se.png
│ │ ├── tile0sw.png
│ │ ├── tile1ed.png
│ │ ├── tile1el.png
│ │ ├── tile1nd.png
│ │ ├── tile1ne.png
│ │ ├── tile1ned.png
│ │ ├── tile1nel.png
│ │ ├── tile1nl.png
│ │ ├── tile1nw.png
│ │ ├── tile1nwd.png
│ │ ├── tile1nwl.png
│ │ ├── tile1sd.png
│ │ ├── tile1se.png
│ │ ├── tile1sed.png
│ │ ├── tile1sel.png
│ │ ├── tile1sl.png
│ │ ├── tile1sw.png
│ │ ├── tile1swd.png
│ │ ├── tile1swl.png
│ │ ├── tile1wd.png
│ │ ├── tile1wl.png
│ │ ├── tile2ed.png
│ │ ├── tile2el.png
│ │ ├── tile2nd.png
│ │ ├── tile2ne.png
│ │ ├── tile2ned.png
│ │ ├── tile2nel.png
│ │ ├── tile2nl.png
│ │ ├── tile2nw.png
│ │ ├── tile2nwd.png
│ │ ├── tile2nwl.png
│ │ ├── tile2sd.png
│ │ ├── tile2se.png
│ │ ├── tile2sed.png
│ │ ├── tile2sel.png
│ │ ├── tile2sl.png
│ │ ├── tile2sw.png
│ │ ├── tile2swd.png
│ │ ├── tile2swl.png
│ │ ├── tile2wd.png
│ │ └── tile2wl.png
└── themes
│ └── jqt
│ └── img
│ ├── button.png
│ ├── chevron.png
│ ├── loading.gif
│ ├── on_off.png
│ ├── rowhead.png
│ ├── toggle.png
│ ├── toolbar.png
│ ├── grayButton.png
│ ├── toggleOn.png
│ ├── back_button.png
│ ├── whiteButton.png
│ ├── button_clicked.png
│ ├── chevron_circle.png
│ └── back_button_clicked.png
├── .gitignore
├── .gitmodules
├── j
├── jquery.combinators.js
├── load.images.js
├── jquery.timers-1.2.js
├── history.js
├── start.js
├── dragscrollable.js
├── to-function.js
├── md5.js
├── ui.js
├── go.js
└── igesture.jquery.mobile_safari.js
├── c
├── application.css
├── sass
│ ├── application.sass
│ ├── board.iphone.sass
│ ├── jqtouch.ipad.customized.sass
│ └── board.ipad.sass
├── jqtouch.min.css
├── jqtouch.css
└── jqtouch.ipad.customized.css
├── cache.manifest
├── haml
└── index.html.haml
├── index.html
└── readme.md
/i/about/box.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/box.png
--------------------------------------------------------------------------------
/i/about/dots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/dots.png
--------------------------------------------------------------------------------
/i/about/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/info.png
--------------------------------------------------------------------------------
/i/about/pass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/pass.png
--------------------------------------------------------------------------------
/i/about/top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/top.png
--------------------------------------------------------------------------------
/i/about/wild.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/wild.png
--------------------------------------------------------------------------------
/i/dot_clear.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/dot_clear.gif
--------------------------------------------------------------------------------
/i/about/bottom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/bottom.png
--------------------------------------------------------------------------------
/i/about/corner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/corner.png
--------------------------------------------------------------------------------
/i/about/empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/empty.png
--------------------------------------------------------------------------------
/i/about/start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/start.png
--------------------------------------------------------------------------------
/i/ghost-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/ghost-black.png
--------------------------------------------------------------------------------
/i/ghost-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/ghost-white.png
--------------------------------------------------------------------------------
/i/in_progress.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/in_progress.gif
--------------------------------------------------------------------------------
/i/simple-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/simple-black.png
--------------------------------------------------------------------------------
/i/simple-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/simple-white.png
--------------------------------------------------------------------------------
/i/about/influence.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/influence.png
--------------------------------------------------------------------------------
/i/tools/help_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/help_20.png
--------------------------------------------------------------------------------
/i/tools/help_30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/help_30.png
--------------------------------------------------------------------------------
/i/tools/home_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/home_20.png
--------------------------------------------------------------------------------
/i/tools/home_30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/home_30.png
--------------------------------------------------------------------------------
/i/tools/info_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/info_20.png
--------------------------------------------------------------------------------
/i/tools/info_30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/info_30.png
--------------------------------------------------------------------------------
/i/tools/update_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/update_20.png
--------------------------------------------------------------------------------
/i/tools/update_30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/update_30.png
--------------------------------------------------------------------------------
/i/ajax-loader-black.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/ajax-loader-black.gif
--------------------------------------------------------------------------------
/i/about/white_to_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/about/white_to_play.png
--------------------------------------------------------------------------------
/i/tools/hey-text-green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/hey-text-green.png
--------------------------------------------------------------------------------
/i/tools/subscribe_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/subscribe_20.png
--------------------------------------------------------------------------------
/i/tools/subscribe_30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/subscribe_30.png
--------------------------------------------------------------------------------
/i/board/temporary/tile0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile0.png
--------------------------------------------------------------------------------
/i/board/temporary/tile0c.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile0c.png
--------------------------------------------------------------------------------
/i/board/temporary/tile0e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile0e.png
--------------------------------------------------------------------------------
/i/board/temporary/tile0n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile0n.png
--------------------------------------------------------------------------------
/i/board/temporary/tile0s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile0s.png
--------------------------------------------------------------------------------
/i/board/temporary/tile0w.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile0w.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1d.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1e.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1l.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1l.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1n.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1s.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1w.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1w.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2d.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2e.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2l.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2l.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2n.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2s.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2w.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2w.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/button.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/chevron.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/chevron.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/loading.gif
--------------------------------------------------------------------------------
/i/themes/jqt/img/on_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/on_off.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/rowhead.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/rowhead.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/toggle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/toggle.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/toolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/toolbar.png
--------------------------------------------------------------------------------
/i/tools/empty-text-green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/tools/empty-text-green.png
--------------------------------------------------------------------------------
/i/board/temporary/tile0ne.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile0ne.png
--------------------------------------------------------------------------------
/i/board/temporary/tile0nw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile0nw.png
--------------------------------------------------------------------------------
/i/board/temporary/tile0se.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile0se.png
--------------------------------------------------------------------------------
/i/board/temporary/tile0sw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile0sw.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1ed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1ed.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1el.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1el.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1nd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1nd.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1ne.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1ne.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1ned.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1ned.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1nel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1nel.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1nl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1nl.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1nw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1nw.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1nwd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1nwd.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1nwl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1nwl.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1sd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1sd.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1se.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1se.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1sed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1sed.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1sel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1sel.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1sl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1sl.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1sw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1sw.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1swd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1swd.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1swl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1swl.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1wd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1wd.png
--------------------------------------------------------------------------------
/i/board/temporary/tile1wl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile1wl.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2ed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2ed.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2el.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2el.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2nd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2nd.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2ne.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2ne.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2ned.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2ned.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2nel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2nel.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2nl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2nl.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2nw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2nw.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2nwd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2nwd.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2nwl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2nwl.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2sd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2sd.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2se.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2se.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2sed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2sed.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2sel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2sel.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2sl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2sl.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2sw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2sw.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2swd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2swd.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2swl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2swl.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2wd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2wd.png
--------------------------------------------------------------------------------
/i/board/temporary/tile2wl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/board/temporary/tile2wl.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/grayButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/grayButton.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/toggleOn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/toggleOn.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/back_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/back_button.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/whiteButton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/whiteButton.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | log/*.log
2 | db/*.sqlite3
3 | tmp/**/*
4 | doc/api
5 | doc/app
6 | doc/plugins
7 | config/environments/development.rb
8 |
--------------------------------------------------------------------------------
/i/themes/jqt/img/button_clicked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/button_clicked.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/chevron_circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/chevron_circle.png
--------------------------------------------------------------------------------
/i/themes/jqt/img/back_button_clicked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/raganwald/wood_and_stones/HEAD/i/themes/jqt/img/back_button_clicked.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "./vendor/plugins/rewrite_rails"]
2 | path = ./vendor/plugins/rewrite_rails
3 | url = git://github.com/raganwald/rewrite_rails.git
4 | [submodule "vendor/plugins/shoulda"]
5 | path = vendor/plugins/shoulda
6 | url = git://github.com/thoughtbot/shoulda.git
7 | [submodule "vendor/plugins/haml"]
8 | path = vendor/plugins/haml
9 | url = git://github.com/nex3/haml.git
10 | [submodule "vendor/plugins/state_machine"]
11 | path = vendor/plugins/state_machine
12 | url = git://github.com/pluginaweek/state_machine.git
13 | [submodule "vendor/plugins/delayed_job"]
14 | path = vendor/plugins/delayed_job
15 | url = git://github.com/tobi/delayed_job.git
16 | [submodule "vendor/plugins/mocha"]
17 | path = vendor/plugins/mocha
18 | url = git://github.com/floehopper/mocha.git
19 |
--------------------------------------------------------------------------------
/j/jquery.combinators.js:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License
3 |
4 | Copyright (c) 2010 Reginald Braithwaite http://reginald.braythwayt.com
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 | */
24 |
25 |
26 | ;(function ($) {
27 | $.fn.K = function (fn) {
28 | fn(this);
29 | return this;
30 | };
31 | $.fn.T = function (fn) {
32 | return fn(this);
33 | };
34 | })(jQuery);
--------------------------------------------------------------------------------
/c/application.css:
--------------------------------------------------------------------------------
1 | .invisible {
2 | visibility: hidden; }
3 |
4 | .slideback.in {
5 | -webkit-animation-name: slideinfromleft; }
6 |
7 | .slideback.out {
8 | -webkit-animation-name: slideouttoright; }
9 |
10 | .slideback.in.reverse {
11 | -webkit-animation-name: slideouttoright; }
12 |
13 | .slideback.out.reverse {
14 | -webkit-animation-name: slideinfromleft; }
15 |
16 | .in_progress:before {
17 | content: url(../i/in_progress.gif); }
18 |
19 | .profile .foot .toolbar {
20 | -webkit-transform: rotate(180deg);
21 | -moz-transform: rotate(180deg); }
22 |
23 | .landscape .foot .toolbar {
24 | display: none; }
25 |
26 | .head.triangle-right {
27 | left: 25%;
28 | margin-left: -12.5%;
29 | width: 25%;
30 | margin-bottom: 10px;
31 | z-index: 1; }
32 |
33 | .foot.triangle-right {
34 | left: 75%;
35 | margin-left: -12.5%;
36 | width: 25%;
37 | z-index: 1;
38 | margin-top: 10px; }
39 |
40 | .new_game ul li {
41 | position: relative !important; }
42 | .new_game ul li .label {
43 | position: absolute;
44 | left: 10px; }
45 | .new_game .email {
46 | height: 40px !important; }
47 | .new_game .size {
48 | padding-left: 70px !important; }
49 | .new_game .you_play {
50 | padding-left: 100px !important; }
51 | .new_game .you_play .toggle {
52 | display: block;
53 | position: relative;
54 | float: right; }
55 | .new_game .you_play .toggle input[type="checkbox"] {
56 | background: white url(../i/black_white.png) 0 0 no-repeat !important; }
57 | .new_game .setup {
58 | padding-left: 80px !important; }
59 | .new_game .rules {
60 | padding-left: 80px !important; }
61 |
62 | .move .toolbar .button img {
63 | margin-top: 5px; }
64 |
65 | .progress .ui-dialog-titlebar {
66 | display: none; }
67 |
68 | .board .head .captured, .board .foot .captured {
69 | height: 30px;
70 | width: 30px;
71 | line-height: 30px;
72 | text-align: center; }
73 | .board .head .captured:empty, .board .foot .captured:empty {
74 | background-color: transparent; }
75 | .board .head .captured.black:not(:empty), .board .foot .captured.black:not(:empty) {
76 | color: white;
77 | background: url(../i/ghost-black.png); }
78 | .board .head .captured.white:not(:empty), .board .foot .captured.white:not(:empty) {
79 | color: black;
80 | background: url(../i/ghost-white.png); }
81 |
--------------------------------------------------------------------------------
/c/sass/application.sass:
--------------------------------------------------------------------------------
1 | $black: #000
2 | $white: #fff
3 | $lightgrey: #333
4 |
5 | .invisible
6 | :visibility hidden
7 |
8 | .slideback.in
9 | -webkit-animation-name: slideinfromleft
10 | .slideback.out
11 | -webkit-animation-name: slideouttoright
12 | .slideback.in.reverse
13 | -webkit-animation-name: slideouttoright
14 | .slideback.out.reverse
15 | -webkit-animation-name: slideinfromleft
16 |
17 | .in_progress:before
18 | content: url(../i/in_progress.gif)
19 |
20 | .profile
21 | .foot
22 | .toolbar
23 | -webkit-transform: rotate(180deg)
24 | -moz-transform: rotate(180deg)
25 |
26 | .landscape
27 | .foot
28 | .toolbar
29 | display: none
30 |
31 |
32 | $messagewidth: 200px
33 | $bubblefrom: #f3961c
34 | $bubbleto: #f9d835
35 |
36 | $separation_between_board_and_bubble: 10px
37 |
38 | .head.triangle-right
39 | left: 25%
40 | margin-left: -12.5%
41 | width: 25%
42 | margin-bottom: $separation_between_board_and_bubble
43 | z-index: 1
44 |
45 | .foot.triangle-right
46 | left: 75%
47 | margin-left: -12.5%
48 | width: 25%
49 | z-index: 1
50 | margin-top: $separation_between_board_and_bubble
51 |
52 | .new_game
53 | ul
54 | li
55 | :position relative !important
56 | .label
57 | :position absolute
58 | :left 10px
59 | .email
60 | :height 40px !important
61 | .size
62 | :padding-left 70px !important
63 | .you_play
64 | :padding-left 100px !important
65 | .toggle
66 | :display block
67 | :position relative
68 | :float right
69 | input[type="checkbox"]
70 | :background #fff url(../i/black_white.png) 0 0 no-repeat !important
71 | .setup
72 | :padding-left 80px !important
73 | .rules
74 | :padding-left 80px !important
75 |
76 | .move
77 | .toolbar
78 | .button
79 | img
80 | :margin
81 | :top 5px
82 |
83 | .progress
84 | .ui-dialog-titlebar
85 | :display none
86 |
87 | .board
88 | .head,.foot
89 | .captured
90 | height: 30px
91 | width: 30px
92 | line-height: 30px
93 | text-align: center
94 | &:empty
95 | background-color: transparent
96 | &.black:not(:empty)
97 | color: white
98 | background: url(../i/ghost-black.png)
99 | &.white:not(:empty)
100 | color: black
101 | background: url(../i/ghost-white.png)
--------------------------------------------------------------------------------
/j/load.images.js:
--------------------------------------------------------------------------------
1 | // (c) 2010 Reg Braithwaite. All rights to the entirety of the program and its parts are reserved with
2 | // the exception of specific files otherwise licensed. Other licenses apply only to the files where
3 | // they appear.
4 |
5 | ;(function ($, undefined) {
6 | $.each( [ '../i/board/temporary/tile1nw.png', '../i/board/temporary/tile1nwd.png', '../i/board/temporary/tile1nwd.png',
7 | '../i/board/temporary/tile2nw.png', '../i/board/temporary/tile2nwd.png', '../i/board/temporary/tile2nwd.png',
8 | '../i/board/temporary/tile0nw.png', '../i/board/temporary/tile1n.png', '../i/board/temporary/tile1nd.png',
9 | '../i/board/temporary/tile1nd.png', '../i/board/temporary/tile2n.png', '../i/board/temporary/tile2nd.png',
10 | '../i/board/temporary/tile2nd.png', '../i/board/temporary/tile0n.png', '../i/board/temporary/tile1ne.png',
11 | '../i/board/temporary/tile1ned.png', '../i/board/temporary/tile1ned.png', '../i/board/temporary/tile2ne.png',
12 | '../i/board/temporary/tile2ned.png', '../i/board/temporary/tile2ned.png', '../i/board/temporary/tile0ne.png',
13 | '../i/board/temporary/tile1w.png', '../i/board/temporary/tile1wd.png', '../i/board/temporary/tile1wd.png',
14 | '../i/board/temporary/tile2w.png', '../i/board/temporary/tile2wd.png', '../i/board/temporary/tile2wd.png',
15 | '../i/board/temporary/tile0w.png', '../i/board/temporary/tile1.png', '../i/board/temporary/tile1d.png',
16 | '../i/board/temporary/tile1d.png', '../i/board/temporary/tile2.png', '../i/board/temporary/tile2d.png',
17 | '../i/board/temporary/tile2d.png', '../i/board/temporary/tile1e.png', '../i/board/temporary/tile1ed.png',
18 | '../i/board/temporary/tile1ed.png', '../i/board/temporary/tile2e.png', '../i/board/temporary/tile2ed.png',
19 | '../i/board/temporary/tile2ed.png', '../i/board/temporary/tile0e.png', '../i/board/temporary/tile1sw.png',
20 | '../i/board/temporary/tile1swd.png', '../i/board/temporary/tile1swd.png', '../i/board/temporary/tile2sw.png',
21 | '../i/board/temporary/tile2swd.png', '../i/board/temporary/tile2swd.png', '../i/board/temporary/tile0sw.png',
22 | '../i/board/temporary/tile1s.png', '../i/board/temporary/tile1sd.png', '../i/board/temporary/tile1sd.png',
23 | '../i/board/temporary/tile2s.png', '../i/board/temporary/tile2sd.png', '../i/board/temporary/tile2sd.png',
24 | '../i/board/temporary/tile0s.png', '../i/board/temporary/tile1se.png', '../i/board/temporary/tile1sed.png',
25 | '../i/board/temporary/tile1sed.png', '../i/board/temporary/tile2se.png', '../i/board/temporary/tile2sed.png',
26 | '../i/board/temporary/tile2sed.png', '../i/board/temporary/tile0se.png', '../i/board/temporary/tile1.png',
27 | '../i/board/temporary/tile1d.png', '../i/board/temporary/tile1d.png', '../i/board/temporary/tile2.png',
28 | '../i/board/temporary/tile2d.png', '../i/board/temporary/tile2d.png', '../i/board/temporary/tile0c.png',
29 | '../i/board/temporary/tile0c.png', '../i/board/temporary/tile0c.png', '../i/board/temporary/tile0.png',
30 | '../i/board/temporary/tile0.png' ], function (path) {
31 | (new Image(30,30)).src = path;
32 | });
33 | })(jQuery);
--------------------------------------------------------------------------------
/cache.manifest:
--------------------------------------------------------------------------------
1 | CACHE MANIFEST
2 | # This is a comment.
3 | # Cache manifest version 5
4 | # If you change the version number in this comment,
5 | # the cache manifest is no longer byte-for-byte
6 | # identical.
7 | #
8 | # See: http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/OfflineApplicationCache/OfflineApplicationCache.html
9 |
10 | NETWORK:
11 |
12 | CACHE:
13 |
14 | # board images
15 |
16 | i/board/temporary/tile1nw.png
17 | i/board/temporary/tile1nwd.png
18 | i/board/temporary/tile1nwd.png
19 | i/board/temporary/tile2nw.png
20 | i/board/temporary/tile2nwd.png
21 | i/board/temporary/tile2nwd.png
22 | i/board/temporary/tile0nw.png
23 | i/board/temporary/tile1n.png
24 | i/board/temporary/tile1nd.png
25 | i/board/temporary/tile1nd.png
26 | i/board/temporary/tile2n.png
27 | i/board/temporary/tile2nd.png
28 | i/board/temporary/tile2nd.png
29 | i/board/temporary/tile0n.png
30 | i/board/temporary/tile1ne.png
31 | i/board/temporary/tile1ned.png
32 | i/board/temporary/tile1ned.png
33 | i/board/temporary/tile2ne.png
34 | i/board/temporary/tile2ned.png
35 | i/board/temporary/tile2ned.png
36 | i/board/temporary/tile0ne.png
37 | i/board/temporary/tile1w.png
38 | i/board/temporary/tile1wd.png
39 | i/board/temporary/tile1wd.png
40 | i/board/temporary/tile2w.png
41 | i/board/temporary/tile2wd.png
42 | i/board/temporary/tile2wd.png
43 | i/board/temporary/tile0w.png
44 | i/board/temporary/tile1.png
45 | i/board/temporary/tile1d.png
46 | i/board/temporary/tile1d.png
47 | i/board/temporary/tile2.png
48 | i/board/temporary/tile2d.png
49 | i/board/temporary/tile2d.png
50 | i/board/temporary/tile1e.png
51 | i/board/temporary/tile1ed.png
52 | i/board/temporary/tile1ed.png
53 | i/board/temporary/tile2e.png
54 | i/board/temporary/tile2ed.png
55 | i/board/temporary/tile2ed.png
56 | i/board/temporary/tile0e.png
57 | i/board/temporary/tile1sw.png
58 | i/board/temporary/tile1swd.png
59 | i/board/temporary/tile1swd.png
60 | i/board/temporary/tile2sw.png
61 | i/board/temporary/tile2swd.png
62 | i/board/temporary/tile2swd.png
63 | i/board/temporary/tile0sw.png
64 | i/board/temporary/tile1s.png
65 | i/board/temporary/tile1sd.png
66 | i/board/temporary/tile1sd.png
67 | i/board/temporary/tile2s.png
68 | i/board/temporary/tile2sd.png
69 | i/board/temporary/tile2sd.png
70 | i/board/temporary/tile0s.png
71 | i/board/temporary/tile1se.png
72 | i/board/temporary/tile1sed.png
73 | i/board/temporary/tile1sed.png
74 | i/board/temporary/tile2se.png
75 | i/board/temporary/tile2sed.png
76 | i/board/temporary/tile2sed.png
77 | i/board/temporary/tile0se.png
78 | i/board/temporary/tile1.png
79 | i/board/temporary/tile1d.png
80 | i/board/temporary/tile1d.png
81 | i/board/temporary/tile2.png
82 | i/board/temporary/tile2d.png
83 | i/board/temporary/tile2d.png
84 | i/board/temporary/tile0c.png
85 | i/board/temporary/tile0c.png
86 | i/board/temporary/tile0c.png
87 | i/board/temporary/tile0.png
88 | i/board/temporary/tile0.png
89 |
90 | # coming soon: other jQTouch images and themes
91 |
92 | i/ajax-loader-black.gif
93 | i/dot_clear.gif
94 | i/in_progress.gif
95 | i/simple-black.png
96 | i/simple-white.png
97 |
98 | i/themes/jqt/img/back_button.png
99 | i/themes/jqt/img/back_button_clicked.png
100 | i/themes/jqt/img/button.png
101 | i/themes/jqt/img/button_clicked.png
102 | i/themes/jqt/img/chevron.png
103 | i/themes/jqt/img/chevron_circle.png
104 | i/themes/jqt/img/grayButton.png
105 | i/themes/jqt/img/loading.gif
106 | i/themes/jqt/img/on_off.png
107 | i/themes/jqt/img/rowhead.png
108 | i/themes/jqt/img/toggle.png
109 | i/themes/jqt/img/toggleOn.png
110 | i/themes/jqt/img/toolbar.png
111 | i/themes/jqt/img/whiteButton.png
112 |
113 | # common JS
114 |
115 | j/jquery.1.4.2.js
116 | j/jquery.timers-1.2.js
117 | j/jqtouch.customized.js
118 | j/md5.js
119 | j/to-function.js
120 | j/functional.js
121 | j/igesture.jquery.mobile_safari.js
122 | j/jquery.combinators.js
123 | j/dragscrollable.js
124 |
125 | # common CSS
126 |
127 | c/jqtouch.css
128 | c/jqtouch.ipad.customized.css
--------------------------------------------------------------------------------
/j/jquery.timers-1.2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * jQuery.timers - Timer abstractions for jQuery
3 | * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
4 | * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
5 | * Date: 2009/10/16
6 | *
7 | * @author Blair Mitchelmore
8 | * @version 1.2
9 | *
10 | **/
11 |
12 | jQuery.fn.extend({
13 | everyTime: function(interval, label, fn, times) {
14 | return this.each(function() {
15 | jQuery.timer.add(this, interval, label, fn, times);
16 | });
17 | },
18 | oneTime: function(interval, label, fn) {
19 | return this.each(function() {
20 | jQuery.timer.add(this, interval, label, fn, 1);
21 | });
22 | },
23 | stopTime: function(label, fn) {
24 | return this.each(function() {
25 | jQuery.timer.remove(this, label, fn);
26 | });
27 | }
28 | });
29 |
30 | jQuery.extend({
31 | timer: {
32 | global: [],
33 | guid: 1,
34 | dataKey: "jQuery.timer",
35 | regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
36 | powers: {
37 | // Yeah this is major overkill...
38 | 'ms': 1,
39 | 'cs': 10,
40 | 'ds': 100,
41 | 's': 1000,
42 | 'das': 10000,
43 | 'hs': 100000,
44 | 'ks': 1000000
45 | },
46 | timeParse: function(value) {
47 | if (value == undefined || value == null)
48 | return null;
49 | var result = this.regex.exec(jQuery.trim(value.toString()));
50 | if (result[2]) {
51 | var num = parseFloat(result[1]);
52 | var mult = this.powers[result[2]] || 1;
53 | return num * mult;
54 | } else {
55 | return value;
56 | }
57 | },
58 | add: function(element, interval, label, fn, times) {
59 | var counter = 0;
60 |
61 | if (jQuery.isFunction(label)) {
62 | if (!times)
63 | times = fn;
64 | fn = label;
65 | label = interval;
66 | }
67 |
68 | interval = jQuery.timer.timeParse(interval);
69 |
70 | if (typeof interval != 'number' || isNaN(interval) || interval < 0)
71 | return;
72 |
73 | if (typeof times != 'number' || isNaN(times) || times < 0)
74 | times = 0;
75 |
76 | times = times || 0;
77 |
78 | var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});
79 |
80 | if (!timers[label])
81 | timers[label] = {};
82 |
83 | fn.timerID = fn.timerID || this.guid++;
84 |
85 | var handler = function() {
86 | if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
87 | jQuery.timer.remove(element, label, fn);
88 | };
89 |
90 | handler.timerID = fn.timerID;
91 |
92 | if (!timers[label][fn.timerID])
93 | timers[label][fn.timerID] = window.setInterval(handler,interval);
94 |
95 | this.global.push( element );
96 |
97 | },
98 | remove: function(element, label, fn) {
99 | var timers = jQuery.data(element, this.dataKey), ret;
100 |
101 | if ( timers ) {
102 |
103 | if (!label) {
104 | for ( label in timers )
105 | this.remove(element, label, fn);
106 | } else if ( timers[label] ) {
107 | if ( fn ) {
108 | if ( fn.timerID ) {
109 | window.clearInterval(timers[label][fn.timerID]);
110 | delete timers[label][fn.timerID];
111 | }
112 | } else {
113 | for ( var fn in timers[label] ) {
114 | window.clearInterval(timers[label][fn]);
115 | delete timers[label][fn];
116 | }
117 | }
118 |
119 | for ( ret in timers[label] ) break;
120 | if ( !ret ) {
121 | ret = null;
122 | delete timers[label];
123 | }
124 | }
125 |
126 | for ( ret in timers ) break;
127 | if ( !ret )
128 | jQuery.removeData(element, this.dataKey);
129 | }
130 | }
131 | }
132 | });
133 |
134 | jQuery(window).bind("unload", function() {
135 | jQuery.each(jQuery.timer.global, function(index, item) {
136 | jQuery.timer.remove(item);
137 | });
138 | });
--------------------------------------------------------------------------------
/j/history.js:
--------------------------------------------------------------------------------
1 | // (c) 2010 Reg Braithwaite. All rights to the entirety of the program and its parts are reserved with
2 | // the exception of specific files otherwise licensed. Other licenses apply only to the files where
3 | // they appear.
4 |
5 | ;(function ($, undefined) {
6 |
7 | var last_move_index = function () {
8 | return go.sgf.floor(go.sgf.current.length-1);
9 | };
10 |
11 | var this_history_index = function () {
12 | return $('.move.history.this .board')
13 | .data('index');
14 | }
15 |
16 | var forwards_in_history = function (event) {
17 |
18 | var this_page = $('.move.history.this');
19 | var that_page;
20 |
21 | var this_index = $('.move.history.this .board')
22 | .data('index');
23 | var that_index = go.sgf.ceiling(this_index + 1);
24 |
25 | var last_index = go.sgf.floor(go.sgf.current.length - 1);
26 |
27 | if (that_index == -1)
28 | return; // may be a fencepost error when dealing with the start position
29 | else if (that_index == last_index) {
30 | that_page = $('.move.play');
31 | }
32 | else {
33 | that_page = $('.move.history.that');
34 | $('.move.history.that .board')
35 | .empty()
36 | .append(
37 | $('.move.history.this .board')
38 | .children()
39 | .clone(false)
40 | )
41 | .data('index', that_index);
42 |
43 | go.sgf.doit($('.move.history.that .board'), go.sgf.current[that_index]);
44 |
45 | this_page
46 | .addClass('that')
47 | .removeClass('this');
48 | that_page
49 | .addClass('this')
50 | .removeClass('that')
51 | .find('.toolbar h1')
52 | .text("Move " + go.sgf.current[that_index]["MN"])
53 | .end();
54 | }
55 |
56 | jQT.swapPages(this_page, that_page, 'slide');
57 |
58 | };
59 |
60 | var backwards_in_history = function (event) {
61 |
62 | var this_page = $('.move.history.this');
63 | var that_page = $('.move.history.that');
64 |
65 | var this_index = $('.move.history.this .board')
66 | .data('index');
67 | if (this_index == -1) return;
68 | var that_index = go.sgf.floor(this_index - 1);
69 |
70 | $('.move.history.that .board')
71 | .empty()
72 | .append(
73 | $('.move.history.this .board')
74 | .children()
75 | .clone(false)
76 | )
77 | .data('index', that_index);
78 |
79 |
80 | go.sgf.undoit($('.move.history.that .board'), go.sgf.current[this_index], go.sgf.current[that_index]);
81 |
82 | this_page
83 | .addClass('that')
84 | .removeClass('this');
85 | that_page
86 | .addClass('this')
87 | .removeClass('that')
88 | .find('.toolbar h1')
89 | .text(that_index >= 0 ? ("Move " + go.sgf.current[that_index]["MN"]) : 'Initial Position')
90 | .end();
91 |
92 | jQT.swapPages(this_page, that_page, 'slide.backwards');
93 | };
94 |
95 | var enter_history = function() {
96 | $('.move.history.this .intersection.black')
97 | .removeClass('black');
98 | $('.move.history.this .intersection.white')
99 | .removeClass('white');
100 | $('.move.history.this .intersection.last')
101 | .removeClass('last');
102 | $.each(['black', 'white'], function (i, colour) {
103 | $('.move.history.this')
104 | .find(
105 | $.map($('.move.play .intersection.'+colour), '"#"+$(_).attr("id")'.lambda()).join(',')
106 | )
107 | .addClass(colour);
108 | });
109 | $('.move.history.this')
110 | .find('.board')
111 | .data('index', last_move_index())
112 | .end();
113 | if (last_move_index() >= 0) {
114 | jQT.swapPages($('.move.play'), $('.move.history.this'), '');
115 | backwards_in_history();
116 | }
117 | }
118 |
119 | var initialize_history_support = function() {
120 | $('.move.play .board.zoomout')
121 | .live('gesture_right', enter_history);
122 | $('.move.history.this .board.zoomout')
123 | .live('gesture_left', forwards_in_history)
124 | .live('gesture_right', backwards_in_history);
125 | };
126 |
127 | go.on_document_ready(initialize_history_support);
128 |
129 | })(jQuery);
--------------------------------------------------------------------------------
/j/start.js:
--------------------------------------------------------------------------------
1 | // (c) 2010 Reg Braithwaite. All rights to the entirety of the program and its parts are reserved with
2 | // the exception of specific files otherwise licensed. Other licenses apply only to the files where
3 | // they appear.
4 |
5 | ;(function ($, undefined) {
6 |
7 | var game_specific_options = function (event) {
8 | var game_setup = $.parseJSON($('form.new_game #rules').val());
9 | var setup_text = $('form.new_game #setup').val();
10 | $('form.new_game #setup')
11 | .empty();
12 | $.each(go.referee.rules.setups[game_setup.setups], function (index, setup) {
13 | $('')
14 | .text(setup.text)
15 | .attr('value', setup.text)
16 | .appendTo($('form.new_game #setup'));
17 | }
18 | );
19 | if ($('form.new_game #setup').has('option:text('+setup_text+')').size() > 0)
20 | $('form.new_game #setup')
21 | .val(setup_text);
22 | else if (setup_text)
23 | $('form.new_game #setup')
24 | .val($('form.new_game #setup option:first').text());
25 | $('form.new_game #dimension')
26 | .empty();
27 | $.each(game_setup.sizes, function (index, size) {
28 | $('')
29 | .text('' + size + 'x' + size)
30 | .attr('value', size)
31 | .appendTo($('form.new_game #dimension'));
32 | }
33 | );
34 | };
35 |
36 | var setup_new_game = function () {
37 | $('form.new_game .rules select')
38 | .each(game_specific_options)
39 | .blur(game_specific_options)
40 | .change(game_specific_options);
41 | $('form.new_game #start')
42 | .click(function () { $('form.new_game').submit(); return false; });
43 | $('form.new_game').submit(function (e) {
44 | go.sgf.game_info = {
45 | FF: 4,
46 | SZ: $('form.new_game #dimension').val(),
47 | AP: "World of Go",
48 | PH: $('form.new_game #black').val() || 'Black', // custom: 'player host'
49 | PG: $('form.new_game #white').val() || 'White', // custom: 'player guest'
50 | GR: $('form.new_game #rules option:selected').text(),
51 | GS: $('form.new_game #setup option:selected').text()
52 | };
53 | go.sgf.game_info.PB = go.sgf.game_info.PH; // TODO: restore picking black or white
54 | go.sgf.game_info.PW = go.sgf.game_info.PG;
55 | go.sgf.root = [go.sgf.game_info];
56 | go.sgf.current = go.sgf.root;
57 | go.letters = go.letters.slice(0, go.sgf.game_info.SZ);
58 | $('.move')
59 | .removeClass('black white')
60 | .find('.board')
61 | .removeClass('size9 size11 size13 size15 size17 size19')
62 | .addClass('size' + go.sgf.game_info.SZ)
63 | .find('.intersections')
64 | .empty();
65 | $.each(go.letters, function (down_index, down_letter) {
66 | $('
')
67 | .addClass('row')
68 | .K(function (row) {
69 | $.each(go.letters, function (across_index, across_letter) {
70 | $('
')
71 | .addClass('intersection playable_black playable_white')
72 | .attr('id', across_letter + down_letter)
73 | .attr('src', 'i/dot_clear.gif')
74 | .appendTo(row);
75 | });
76 | })
77 | .appendTo($('.move .board .intersections'));
78 | });
79 | var game_setup = $.parseJSON($('form.new_game #rules').val());
80 | go.sgf.game_info.GM = game_setup.GM;
81 | go.referee.set_rules(game_setup);
82 | var setup_text = $('form.new_game #setup').val();
83 | var setup;
84 | $.each(go.referee.rules.setups[game_setup.setups], function (i, each_setup) {
85 | if (each_setup.text == setup_text)
86 | setup = each_setup;
87 | });
88 | $.extend(go.sgf.game_info, setup.sgf);
89 | if (setup.setup) setup.setup();
90 | go.sgf.doit($('.move.play .board'), go.sgf.game_info);
91 | $('#info')
92 | .find('.players .black')
93 | .text(go.sgf.game_info.PB)
94 | .end()
95 | .find('.players .white')
96 | .text(go.sgf.game_info.PW)
97 | .end()
98 | .find('h1')
99 | .text(go.sgf.game_info.GR)
100 | .end()
101 | .find('.game .setup')
102 | .text(go.sgf.game_info.GS)
103 | .end();
104 | go.set_titles();
105 | jQT.swapPages($('#new'), $('.move.play'));
106 | return false;
107 | });
108 | };
109 |
110 | go.on_document_ready(setup_new_game);
111 |
112 | })(jQuery);
--------------------------------------------------------------------------------
/haml/index.html.haml:
--------------------------------------------------------------------------------
1 | // (c) 2010 Reg Braithwaite. All rights to the entirety of the program and its parts are reserved with
2 | // the exception of specific files otherwise licensed. Other licenses apply only to the files where
3 | // they appear.
4 |
5 | !!!Strict
6 | %html{html_attrs('en').merge(:manifest=>"cache.manifest")}
7 | %head
8 |
9 | %title World of Go
10 |
11 | %meta{:name=>"apple-mobile-web-app-status-bar-style", :content=>"black"}/
12 | %meta{:name=>"viewport", :content=>"user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"}/
13 |
14 | // their stuff
15 |
16 | %script{:src=>"j/jquery.1.4.2.js", :type=>"text/javascript", :charset=>"utf-8"}
17 | %script{:src=>"j/jquery.timers-1.2.js", :type=>"text/javascript", :charset=>"utf-8"}
18 | %script{:src=>"j/jqtouch.customized.js", :type=>"text/javascript", :charset=>"utf-8"}
19 |
20 | %script{:src=>"j/md5.js", :type=>"text/javascript", :charset=>"utf-8"}
21 |
22 | %script{:src=>"j/to-function.js", :type=>"text/javascript", :charset=>"utf-8"}
23 | %script{:src=>"j/functional.js", :type=>"text/javascript", :charset=>"utf-8"}
24 |
25 | // my open stuff
26 |
27 | %script{:src=>"j/igesture.jquery.mobile_safari.js", :type=>"text/javascript", :charset=>"utf-8"}
28 | %script{:src=>"j/jquery.combinators.js", :type=>"text/javascript", :charset=>"utf-8"}
29 | %script{:src=>"j/dragscrollable.js", :type=>"text/javascript", :charset=>"utf-8"}
30 |
31 | // my proprietary stuff
32 |
33 | %script{:src=>"j/go.js", :type=>"text/javascript", :charset=>"utf-8"}
34 | %script{:src=>"j/adjacency.js", :type=>"text/javascript", :charset=>"utf-8"}
35 | %script{:src=>"j/referee.js", :type=>"text/javascript", :charset=>"utf-8"}
36 | %script{:src=>"j/start.js", :type=>"text/javascript", :charset=>"utf-8"}
37 | %script{:src=>"j/ui.js", :type=>"text/javascript", :charset=>"utf-8"}
38 | %script{:src=>"j/history.js", :type=>"text/javascript", :charset=>"utf-8"}
39 |
40 | %style{:type=>"text/css", :media=>"screen"} @import "c/jqtouch.css";
41 | %style{:type=>"text/css", :media=>"screen"} @import "c/jqtouch.ipad.customized.css";
42 | %style{:type=>"text/css", :media=>"screen"} @import "c/application.css";
43 | %style{:type=>"text/css", :media=>"screen"} @import "c/board.ipad.css";
44 | %style{:type=>"text/css", :media=>"screen"} @import "c/bubbles.css";
45 |
46 | %style{:id=>'toolbar_titles'}
47 | %style{:id=>'bubbles'}
48 |
49 | :javascript
50 | // (c) 2010 Reg Braithwaite. All rights to the entirety of the program and its parts are reserved with
51 | // the exception of specific files otherwise licensed. Other licenses apply only to the files where
52 | // they appear.
53 | var jQT = new $.jQTouch({
54 | icon: 'i/black_white.png',
55 | statusBar: 'black-translucent',
56 | touchSelector: '.board .intersection, .board, .touch'
57 | });
58 | $(function(){
59 | jQT.addAnimation({
60 | name: 'slideback',
61 | selector: '.slideback'
62 | });
63 | });
64 | %body
65 |
66 | %div#useful_stuff
67 | .ajax_load
68 | %img{:src=>'i/ajax-loader-black.gif',:height=>66,:width=>66}
69 |
70 | #new.current
71 | .toolbar
72 | %h1 Start
73 | %form#form.new_game
74 | %ul.edit.rounded
75 | %li.email
76 | %input#black{:name=>'black', :placeholder=>"Black's name", :type=>'text'}/
77 | %li.email
78 | %input#white{:name=>'white', :placeholder=>"White's name", :type=>'text'}/
79 | %li.rules
80 | .label Game:
81 | %select#rules{:name=>'rules'}
82 | %li.size
83 | .label Size:
84 | %select#dimension{:name=>'dimension'}
85 | %li.setup
86 | .label Setup:
87 | %select#setup{:name=>'setup'}
88 | %a.whiteButton#start{:style=>"margin:0 10px;color:rgba(0,0,0,.9)", :href=>"#"} Play
89 |
90 | #info
91 | .toolbar
92 | %h1 Game Info
93 | %h2 Players
94 | %ul.rounded.players
95 | %li.black
96 | %li.white
97 | %h2 Setup
98 | %ul.rounded.game
99 | %li.setup
100 | %h2 Captures
101 | %ul.rounded
102 | %li
103 | Black has captured
104 | %span.captured_whites
105 | %li
106 | White has captured
107 | %span.captured_blacks
108 |
109 | .move.history.this
110 | .toolbar
111 | %h1
112 | %span.playing
113 | .board.zoomout.scrub
114 | .intersections
115 |
116 | .move.history.that
117 | .toolbar
118 | %h1
119 | .board.zoomout.scrub
120 | .intersections
121 |
122 | .move.play
123 | .head
124 | .toolbar
125 | %h1
126 | .board.zoomout.scrub.pass.play
127 | .head
128 | .guest.black.captured
129 | .intersections
130 | .foot
131 | .guest.black.captured
132 | .host.white.captured
133 | .foot
134 | .toolbar
135 | %h1
--------------------------------------------------------------------------------
/c/jqtouch.min.css:
--------------------------------------------------------------------------------
1 | *{margin:0;padding:0;}a{-webkit-tap-highlight-color:rgba(0,0,0,0);}body{overflow-x:hidden;-webkit-user-select:none;-webkit-text-size-adjust:none;font-family:Helvetica;-webkit-perspective:800;-webkit-transform-style:preserve-3d;}.selectable,input,textarea{-webkit-user-select:auto;}body>*{-webkit-backface-visibility:hidden;-webkit-box-sizing:border-box;display:none;position:absolute;left:0;width:100%;-webkit-transform:translate3d(0,0,0) rotate(0) scale(1);min-height:420px!important;}body.fullscreen>*{min-height:460px!important;}body.fullscreen.black-translucent>*{min-height:480px!important;}body.landscape>*{min-height:320px;}body>.current{display:block!important;}.in,.out{-webkit-animation-timing-function:ease-in-out;-webkit-animation-duration:350ms;}.slide.in{-webkit-animation-name:slideinfromright;}.slide.out{-webkit-animation-name:slideouttoleft;}.slide.in.reverse{-webkit-animation-name:slideinfromleft;}.slide.out.reverse{-webkit-animation-name:slideouttoright;}@-webkit-keyframes slideinfromright{from{-webkit-transform:translateX(100%);}to{-webkit-transform:translateX(0);}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translateX(-100%);}to{-webkit-transform:translateX(0);}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translateX(0);}to{-webkit-transform:translateX(-100%);}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translateX(0);}to{-webkit-transform:translateX(100%);}}@-webkit-keyframes fadein{from{opacity:0;}to{opacity:1;}}@-webkit-keyframes fadeout{from{opacity:1;}to{opacity:0;}}.fade.in{z-index:10;-webkit-animation-name:fadein;}.fade.out{z-index:0;}.dissolve.in{-webkit-animation-name:fadein;}.dissolve.out{-webkit-animation-name:fadeout;}.flip{-webkit-animation-duration:.65s;}.flip.in{-webkit-animation-name:flipinfromleft;}.flip.out{-webkit-animation-name:flipouttoleft;}.flip.in.reverse{-webkit-animation-name:flipinfromright;}.flip.out.reverse{-webkit-animation-name:flipouttoright;}@-webkit-keyframes flipinfromright{from{-webkit-transform:rotateY(-180deg) scale(.8);}to{-webkit-transform:rotateY(0) scale(1);}}@-webkit-keyframes flipinfromleft{from{-webkit-transform:rotateY(180deg) scale(.8);}to{-webkit-transform:rotateY(0) scale(1);}}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0) scale(1);}to{-webkit-transform:rotateY(-180deg) scale(.8);}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0) scale(1);}to{-webkit-transform:rotateY(180deg) scale(.8);}}.slideup.in{-webkit-animation-name:slideup;z-index:10;}.slideup.out{-webkit-animation-name:dontmove;z-index:0;}.slideup.out.reverse{z-index:10;-webkit-animation-name:slidedown;}.slideup.in.reverse{z-index:0;-webkit-animation-name:dontmove;}@-webkit-keyframes slideup{from{-webkit-transform:translateY(100%);}to{-webkit-transform:translateY(0);}}@-webkit-keyframes slidedown{from{-webkit-transform:translateY(0);}to{-webkit-transform:translateY(100%);}}@-webkit-keyframes dontmove{from{opacity:1;}to{opacity:1;}}.swap{-webkit-transform:perspective(800);-webkit-animation-duration:.7s;}.swap.out{-webkit-animation-name:swapouttoleft;}.swap.in{-webkit-animation-name:swapinfromright;}.swap.out.reverse{-webkit-animation-name:swapouttoright;}.swap.in.reverse{-webkit-animation-name:swapinfromleft;}@-webkit-keyframes swapouttoright{0%{-webkit-transform:translate3d(0px,0px,0px) rotateY(0deg);-webkit-animation-timing-function:ease-in-out;}50%{-webkit-transform:translate3d(-180px,0px,-400px) rotateY(20deg);-webkit-animation-timing-function:ease-in;}100%{-webkit-transform:translate3d(0px,0px,-800px) rotateY(70deg);}}@-webkit-keyframes swapouttoleft{0%{-webkit-transform:translate3d(0px,0px,0px) rotateY(0deg);-webkit-animation-timing-function:ease-in-out;}50%{-webkit-transform:translate3d(180px,0px,-400px) rotateY(-20deg);-webkit-animation-timing-function:ease-in;}100%{-webkit-transform:translate3d(0px,0px,-800px) rotateY(-70deg);}}@-webkit-keyframes swapinfromright{0%{-webkit-transform:translate3d(0px,0px,-800px) rotateY(70deg);-webkit-animation-timing-function:ease-out;}50%{-webkit-transform:translate3d(-180px,0px,-400px) rotateY(20deg);-webkit-animation-timing-function:ease-in-out;}100%{-webkit-transform:translate3d(0px,0px,0px) rotateY(0deg);}}@-webkit-keyframes swapinfromleft{0%{-webkit-transform:translate3d(0px,0px,-800px) rotateY(-70deg);-webkit-animation-timing-function:ease-out;}50%{-webkit-transform:translate3d(180px,0px,-400px) rotateY(-20deg);-webkit-animation-timing-function:ease-in-out;}100%{-webkit-transform:translate3d(0px,0px,0px) rotateY(0deg);}}.cube{-webkit-animation-duration:.55s;}.cube.in{-webkit-animation-name:cubeinfromright;-webkit-transform-origin:0 50%;}.cube.out{-webkit-animation-name:cubeouttoleft;-webkit-transform-origin:100% 50%;}.cube.in.reverse{-webkit-animation-name:cubeinfromleft;-webkit-transform-origin:100% 50%;}.cube.out.reverse{-webkit-animation-name:cubeouttoright;-webkit-transform-origin:0 50%;}@-webkit-keyframes cubeinfromleft{from{-webkit-transform:rotateY(-90deg) translateZ(320px);opacity:.5;}to{-webkit-transform:rotateY(0deg) translateZ(0);opacity:1;}}@-webkit-keyframes cubeouttoright{from{-webkit-transform:rotateY(0deg) translateX(0);opacity:1;}to{-webkit-transform:rotateY(90deg) translateZ(320px);opacity:.5;}}@-webkit-keyframes cubeinfromright{from{-webkit-transform:rotateY(90deg) translateZ(320px);opacity:.5;}to{-webkit-transform:rotateY(0deg) translateZ(0);opacity:1;}}@-webkit-keyframes cubeouttoleft{from{-webkit-transform:rotateY(0deg) translateZ(0);opacity:1;}to{-webkit-transform:rotateY(-90deg) translateZ(320px);opacity:.5;}}.pop{-webkit-transform-origin:50% 50%;}.pop.in{-webkit-animation-name:popin;z-index:10;}.pop.out.reverse{-webkit-animation-name:popout;z-index:10;}.pop.in.reverse{z-index:0;-webkit-animation-name:dontmove;}@-webkit-keyframes popin{from{-webkit-transform:scale(.2);opacity:0;}to{-webkit-transform:scale(1);opacity:1;}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1;}to{-webkit-transform:scale(.2);opacity:0;}}
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | World of Go
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
53 |
54 |
55 |
56 |
57 |

58 |
59 |
60 |
61 |
62 |
Start
63 |
64 |
87 |
88 |
89 |
90 |
Game Info
91 |
92 |
Players
93 |
97 |
Setup
98 |
101 |
Captures
102 |
103 | -
104 | Black has captured
105 |
106 |
107 | -
108 | White has captured
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
122 |
123 |
124 |
125 |
126 |
127 |
130 |
131 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/j/dragscrollable.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery dragscrollable Plugin
3 | * version: 1.0 (25-Jun-2009)
4 | * Copyright (c) 2009 Miquel Herrera
5 | *
6 | * Portions Copyright (c) 2010 Reg Braithwaite
7 | *
8 | * Dual licensed under the MIT and GPL licenses:
9 | * http://www.opensource.org/licenses/mit-license.php
10 | * http://www.gnu.org/licenses/gpl.html
11 | *
12 | */
13 | ;(function($){ // secure $ jQuery alias
14 |
15 | /**
16 | * Adds the ability to manage elements scroll by dragging
17 | * one or more of its descendant elements. Options parameter
18 | * allow to specifically select which inner elements will
19 | * respond to the drag events.
20 | *
21 | * options properties:
22 | * ------------------------------------------------------------------------
23 | * dragSelector | jquery selector to apply to each wrapped element
24 | * | to find which will be the dragging elements.
25 | * | Defaults to '>:first' which is the first child of
26 | * | scrollable element
27 | * ------------------------------------------------------------------------
28 | * acceptPropagatedEvent| Will the dragging element accept propagated
29 | * | events? default is yes, a propagated mouse event
30 | * | on a inner element will be accepted and processed.
31 | * | If set to false, only events originated on the
32 | * | draggable elements will be processed.
33 | * ------------------------------------------------------------------------
34 | * preventDefault | Prevents the event to propagate further effectivey
35 | * | dissabling other default actions. Defaults to true
36 | * ------------------------------------------------------------------------
37 | *
38 | * usage examples:
39 | *
40 | * To add the scroll by drag to the element id=viewport when dragging its
41 | * first child accepting any propagated events
42 | * $('#viewport').dragscrollable();
43 | *
44 | * To add the scroll by drag ability to any element div of class viewport
45 | * when dragging its first descendant of class dragMe responding only to
46 | * evcents originated on the '.dragMe' elements.
47 | * $('div.viewport').dragscrollable({dragSelector:'.dragMe:first',
48 | * acceptPropagatedEvent: false});
49 | *
50 | * Notice that some 'viewports' could be nested within others but events
51 | * would not interfere as acceptPropagatedEvent is set to false.
52 | *
53 | */
54 |
55 | var append_namespace = function (string_of_events, ns) {
56 | return string_of_events
57 | .split(' ')
58 | .map(function (name) { return name + ns; })
59 | .join(' ');
60 | };
61 |
62 | var left_top = function(event) {
63 |
64 | var x;
65 | var y;
66 | if (typeof(event.clientX) != 'undefined') {
67 | x = event.clientX;
68 | y = event.clientY;
69 | }
70 | else if (typeof(event.screenX) != 'undefined') {
71 | x = event.screenX;
72 | y = event.screenY;
73 | }
74 | else if (typeof(event.targetTouches) != 'undefined') {
75 | x = event.targetTouches[0].pageX;
76 | y = event.targetTouches[0].pageY;
77 | }
78 | else if (typeof(event.originalEvent) == 'undefined') {
79 | var str = '';
80 | for (i in event) {
81 | str += ', ' + i + ': ' + event[i];
82 | }
83 | console.error("don't understand x and y for " + event.type + ' event: ' + str);
84 | }
85 | else if (typeof(event.originalEvent.clientX) != 'undefined') {
86 | x = event.originalEvent.clientX;
87 | y = event.originalEvent.clientY;
88 | }
89 | else if (typeof(event.originalEvent.screenX) != 'undefined') {
90 | x = event.originalEvent.screenX;
91 | y = event.originalEvent.screenY;
92 | }
93 | else if (typeof(event.originalEvent.targetTouches) != 'undefined') {
94 | x = event.originalEvent.targetTouches[0].pageX;
95 | y = event.originalEvent.targetTouches[0].pageY;
96 | }
97 |
98 | return {left: x, top:y};
99 | };
100 |
101 | $.fn.dragscrollable = function( options ) {
102 |
103 | var handling_element = $(this);
104 |
105 | var settings = $.extend(
106 | {
107 | dragSelector:'>:first',
108 | acceptPropagatedEvent: true,
109 | preventDefault: true,
110 | dragstart: 'mousedown touchstart',
111 | dragcontinue: 'mousemove touchmove',
112 | dragend: 'mouseup touchend',
113 | namespace: '.ds'
114 | },options || {});
115 |
116 | settings.dragstart = append_namespace(settings.dragstart, settings.namespace);
117 | settings.dragcontinue = append_namespace(settings.dragcontinue, settings.namespace);
118 | settings.dragend = append_namespace(settings.dragend, settings.namespace);
119 |
120 | var dragscroll= {
121 | dragStartHandler : function(event) {
122 |
123 | // mousedown, left click, check propagation
124 | if (event.which > 1 ||
125 | (!event.data.acceptPropagatedEvent && event.target != this)){
126 | return false;
127 | }
128 |
129 | // Initial coordinates will be the last when dragging
130 | event.data.lastCoord = left_top(event);
131 |
132 | handling_element
133 | .bind(settings.dragcontinue, event.data, dragscroll.dragContinueHandler)
134 | .bind(settings.dragend, event.data, dragscroll.dragEndHandler);
135 |
136 | if (event.data.preventDefault) {
137 | event.preventDefault();
138 | return false;
139 | }
140 | },
141 | dragContinueHandler : function(event) { // User is dragging
142 |
143 | var lt = left_top(event);
144 |
145 | // How much did the mouse move?
146 | var delta = {left: (lt.left - event.data.lastCoord.left),
147 | top: (lt.top - event.data.lastCoord.top)};
148 |
149 | // Set the scroll position relative to what ever the scroll is now
150 | event.data.scrollable.scrollLeft(
151 | event.data.scrollable.scrollLeft() - delta.left);
152 | event.data.scrollable.scrollTop(
153 | event.data.scrollable.scrollTop() - delta.top);
154 |
155 | // Save where the cursor is
156 | event.data.lastCoord = lt;
157 |
158 | if (event.data.preventDefault) {
159 | event.preventDefault();
160 | return false;
161 | }
162 |
163 | },
164 | dragEndHandler : function(event) { // Stop scrolling
165 | handling_element
166 | .unbind(settings.dragcontinue)
167 | .unbind(settings.dragend);
168 | if (event.data.preventDefault) {
169 | event.preventDefault();
170 | return false;
171 | }
172 | }
173 | }
174 |
175 | // set up the initial events
176 | return this.each(function() {
177 | // closure object data for each scrollable element
178 | var data = {scrollable : $(this),
179 | acceptPropagatedEvent : settings.acceptPropagatedEvent,
180 | preventDefault : settings.preventDefault }
181 | // Set mouse initiating event on the desired descendant
182 | $(this).find(settings.dragSelector).
183 | bind(settings.dragstart, data, dragscroll.dragStartHandler);
184 | });
185 | }; //end plugin dragscrollable
186 |
187 | $.fn.removedragscrollable = function (namespace) {
188 | if (typeof(namespace) == 'undefined')
189 | namespace = '.ds';
190 | return this.each(function() {
191 | var x = $(document).find('*').andSelf().unbind(namespace);
192 | });
193 | };
194 |
195 | })( jQuery ); // confine scope
196 |
--------------------------------------------------------------------------------
/j/to-function.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Author: Oliver Steele
3 | * Copyright: Copyright 2007 by Oliver Steele. All rights reserved.
4 | * License: MIT License
5 | * Homepage: http://osteele.com/javascripts/functional
6 | * Created: 2007-07-11
7 | * Version: 1.0.2
8 | *
9 | *
10 | * This defines "string lambdas", that allow strings such as `x+1` and
11 | * `x -> x+1` to be used in some contexts as functions.
12 | */
13 |
14 |
15 | /// ^ String lambdas
16 |
17 | /**
18 | * Turns a string that contains a JavaScript expression into a
19 | * `Function` that returns the value of that expression.
20 | *
21 | * If the string contains a `->`, this separates the parameters from the body:
22 | * >> 'x -> x + 1'.lambda()(1) -> 2
23 | * >> 'x y -> x + 2*y'.lambda()(1, 2) -> 5
24 | * >> 'x, y -> x + 2*y'.lambda()(1, 2) -> 5
25 | *
26 | * Otherwise, if the string contains a `_`, this is the parameter:
27 | * >> '_ + 1'.lambda()(1) -> 2
28 | *
29 | * Otherwise if the string begins or ends with an operator or relation,
30 | * prepend or append a parameter. (The documentation refers to this type
31 | * of string as a "section".)
32 | * >> '/2'.lambda()(4) -> 2
33 | * >> '2/'.lambda()(4) -> 0.5
34 | * >> '/'.lambda()(2,4) -> 0.5
35 | * Sections can end, but not begin with, `-`. (This is to avoid interpreting
36 | * e.g. `-2*x` as a section). On the other hand, a string that either begins
37 | * or ends with `/` is a section, so an expression that begins or ends with a
38 | * regular expression literal needs an explicit parameter.
39 | *
40 | * Otherwise, each variable name is an implicit parameter:
41 | * >> 'x + 1'.lambda()(1) -> 2
42 | * >> 'x + 2*y'.lambda()(1, 2) -> 5
43 | * >> 'y + 2*x'.lambda()(1, 2) -> 5
44 | *
45 | * Implicit parameter detection ignores strings literals, variable names that
46 | * start with capitals, and identifiers that precede `:` or follow `.`:
47 | * >> map('"im"+root', ["probable", "possible"]) -> ["improbable", "impossible"]
48 | * >> 'Math.cos(angle)'.lambda()(Math.PI) -> -1
49 | * >> 'point.x'.lambda()({x:1, y:2}) -> 1
50 | * >> '({x:1, y:2})[key]'.lambda()('x') -> 1
51 | *
52 | * Implicit parameter detection mistakenly looks inside regular expression
53 | * literals for variable names. It also doesn't know to ignore JavaScript
54 | * keywords and bound variables. (The only way you can get these last two is
55 | * with a function literal inside the string. This is outside the intended use
56 | * case for string lambdas.)
57 | *
58 | * Use `_` (to define a unary function) or `->`, if the string contains anything
59 | * that looks like a free variable but shouldn't be used as a parameter, or
60 | * to specify parameters that are ordered differently from their first
61 | * occurrence in the string.
62 | *
63 | * Chain `->`s to create a function in uncurried form:
64 | * >> 'x -> y -> x + 2*y'.lambda()(1)(2) -> 5
65 | * >> 'x -> y -> z -> x + 2*y+3*z'.lambda()(1)(2)(3) -> 14
66 | *
67 | * `this` and `arguments` are special:
68 | * >> 'this'.call(1) -> 1
69 | * >> '[].slice.call(arguments, 0)'.call(null,1,2) -> [1, 2]
70 | */
71 | String.prototype.lambda = function() {
72 | var params = [],
73 | expr = this,
74 | sections = expr.ECMAsplit(/\s*->\s*/m);
75 | if (sections.length > 1) {
76 | while (sections.length) {
77 | expr = sections.pop();
78 | params = sections.pop().split(/\s*,\s*|\s+/m);
79 | sections.length && sections.push('(function('+params+'){return ('+expr+')})');
80 | }
81 | } else if (expr.match(/\b_\b/)) {
82 | params = '_';
83 | } else {
84 | // test whether an operator appears on the left (or right), respectively
85 | var leftSection = expr.match(/^\s*(?:[+*\/%&|\^\.=<>]|!=)/m),
86 | rightSection = expr.match(/[+\-*\/%&|\^\.=<>!]\s*$/m);
87 | if (leftSection || rightSection) {
88 | if (leftSection) {
89 | params.push('$1');
90 | expr = '$1' + expr;
91 | }
92 | if (rightSection) {
93 | params.push('$2');
94 | expr = expr + '$2';
95 | }
96 | } else {
97 | // `replace` removes symbols that are capitalized, follow '.',
98 | // precede ':', are 'this' or 'arguments'; and also the insides of
99 | // strings (by a crude test). `match` extracts the remaining
100 | // symbols.
101 | var vars = this.replace(/(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_$\d]*\s*:|this|arguments|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g, '').match(/([a-z_$][a-z_$\d]*)/gi) || []; // '
102 | for (var i = 0, v; v = vars[i++]; )
103 | params.indexOf(v) >= 0 || params.push(v);
104 | }
105 | }
106 | return new Function(params, 'return (' + expr + ')');
107 | }
108 |
109 | /// Turn on caching for `string` -> `Function` conversion.
110 | String.prototype.lambda.cache = function() {
111 | var proto = String.prototype,
112 | cache = {},
113 | uncached = proto.lambda,
114 | cached = function() {
115 | var key = '#' + this; // avoid hidden properties on Object.prototype
116 | return cache[key] || (cache[key] = uncached.call(this));
117 | };
118 | cached.cached = function(){};
119 | cached.uncache = function(){proto.lambda = uncached};
120 | proto.lambda = cached;
121 | }
122 |
123 | /**
124 | * ^^ Duck-Typing
125 | *
126 | * Strings support `call` and `apply`. This duck-types them as
127 | * functions, to some callers.
128 | */
129 |
130 | /**
131 | * Coerce the string to a function and then apply it.
132 | * >> 'x+1'.apply(null, [2]) -> 3
133 | * >> '/'.apply(null, [2, 4]) -> 0.5
134 | */
135 | String.prototype.apply = function(thisArg, args) {
136 | return this.toFunction().apply(thisArg, args);
137 | }
138 |
139 | /**
140 | * Coerce the string to a function and then call it.
141 | * >> 'x+1'.call(null, 2) -> 3
142 | * >> '/'.call(null, 2, 4) -> 0.5
143 | */
144 | String.prototype.call = function() {
145 | return this.toFunction().apply(arguments[0],
146 | Array.prototype.slice.call(arguments, 1));
147 | }
148 |
149 | /// ^^ Coercion
150 |
151 | /**
152 | * Returns a `Function` that perfoms the action described by this
153 | * string. If the string contains a `return`, applies
154 | * `new Function` to it. Otherwise, this function returns
155 | * the result of `this.lambda()`.
156 | * >> '+1'.toFunction()(2) -> 3
157 | * >> 'return 1'.toFunction()(1) -> 1
158 | */
159 | String.prototype.toFunction = function() {
160 | var body = this;
161 | if (body.match(/\breturn\b/))
162 | return new Function(this);
163 | return this.lambda();
164 | }
165 |
166 | /**
167 | * Returns this function. `Function.toFunction` calls this.
168 | * >> '+1'.lambda().toFunction()(2) -> 3
169 | */
170 | Function.prototype.toFunction = function() {
171 | return this;
172 | }
173 |
174 | /**
175 | * Coerces `fn` into a function if it is not already one,
176 | * by calling its `toFunction` method.
177 | * >> Function.toFunction(function() {return 1})() -> 1
178 | * >> Function.toFunction('+1')(2) -> 3
179 | *
180 | * `Function.toFunction` requires an argument that can be
181 | * coerced to a function. A nullary version can be
182 | * constructed via `guard`:
183 | * >> Function.toFunction.guard()('1+') -> function()
184 | * >> Function.toFunction.guard()(null) -> null
185 | *
186 | * `Function.toFunction` doesn't coerce arbitrary values to functions.
187 | * It might seem convenient to treat
188 | * `Function.toFunction(value)` as though it were the
189 | * constant function that returned `value`, but it's rarely
190 | * useful and it hides errors. Use `Functional.K(value)` instead,
191 | * or a lambda string when the value is a compile-time literal:
192 | * >> Functional.K('a string')() -> "a string"
193 | * >> Function.toFunction('"a string"')() -> "a string"
194 | */
195 | Function.toFunction = function(value) {
196 | return value.toFunction();
197 | }
198 |
199 | // Utilities
200 |
201 | // IE6 split is not ECMAScript-compliant. This breaks '->1'.lambda().
202 | // ECMAsplit is an ECMAScript-compliant `split`, although only for
203 | // one argument.
204 | String.prototype.ECMAsplit =
205 | // The test is from the ECMAScript reference.
206 | ('ab'.split(/a*/).length > 1
207 | ? String.prototype.split
208 | : function(separator, limit) {
209 | if (typeof limit != 'undefined')
210 | throw "ECMAsplit: limit is unimplemented";
211 | var result = this.split.apply(this, arguments),
212 | re = RegExp(separator),
213 | savedIndex = re.lastIndex,
214 | match = re.exec(this);
215 | if (match && match.index == 0)
216 | result.unshift('');
217 | // in case `separator` was already a RegExp:
218 | re.lastIndex = savedIndex;
219 | return result;
220 | });
--------------------------------------------------------------------------------
/c/jqtouch.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 | a {
6 | -webkit-tap-highlight-color: rgba(0,0,0,0);
7 | }
8 |
9 | body {
10 | overflow-x: hidden;
11 | -webkit-user-select: none;
12 | -webkit-text-size-adjust: none;
13 | font-family: Helvetica;
14 | -webkit-perspective: 800;
15 | -webkit-transform-style: preserve-3d;
16 | }
17 | .selectable, input, textarea {
18 | -webkit-user-select: auto;
19 | }
20 | body > * {
21 | -webkit-backface-visibility: hidden;
22 | -webkit-box-sizing: border-box;
23 | display: none;
24 | position: absolute;
25 | left: 0;
26 | width: 100%;
27 | -webkit-transform: translate3d(0,0,0) rotate(0) scale(1);
28 | min-height: 420px !important;
29 | }
30 | body.fullscreen > * {
31 | min-height: 460px !important;
32 | }
33 | body.fullscreen.black-translucent > * {
34 | min-height: 480px !important;
35 | }
36 | body.landscape > * {
37 | min-height: 320px;
38 | }
39 | body > .current {
40 | display: block !important;
41 | }
42 |
43 | .in, .out {
44 | -webkit-animation-timing-function: ease-in-out;
45 | -webkit-animation-duration: 350ms;
46 | }
47 |
48 | .slide.in {
49 | -webkit-animation-name: slideinfromright;
50 | }
51 |
52 | .slide.out {
53 | -webkit-animation-name: slideouttoleft;
54 | }
55 |
56 | .slide.in.reverse {
57 | -webkit-animation-name: slideinfromleft;
58 | }
59 |
60 | .slide.out.reverse {
61 | -webkit-animation-name: slideouttoright;
62 | }
63 |
64 | @-webkit-keyframes slideinfromright {
65 | from { -webkit-transform: translateX(100%); }
66 | to { -webkit-transform: translateX(0); }
67 | }
68 |
69 | @-webkit-keyframes slideinfromleft {
70 | from { -webkit-transform: translateX(-100%); }
71 | to { -webkit-transform: translateX(0); }
72 | }
73 |
74 | @-webkit-keyframes slideouttoleft {
75 | from { -webkit-transform: translateX(0); }
76 | to { -webkit-transform: translateX(-100%); }
77 | }
78 |
79 | @-webkit-keyframes slideouttoright {
80 | from { -webkit-transform: translateX(0); }
81 | to { -webkit-transform: translateX(100%); }
82 | }
83 |
84 | @-webkit-keyframes fadein {
85 | from { opacity: 0; }
86 | to { opacity: 1; }
87 | }
88 |
89 | @-webkit-keyframes fadeout {
90 | from { opacity: 1; }
91 | to { opacity: 0; }
92 | }
93 |
94 | .fade.in {
95 | z-index: 10;
96 | -webkit-animation-name: fadein;
97 | }
98 | .fade.out {
99 | z-index: 0;
100 | }
101 |
102 | .dissolve.in {
103 | -webkit-animation-name: fadein;
104 | }
105 |
106 | .dissolve.out {
107 | -webkit-animation-name: fadeout;
108 | }
109 |
110 |
111 |
112 | .flip {
113 | -webkit-animation-duration: .65s;
114 | }
115 |
116 | .flip.in {
117 | -webkit-animation-name: flipinfromleft;
118 | }
119 |
120 | .flip.out {
121 | -webkit-animation-name: flipouttoleft;
122 | }
123 |
124 | /* Shake it all about */
125 |
126 | .flip.in.reverse {
127 | -webkit-animation-name: flipinfromright;
128 | }
129 |
130 | .flip.out.reverse {
131 | -webkit-animation-name: flipouttoright;
132 | }
133 |
134 | @-webkit-keyframes flipinfromright {
135 | from { -webkit-transform: rotateY(-180deg) scale(.8); }
136 | to { -webkit-transform: rotateY(0) scale(1); }
137 | }
138 |
139 | @-webkit-keyframes flipinfromleft {
140 | from { -webkit-transform: rotateY(180deg) scale(.8); }
141 | to { -webkit-transform: rotateY(0) scale(1); }
142 | }
143 |
144 | @-webkit-keyframes flipouttoleft {
145 | from { -webkit-transform: rotateY(0) scale(1); }
146 | to { -webkit-transform: rotateY(-180deg) scale(.8); }
147 | }
148 |
149 | @-webkit-keyframes flipouttoright {
150 | from { -webkit-transform: rotateY(0) scale(1); }
151 | to { -webkit-transform: rotateY(180deg) scale(.8); }
152 | }
153 |
154 | .slideup.in {
155 | -webkit-animation-name: slideup;
156 | z-index: 10;
157 | }
158 |
159 | .slideup.out {
160 | -webkit-animation-name: dontmove;
161 | z-index: 0;
162 | }
163 |
164 | .slideup.out.reverse {
165 | z-index: 10;
166 | -webkit-animation-name: slidedown;
167 | }
168 |
169 | .slideup.in.reverse {
170 | z-index: 0;
171 | -webkit-animation-name: dontmove;
172 | }
173 |
174 |
175 | @-webkit-keyframes slideup {
176 | from { -webkit-transform: translateY(100%); }
177 | to { -webkit-transform: translateY(0); }
178 | }
179 |
180 | @-webkit-keyframes slidedown {
181 | from { -webkit-transform: translateY(0); }
182 | to { -webkit-transform: translateY(100%); }
183 | }
184 |
185 |
186 |
187 | /* Hackish, but reliable. */
188 |
189 | @-webkit-keyframes dontmove {
190 | from { opacity: 1; }
191 | to { opacity: 1; }
192 | }
193 |
194 | .swap {
195 | -webkit-transform: perspective(800);
196 | -webkit-animation-duration: .7s;
197 | }
198 | .swap.out {
199 | -webkit-animation-name: swapouttoleft;
200 | }
201 | .swap.in {
202 | -webkit-animation-name: swapinfromright;
203 | }
204 | .swap.out.reverse {
205 | -webkit-animation-name: swapouttoright;
206 | }
207 | .swap.in.reverse {
208 | -webkit-animation-name: swapinfromleft;
209 | }
210 |
211 |
212 | @-webkit-keyframes swapouttoright {
213 | 0% {
214 | -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
215 | -webkit-animation-timing-function: ease-in-out;
216 | }
217 | 50% {
218 | -webkit-transform: translate3d(-180px, 0px, -400px) rotateY(20deg);
219 | -webkit-animation-timing-function: ease-in;
220 | }
221 | 100% {
222 | -webkit-transform: translate3d(0px, 0px, -800px) rotateY(70deg);
223 | }
224 | }
225 |
226 | @-webkit-keyframes swapouttoleft {
227 | 0% {
228 | -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
229 | -webkit-animation-timing-function: ease-in-out;
230 | }
231 | 50% {
232 | -webkit-transform: translate3d(180px, 0px, -400px) rotateY(-20deg);
233 | -webkit-animation-timing-function: ease-in;
234 | }
235 | 100% {
236 | -webkit-transform: translate3d(0px, 0px, -800px) rotateY(-70deg);
237 | }
238 | }
239 |
240 | @-webkit-keyframes swapinfromright {
241 | 0% {
242 | -webkit-transform: translate3d(0px, 0px, -800px) rotateY(70deg);
243 | -webkit-animation-timing-function: ease-out;
244 | }
245 | 50% {
246 | -webkit-transform: translate3d(-180px, 0px, -400px) rotateY(20deg);
247 | -webkit-animation-timing-function: ease-in-out;
248 | }
249 | 100% {
250 | -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
251 | }
252 | }
253 |
254 | @-webkit-keyframes swapinfromleft {
255 | 0% {
256 | -webkit-transform: translate3d(0px, 0px, -800px) rotateY(-70deg);
257 | -webkit-animation-timing-function: ease-out;
258 | }
259 | 50% {
260 | -webkit-transform: translate3d(180px, 0px, -400px) rotateY(-20deg);
261 | -webkit-animation-timing-function: ease-in-out;
262 | }
263 | 100% {
264 | -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
265 | }
266 | }
267 |
268 | .cube {
269 | -webkit-animation-duration: .55s;
270 | }
271 |
272 | .cube.in {
273 | -webkit-animation-name: cubeinfromright;
274 | -webkit-transform-origin: 0% 50%;
275 | }
276 | .cube.out {
277 | -webkit-animation-name: cubeouttoleft;
278 | -webkit-transform-origin: 100% 50%;
279 | }
280 | .cube.in.reverse {
281 | -webkit-animation-name: cubeinfromleft;
282 | -webkit-transform-origin: 100% 50%;
283 | }
284 | .cube.out.reverse {
285 | -webkit-animation-name: cubeouttoright;
286 | -webkit-transform-origin: 0% 50%;
287 |
288 | }
289 |
290 | @-webkit-keyframes cubeinfromleft {
291 | from {
292 | -webkit-transform: rotateY(-90deg) translateZ(320px);
293 | opacity: .5;
294 | }
295 | to {
296 | -webkit-transform: rotateY(0deg) translateZ(0);
297 | opacity: 1;
298 | }
299 | }
300 | @-webkit-keyframes cubeouttoright {
301 | from {
302 | -webkit-transform: rotateY(0deg) translateX(0);
303 | opacity: 1;
304 | }
305 | to {
306 | -webkit-transform: rotateY(90deg) translateZ(320px);
307 | opacity: .5;
308 | }
309 | }
310 | @-webkit-keyframes cubeinfromright {
311 | from {
312 | -webkit-transform: rotateY(90deg) translateZ(320px);
313 | opacity: .5;
314 | }
315 | to {
316 | -webkit-transform: rotateY(0deg) translateZ(0);
317 | opacity: 1;
318 | }
319 | }
320 | @-webkit-keyframes cubeouttoleft {
321 | from {
322 | -webkit-transform: rotateY(0deg) translateZ(0);
323 | opacity: 1;
324 | }
325 | to {
326 | -webkit-transform: rotateY(-90deg) translateZ(320px);
327 | opacity: .5;
328 | }
329 | }
330 |
331 |
332 |
333 |
334 | .pop {
335 | -webkit-transform-origin: 50% 50%;
336 | }
337 |
338 | .pop.in {
339 | -webkit-animation-name: popin;
340 | z-index: 10;
341 | }
342 |
343 | .pop.out.reverse {
344 | -webkit-animation-name: popout;
345 | z-index: 10;
346 | }
347 |
348 | .pop.in.reverse {
349 | z-index: 0;
350 | -webkit-animation-name: dontmove;
351 | }
352 |
353 | @-webkit-keyframes popin {
354 | from {
355 | -webkit-transform: scale(.2);
356 | opacity: 0;
357 | }
358 | to {
359 | -webkit-transform: scale(1);
360 | opacity: 1;
361 | }
362 | }
363 |
364 | @-webkit-keyframes popout {
365 | from {
366 | -webkit-transform: scale(1);
367 | opacity: 1;
368 | }
369 | to {
370 | -webkit-transform: scale(.2);
371 | opacity: 0;
372 | }
373 | }
--------------------------------------------------------------------------------
/j/md5.js:
--------------------------------------------------------------------------------
1 | /*
2 | * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
3 | * Digest Algorithm, as defined in RFC 1321.
4 | * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
5 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
6 | * Distributed under the BSD License
7 | * See http://pajhome.org.uk/crypt/md5 for more info.
8 | */
9 |
10 | /*
11 | * Configurable variables. You may need to tweak these to be compatible with
12 | * the server-side, but the defaults work in most cases.
13 | */
14 | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
15 | var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
16 | var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
17 |
18 | /*
19 | * These are the functions you'll usually want to call
20 | * They take string arguments and return either hex or base-64 encoded strings
21 | */
22 | function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
23 | function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
24 | function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
25 | function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
26 | function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
27 | function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
28 |
29 | /*
30 | * Perform a simple self-test to see if the VM is working
31 | */
32 | function md5_vm_test()
33 | {
34 | return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
35 | }
36 |
37 | /*
38 | * Calculate the MD5 of an array of little-endian words, and a bit length
39 | */
40 | function core_md5(x, len)
41 | {
42 | /* append padding */
43 | x[len >> 5] |= 0x80 << ((len) % 32);
44 | x[(((len + 64) >>> 9) << 4) + 14] = len;
45 |
46 | var a = 1732584193;
47 | var b = -271733879;
48 | var c = -1732584194;
49 | var d = 271733878;
50 |
51 | for(var i = 0; i < x.length; i += 16)
52 | {
53 | var olda = a;
54 | var oldb = b;
55 | var oldc = c;
56 | var oldd = d;
57 |
58 | a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
59 | d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
60 | c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
61 | b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
62 | a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
63 | d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
64 | c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
65 | b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
66 | a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
67 | d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
68 | c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
69 | b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
70 | a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
71 | d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
72 | c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
73 | b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
74 |
75 | a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
76 | d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
77 | c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
78 | b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
79 | a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
80 | d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
81 | c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
82 | b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
83 | a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
84 | d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
85 | c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
86 | b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
87 | a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
88 | d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
89 | c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
90 | b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
91 |
92 | a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
93 | d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
94 | c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
95 | b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
96 | a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
97 | d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
98 | c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
99 | b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
100 | a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
101 | d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
102 | c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
103 | b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
104 | a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
105 | d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
106 | c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
107 | b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
108 |
109 | a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
110 | d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
111 | c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
112 | b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
113 | a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
114 | d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
115 | c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
116 | b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
117 | a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
118 | d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
119 | c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
120 | b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
121 | a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
122 | d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
123 | c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
124 | b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
125 |
126 | a = safe_add(a, olda);
127 | b = safe_add(b, oldb);
128 | c = safe_add(c, oldc);
129 | d = safe_add(d, oldd);
130 | }
131 | return Array(a, b, c, d);
132 |
133 | }
134 |
135 | /*
136 | * These functions implement the four basic operations the algorithm uses.
137 | */
138 | function md5_cmn(q, a, b, x, s, t)
139 | {
140 | return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
141 | }
142 | function md5_ff(a, b, c, d, x, s, t)
143 | {
144 | return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
145 | }
146 | function md5_gg(a, b, c, d, x, s, t)
147 | {
148 | return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
149 | }
150 | function md5_hh(a, b, c, d, x, s, t)
151 | {
152 | return md5_cmn(b ^ c ^ d, a, b, x, s, t);
153 | }
154 | function md5_ii(a, b, c, d, x, s, t)
155 | {
156 | return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
157 | }
158 |
159 | /*
160 | * Calculate the HMAC-MD5, of a key and some data
161 | */
162 | function core_hmac_md5(key, data)
163 | {
164 | var bkey = str2binl(key);
165 | if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
166 |
167 | var ipad = Array(16), opad = Array(16);
168 | for(var i = 0; i < 16; i++)
169 | {
170 | ipad[i] = bkey[i] ^ 0x36363636;
171 | opad[i] = bkey[i] ^ 0x5C5C5C5C;
172 | }
173 |
174 | var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
175 | return core_md5(opad.concat(hash), 512 + 128);
176 | }
177 |
178 | /*
179 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally
180 | * to work around bugs in some JS interpreters.
181 | */
182 | function safe_add(x, y)
183 | {
184 | var lsw = (x & 0xFFFF) + (y & 0xFFFF);
185 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
186 | return (msw << 16) | (lsw & 0xFFFF);
187 | }
188 |
189 | /*
190 | * Bitwise rotate a 32-bit number to the left.
191 | */
192 | function bit_rol(num, cnt)
193 | {
194 | return (num << cnt) | (num >>> (32 - cnt));
195 | }
196 |
197 | /*
198 | * Convert a string to an array of little-endian words
199 | * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
200 | */
201 | function str2binl(str)
202 | {
203 | var bin = Array();
204 | var mask = (1 << chrsz) - 1;
205 | for(var i = 0; i < str.length * chrsz; i += chrsz)
206 | bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
207 | return bin;
208 | }
209 |
210 | /*
211 | * Convert an array of little-endian words to a string
212 | */
213 | function binl2str(bin)
214 | {
215 | var str = "";
216 | var mask = (1 << chrsz) - 1;
217 | for(var i = 0; i < bin.length * 32; i += chrsz)
218 | str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
219 | return str;
220 | }
221 |
222 | /*
223 | * Convert an array of little-endian words to a hex string.
224 | */
225 | function binl2hex(binarray)
226 | {
227 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
228 | var str = "";
229 | for(var i = 0; i < binarray.length * 4; i++)
230 | {
231 | str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
232 | hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
233 | }
234 | return str;
235 | }
236 |
237 | /*
238 | * Convert an array of little-endian words to a base-64 string
239 | */
240 | function binl2b64(binarray)
241 | {
242 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
243 | var str = "";
244 | for(var i = 0; i < binarray.length * 4; i += 3)
245 | {
246 | var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
247 | | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
248 | | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
249 | for(var j = 0; j < 4; j++)
250 | {
251 | if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
252 | else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
253 | }
254 | }
255 | return str;
256 | }
257 |
--------------------------------------------------------------------------------
/j/ui.js:
--------------------------------------------------------------------------------
1 | // (c) 2010 Reg Braithwaite. All rights to the entirety of the program and its parts are reserved with
2 | // the exception of specific files otherwise licensed. Other licenses apply only to the files where
3 | // they appear.
4 |
5 | ;(function ($, F, undefined) {
6 |
7 | var validate = function (move) {
8 |
9 | };
10 |
11 | go.ui = {
12 | validate: validate
13 | };
14 |
15 | var initialize_ui_support = (function () {
16 |
17 | var do_undo = function (event) {
18 | var to_play;
19 | var was_playing;
20 |
21 | var this_index = go.sgf.current.length - 1;
22 | var penultimate_index = go.sgf.floor(go.sgf.current.length - 2);
23 |
24 | go.sgf.undoit($('.move.play .board'), go.sgf.current[this_index], go.sgf.current[penultimate_index]);
25 |
26 | go.sgf.current.pop();
27 |
28 | };
29 |
30 | var do_pass = function() {
31 | if (go.sgf.game_info['RE']) return;
32 |
33 | var to_play = go.playing();
34 | var was_playing = go.opponent();
35 | var was_playing_index = was_playing[0].toUpperCase();
36 | var last_move_index = go.sgf.floor(go.sgf.current.length - 1);
37 |
38 | var really_pass = function () {
39 |
40 | var annotation = {};
41 | annotation[to_play[0].toUpperCase()] = '';
42 | annotation['MN'] = (last_move_index >= 0 && go.sgf.current[last_move_index]['MN']) ? go.sgf.current[last_move_index]['MN']+ 1 : 1;
43 | go.sgf.push(annotation);
44 | };
45 |
46 | if (last_move_index >= 0) {
47 | var last_move = go.sgf.current[last_move_index];
48 | var position = last_move[was_playing_index];
49 | if (position != undefined && (position == '' || !$('.move.play .board').has('#' + position))) {
50 | go.dialog({
51 | title: "End Game",
52 | message: "End the game with a second consecutive pass?",
53 | yes_button: "Pass",
54 | no_button: "No",
55 | yes_callback: really_pass
56 | });
57 | }
58 | else really_pass();
59 | }
60 | else really_pass();
61 | };
62 |
63 | var annotate = function (event_data, key) {
64 | target = $(event_data.target);
65 | if (!target.is('.intersection')) target = target.closest('.intersection');
66 | if (target.is('.black,.white')) console.error(target.attr('id') + ' is already occupied');
67 | var killed_stones = $('.move.play .intersection.'+go.opponent()+'.last_liberty_is_'+target.attr('id'));
68 |
69 | var annotation = {};
70 | annotation[key] = target.attr('id');
71 | if (killed_stones.size() > 0) {
72 | annotation['K'] = $.map(killed_stones, 'x -> $(x).attr("id")'.lambda()).join(',');
73 | }
74 | var last_move_index = go.sgf.floor(go.sgf.current.length - 1);
75 | annotation['MN'] = (last_move_index >= 0 && go.sgf.current[last_move_index]['MN']) ? go.sgf.current[last_move_index]['MN'] + 1 : 1;
76 | go.sgf.push(annotation);
77 | };
78 |
79 | var do_play = function (event_data) {
80 | annotate(event_data, go.playing()[0].toUpperCase());
81 | return false;
82 | };
83 |
84 | var do_reject_swap = function (event_data) {
85 | var opponent_name = go.sgf.game_info['P' + go.opponent()[0].toUpperCase()];
86 | var player_name = go.sgf.game_info['P' + go.playing()[0].toUpperCase()];
87 | $('.move.play')
88 | .removeClass('swap');
89 | do_play(event_data);
90 | go.sgf.current[go.sgf.current.length - 1].C = player_name + " declines to swap places with " + opponent_name;
91 | return false;
92 | };
93 |
94 | var do_accept_swap = function (event_data) {
95 | var opponent_name = go.sgf.game_info['P' + go.opponent()[0].toUpperCase()];
96 | var player_name = go.sgf.game_info['P' + go.playing()[0].toUpperCase()];
97 |
98 | if (opponent_name.match(/white|black/i) || player_name.match(/white|black/i)) {
99 | if ($('body').is('landscape'))
100 | go.message("Since you've decided to swap, it's your opponent's turn to play " + go.playing());
101 | $.extend(go.sgf.game_info, {
102 | PH: go.sgf.game_info.PW,
103 | PG: go.sgf.game_info.PB
104 | });
105 | }
106 | else {
107 | if ($('body').is('landscape'))
108 | go.message("Since you've decided to swap, " + opponent_name + " will play " + go.playing() + ' (this changes PB and PW.)');
109 | $.extend(go.sgf.game_info, {
110 | PB: go.sgf.game_info.PG,
111 | PW: go.sgf.game_info.PH
112 | });
113 | }
114 | go.sgf.current.push({ C: player_name + " swaps places with " + opponent_name });
115 |
116 | $('.move.play')
117 | .removeClass('swap');
118 |
119 | $('.play .guest.captured')
120 | .removeClass('black')
121 | .addClass('white');
122 |
123 | $('.board .host.captured')
124 | .removeClass('white')
125 | .addClass('black');
126 |
127 | go.set_titles();
128 | return false;
129 | };
130 |
131 | var do_place = function (event_data) {
132 | annotate(event_data, 'AB');
133 | return false;
134 | }
135 |
136 | var zoomed_out_p = function() {
137 | return $('.board:last').is('.zoomout');
138 | };
139 |
140 | var remove_zoomout = function(selection) {
141 | return $(selection)
142 | .removeClass('zoomout')
143 | .unbind('.zoomout');
144 | };
145 |
146 | var remove_zoomin = function(selection) {
147 | return $(selection)
148 | .removeClass('zoomin')
149 | .unbind('.zoomin')
150 | .removedragscrollable();
151 | };
152 |
153 | var really_zoomout = function(selection) {
154 | return $(selection)
155 | .filter('.board:not(.zoomout)')
156 | .K(remove_zoomin)
157 | .addClass('zoomout');
158 | };
159 |
160 | var really_zoomin = function (target) {
161 | var across;
162 | var down;
163 | var board;
164 | if (typeof(target) == 'undefined') {
165 | across = 0;
166 | down = 0;
167 | board = null;
168 | }
169 | else {
170 | down = $(target)
171 | .closest('.row')
172 | .prevAll('.row')
173 | .size();
174 | across = $(target)
175 | .prevAll('.intersection')
176 | .size();
177 | board = $(target).closest('.board');
178 | }
179 | return function(selection) {
180 | $(selection)
181 | .filter('.board:not(.zoomin)')
182 | .K(remove_zoomout)
183 | .addClass('zoomin')
184 | .dragscrollable({ preventDefault: false });
185 | if (typeof(board) != 'undefined') {
186 | var new_target = (across == 0 && down == 0) ? null : board.find('.row:nth-child('+down+') .intersection:nth-child('+across+')');
187 | board
188 | .scrollLeft(across == 0 ? 0 : (new_target.width() * across) - (board.width() / 2)) // handles min and max for us
189 | .scrollTop(down == 0 ? 0 : (new_target.height() * down) - (board.height() / 2));
190 | }
191 | };
192 | };
193 |
194 | var do_zoomin = function(event) {
195 | $('.board')
196 | .K(really_zoomin(event.target));
197 | $(this)
198 | .children(':first')
199 | .trigger(event.gesture_data.originalEvent);
200 | return false;
201 | };
202 |
203 | var do_zoomout = function(event) {
204 | $('.board')
205 | .K(really_zoomout);
206 | return false;
207 | };
208 |
209 | var do_scale = function(event, data) {
210 | if (event.scale <= 0.75)
211 | $('.board')
212 | .K(really_zoomout);
213 | else if (event.scale >= 1.5)
214 | $('.board')
215 | .K(really_zoomin(event.target));
216 | return false;
217 | };
218 |
219 | var show_play_info = function (event) {
220 | var whites = 0;
221 | var blacks = 0;
222 | $.each(go.sgf.current, function (index, properties) {
223 | if (properties.W && properties.K)
224 | blacks = blacks + 1 + ((properties.K.length - 2) / 3);
225 | else if (properties.W && properties.K)
226 | whites = whites + 1 + ((properties.K.length - 2) / 3);
227 | });
228 | $('#info')
229 | .find('.captured_blacks')
230 | .text(blacks == 0 ? 'no stones' : (blacks == 1 ? 'one stone' : '' + blacks + ' stones'))
231 | .end()
232 | .find('.captured_whites')
233 | .text(whites == 0 ? 'no stones' : (whites == 1 ? 'one stone' : '' + whites + ' stones'))
234 | .end();
235 | jQT.goTo($('#info'), 'slideup.reverse');
236 | return false;
237 | };
238 |
239 | return function() {
240 | $('.move.play')
241 | .gesture(['click', 'circle', 'close']);
242 | $('.move')
243 | .gesture([
244 | 'bottom', 'hold', 'scale', 'left', 'right', 'open',
245 | { scrub: function(target) {
246 | return $(target)
247 | .parents('body > *')
248 | .find('.scrub');
249 | }
250 | }
251 | ]);
252 | $('.move.play:has(.zoomout)')
253 | .live('gesture_open',
254 | function () {
255 | go.dialog({
256 | title: "New Game",
257 | message: "Start a new game from scratch?",
258 | yes_button: "New",
259 | yes_callback: function () { jQT.swapPages( $('.move.play'), $('#new'), 'dissolve'); }
260 | });
261 | return false;
262 | }
263 | );
264 |
265 | $('.board')
266 | .live('gesture_scale', do_scale);
267 |
268 | $('.board.zoomout')
269 | .live('gesture_hold', do_zoomin);
270 | $('.board.zoomin')
271 | .live('gesture_hold', do_zoomout);
272 |
273 | $('.move.play .board.pass:not(:has(.playable_black.black,.playable_white.white))')
274 | .live('gesture_close', do_pass);
275 |
276 | $('.move.play .board:not(.pass):not(:has(.playable_black.black,.playable_white.white))')
277 | .live('gesture_close', function () {go.message("Sorry, the rules prohibit passing at this time");});
278 |
279 | $('.move.play .board')
280 | .live('gesture_scrub', do_undo)
281 | .live('gesture_bottom', show_play_info);
282 |
283 | $('#info')
284 | .gesture(['top'])
285 | .bind('gesture_top', function(event) { jQT.goBack(); });
286 |
287 | $('.move.play.black:not(.swap) .board.play .playable_black')
288 | .live('gesture_click', do_play);
289 | $('.move.play.white:not(.swap) .board.play .playable_white')
290 | .live('gesture_click', do_play);
291 |
292 | $('.move.play.black .board.place .playable_black')
293 | .live('gesture_click', do_place);
294 | $('.move.play.white .board.place .playable_white')
295 | .live('gesture_click', do_place);
296 |
297 | $('.move.play.black.swap .board.play .playable_black')
298 | .live('gesture_click', do_reject_swap);
299 | $('.move.play.white.swap .board.play .playable_white')
300 | .live('gesture_click', do_reject_swap);
301 |
302 | $('.move.play.swap .board.play')
303 | .live('gesture_circle', do_accept_swap);
304 |
305 | };
306 | })();
307 |
308 | go.on_document_ready(initialize_ui_support);
309 |
310 | })(jQuery, Functional);
--------------------------------------------------------------------------------
/c/sass/board.iphone.sass:
--------------------------------------------------------------------------------
1 | .board.size19
2 | $full_cells: 19
3 | $zoom_out_size: 14px
4 | $zoom_out_cells: $full_cells
5 | $zoom_in_size: 30px
6 | $zoom_in_cells: 9
7 | &.zoomin
8 | width: $zoom_in_size * $zoom_in_cells
9 | height: $zoom_in_size * $zoom_in_cells
10 | .row
11 | height: $zoom_in_size
12 | width: $zoom_in_size * $full_cells
13 | img
14 | height: $zoom_in_size
15 | width: $zoom_in_size
16 | &.zoomout
17 | width: $zoom_out_size * $full_cells
18 | height: $zoom_out_size * $full_cells
19 | .row
20 | height: $zoom_out_size
21 | width: $zoom_out_size * $zoom_out_cells
22 | img
23 | height: $zoom_out_size
24 | width: $zoom_out_size
25 |
26 | .board.size17
27 | $full_cells: 17
28 | $zoom_out_size: 15px
29 | $zoom_out_cells: $full_cells
30 | $zoom_in_size: 30px
31 | $zoom_in_cells: 9
32 | &.zoomin
33 | width: $zoom_in_size * $zoom_in_cells
34 | height: $zoom_in_size * $zoom_in_cells
35 | .row
36 | height: $zoom_in_size
37 | width: $zoom_in_size * $full_cells
38 | img
39 | height: $zoom_in_size
40 | width: $zoom_in_size
41 | &.zoomout
42 | width: $zoom_out_size * $full_cells
43 | height: $zoom_out_size * $full_cells
44 | .row
45 | height: $zoom_out_size
46 | width: $zoom_out_size * $zoom_out_cells
47 | img
48 | height: $zoom_out_size
49 | width: $zoom_out_size
50 |
51 | .board.size15
52 | $full_cells: 15
53 | $zoom_out_size: 18px
54 | $zoom_out_cells: $full_cells
55 | $zoom_in_size: 30px
56 | $zoom_in_cells: 9
57 | &.zoomin
58 | width: $zoom_in_size * $zoom_in_cells
59 | height: $zoom_in_size * $zoom_in_cells
60 | .row
61 | height: $zoom_in_size
62 | width: $zoom_in_size * $full_cells
63 | img
64 | height: $zoom_in_size
65 | width: $zoom_in_size
66 | &.zoomout
67 | width: $zoom_out_size * $full_cells
68 | height: $zoom_out_size * $full_cells
69 | .row
70 | height: $zoom_out_size
71 | width: $zoom_out_size * $zoom_out_cells
72 | img
73 | height: $zoom_out_size
74 | width: $zoom_out_size
75 |
76 | .board.size13
77 | $full_cells: 13
78 | $zoom_out_size: 20px
79 | $zoom_out_cells: $full_cells
80 | $zoom_in_size: 30px
81 | $zoom_in_cells: 9
82 | &.zoomin
83 | width: $zoom_in_size * $zoom_in_cells
84 | height: $zoom_in_size * $zoom_in_cells
85 | .row
86 | height: $zoom_in_size
87 | width: $zoom_in_size * $full_cells
88 | img
89 | height: $zoom_in_size
90 | width: $zoom_in_size
91 | &.zoomout
92 | width: $zoom_out_size * $full_cells
93 | height: $zoom_out_size * $full_cells
94 | .row
95 | height: $zoom_out_size
96 | width: $zoom_out_size * $zoom_out_cells
97 | img
98 | height: $zoom_out_size
99 | width: $zoom_out_size
100 |
101 | .board.size11
102 | $full_cells: 11
103 | $zoom_out_size: 24px
104 | $zoom_out_cells: $full_cells
105 | $zoom_in_size: 30px
106 | $zoom_in_cells: 9
107 | &.zoomin
108 | width: $zoom_in_size * $zoom_in_cells
109 | height: $zoom_in_size * $zoom_in_cells
110 | .row
111 | height: $zoom_in_size
112 | width: $zoom_in_size * $full_cells
113 | img
114 | height: $zoom_in_size
115 | width: $zoom_in_size
116 | &.zoomout
117 | width: $zoom_out_size * $full_cells
118 | height: $zoom_out_size * $full_cells
119 | .row
120 | height: $zoom_out_size
121 | width: $zoom_out_size * $zoom_out_cells
122 | img
123 | height: $zoom_out_size
124 | width: $zoom_out_size
125 |
126 | .board.size9
127 | $full_cells: 9
128 | $zoom_out_size: 30px
129 | $zoom_out_cells: $full_cells
130 | $zoom_in_size: 30px
131 | $zoom_in_cells: 9
132 | &.zoomin
133 | width: $zoom_in_size * $zoom_in_cells
134 | height: $zoom_in_size * $zoom_in_cells
135 | .row
136 | height: $zoom_in_size
137 | width: $zoom_in_size * $full_cells
138 | img
139 | height: $zoom_in_size
140 | width: $zoom_in_size
141 | &.zoomout
142 | width: $zoom_out_size * $full_cells
143 | height: $zoom_out_size * $full_cells
144 | .row
145 | height: $zoom_out_size
146 | width: $zoom_out_size * $zoom_out_cells
147 | img
148 | height: $zoom_out_size
149 | width: $zoom_out_size
150 |
151 | .board
152 | overflow: hidden
153 | position: relative
154 | left: 50%
155 | :margin
156 | :left -135px
157 | :top 10px
158 | .intersections
159 | position: relative
160 | background: black
161 | .intersection
162 | :display inline-block
163 | .row
164 | &:first-child
165 | .intersection
166 | &:first-child
167 | &.black
168 | background: url('../i/board/temporary/tile1nw.png')
169 | &.playable_black,&.playable_white
170 | background: url('../i/board/temporary/tile1nwd.png') !important
171 | &.latest
172 | background: url('../i/board/temporary/tile1nwd.png') !important
173 | &.white
174 | background: url('../i/board/temporary/tile2nw.png')
175 | &.playable_black,&.playable_white
176 | background: url('../i/board/temporary/tile2nwd.png') !important
177 | &.latest
178 | background: url('../i/board/temporary/tile2nwd.png') !important
179 | &:not(.black):not(.white)
180 | background: url('../i/board/temporary/tile0nw.png')
181 | &:not(:first-child):not(:last-child)
182 | &.black
183 | background: url('../i/board/temporary/tile1n.png')
184 | &.playable_black,&.playable_white
185 | background: url('../i/board/temporary/tile1nd.png') !important
186 | &.latest
187 | background: url('../i/board/temporary/tile1nd.png') !important
188 | &.white
189 | background: url('../i/board/temporary/tile2n.png')
190 | &.playable_black,&.playable_white
191 | background: url('../i/board/temporary/tile2nd.png') !important
192 | &.latest
193 | background: url('../i/board/temporary/tile2nd.png') !important
194 | &:not(.black):not(.white)
195 | background: url('../i/board/temporary/tile0n.png')
196 | &:last-child
197 | &.black
198 | background: url('../i/board/temporary/tile1ne.png')
199 | &.playable_black,&.playable_white
200 | background: url('../i/board/temporary/tile1ned.png') !important
201 | &.latest
202 | background: url('../i/board/temporary/tile1ned.png') !important
203 | &.white
204 | background: url('../i/board/temporary/tile2ne.png')
205 | &.playable_black,&.playable_white
206 | background: url('../i/board/temporary/tile2ned.png') !important
207 | &.latest
208 | background: url('../i/board/temporary/tile2ned.png') !important
209 | &:not(.black):not(.white)
210 | background: url('../i/board/temporary/tile0ne.png')
211 | &:not(:first-child):not(:last-child)
212 | .intersection
213 | &:first-child
214 | &.black
215 | background: url('../i/board/temporary/tile1w.png')
216 | &.playable_black,&.playable_white
217 | background: url('../i/board/temporary/tile1wd.png') !important
218 | &.latest
219 | background: url('../i/board/temporary/tile1wd.png') !important
220 | &.white
221 | background: url('../i/board/temporary/tile2w.png')
222 | &.playable_black,&.playable_white
223 | background: url('../i/board/temporary/tile2wd.png') !important
224 | &.latest
225 | background: url('../i/board/temporary/tile2wd.png') !important
226 | &:not(.black):not(.white)
227 | background: url('../i/board/temporary/tile0w.png')
228 | &:not(:first-child):not(:last-child)
229 | &.black
230 | background: url('../i/board/temporary/tile1.png')
231 | &.playable_black,&.playable_white
232 | background: url('../i/board/temporary/tile1d.png') !important
233 | &.latest
234 | background: url('../i/board/temporary/tile1d.png') !important
235 | &.white
236 | background: url('../i/board/temporary/tile2.png')
237 | &.playable_black,&.playable_white
238 | background: url('../i/board/temporary/tile2d.png') !important
239 | &.latest
240 | background: url('../i/board/temporary/tile2d.png') !important
241 | &:last-child
242 | &.black
243 | background: url('../i/board/temporary/tile1e.png')
244 | &.playable_black,&.playable_white
245 | background: url('../i/board/temporary/tile1ed.png') !important
246 | &.latest
247 | background: url('../i/board/temporary/tile1ed.png') !important
248 | &.white
249 | background: url('../i/board/temporary/tile2e.png')
250 | &.playable_black,&.playable_white
251 | background: url('../i/board/temporary/tile2ed.png') !important
252 | &.latest
253 | background: url('../i/board/temporary/tile2ed.png') !important
254 | &:not(.black):not(.white)
255 | background: url('../i/board/temporary/tile0e.png')
256 | &:last-child
257 | .intersection
258 | &:first-child
259 | &.black
260 | background: url('../i/board/temporary/tile1sw.png')
261 | &.playable_black,&.playable_white
262 | background: url('../i/board/temporary/tile1swd.png') !important
263 | &.latest
264 | background: url('../i/board/temporary/tile1swd.png') !important
265 | &.white
266 | background: url('../i/board/temporary/tile2sw.png')
267 | &.playable_black,&.playable_white
268 | background: url('../i/board/temporary/tile2swd.png') !important
269 | &.latest
270 | background: url('../i/board/temporary/tile2swd.png') !important
271 | &:not(.black):not(.white)
272 | background: url('../i/board/temporary/tile0sw.png')
273 | &:not(:first-child):not(:last-child)
274 | &.black
275 | background: url('../i/board/temporary/tile1s.png')
276 | &.playable_black,&.playable_white
277 | background: url('../i/board/temporary/tile1sd.png') !important
278 | &.latest
279 | background: url('../i/board/temporary/tile1sd.png') !important
280 | &.white
281 | background: url('../i/board/temporary/tile2s.png')
282 | &.playable_black,&.playable_white
283 | background: url('../i/board/temporary/tile2sd.png') !important
284 | &.latest
285 | background: url('../i/board/temporary/tile2sd.png') !important
286 | &:not(.black):not(.white)
287 | background: url('../i/board/temporary/tile0s.png')
288 | &:last-child
289 | &.black
290 | background: url('../i/board/temporary/tile1se.png')
291 | &.playable_black,&.playable_white
292 | background: url('../i/board/temporary/tile1sed.png') !important
293 | &.latest
294 | background: url('../i/board/temporary/tile1sed.png') !important
295 | &.white
296 | background: url('../i/board/temporary/tile2se.png')
297 | &.playable_black,&.playable_white
298 | background: url('../i/board/temporary/tile2sed.png') !important
299 | &.latest
300 | background: url('../i/board/temporary/tile2sed.png') !important
301 | &:not(.black):not(.white)
302 | background: url('../i/board/temporary/tile0se.png')
303 | .star
304 | &.black
305 | background: url('../i/board/temporary/tile1.png')
306 | &.playable_black,&.playable_white
307 | background: url('../i/board/temporary/tile1d.png') !important
308 | &.latest
309 | background: url('../i/board/temporary/tile1d.png') !important
310 | &.white
311 | background: url('../i/board/temporary/tile2.png')
312 | &.playable_black,&.playable_white
313 | background: url('../i/board/temporary/tile2d.png') !important
314 | &.latest
315 | background: url('../i/board/temporary/tile2d.png') !important
316 | &:not(.black):not(.white)
317 | background: url('../i/board/temporary/tile0c.png')
318 | &.playable_black,&.playable_white
319 | BEFORE: URL('../i/board/temporary/tile0c.png')
320 |
321 | @mixin interior($corner,$middle)
322 | .row
323 | &:nth-child(#{$corner}),&:nth-child(#{$middle}),&:nth-last-child(#{$corner})
324 | .intersection:not(.black):not(.white)
325 | &:nth-child(#{$corner}),&:nth-child(#{$middle}),&:nth-last-child(#{$corner})
326 | background: url('../i/board/temporary/tile0c.png')
327 | &:not(:nth-child(#{$corner})):not(:nth-child(#{$middle})):not(:nth-last-child(#{$corner})):not(:first-child):not(:last-child)
328 | background: url('../i/board/temporary/tile0.png')
329 | &:not(:nth-child(#{$corner})):not(:nth-child(#{$middle})):not(:nth-last-child(#{$corner})):not(:first-child):not(:last-child)
330 | .intersection:not(.black):not(.white):not(:first-child):not(:last-child)
331 | background: url('../i/board/temporary/tile0.png')
332 |
333 | .board
334 | &.size9
335 | @include interior(3,5)
336 | &.size11
337 | @include interior(3,6)
338 | &.size13
339 | @include interior(4,7)
340 | &.size15
341 | @include interior(4,8)
342 | &.size17
343 | @include interior(4,9)
344 | &.size19
345 | @include interior(4,10)
346 |
347 | .intersection
348 | &.playable_black,&.playable_white
349 | cursor: pointer
350 |
351 | .move
352 | .actions
353 | .send
354 | :display none
355 |
356 | .move.playing
357 | .actions
358 | .send
359 | :display inline !important
360 |
361 | .intersection
362 | -o-background-size: 100%
363 | -webkit-background-size: 100%
364 | -khtml-background-size: 100%
365 | -moz-background-size: 100%
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | Wood & Stones
2 | ===
3 |
4 | Go is "an ancient oriental board game for two players that is noted for being rich in strategy despite its simple rules." [I tried to learn Go](http://github.com/raganwald/homoiconic/blob/master/2009-10-20/high_anxiety.md#readme "High Anxiety") recently, and it was a rich and rewarding personal experience to struggle with my inability to play at even a novice level. I received a lot of [great feedback][hn] about that post, including a nice comment from Dave Peck, who pointed me to his weekend project, [Dave Peck's Go](http://github.com/davepeck/appengine-go "[Dave Peck's Go]").
5 |
6 | The sense of adventure in finding things out can be experienced in many different ways. Learning to play less poorly is one way. Another is to write a game playing algorithm, something that has fascinated me since I wrote a [Maharajah and the Sepoys](http://en.wikipedia.org/wiki/Maharajah_and_the_Sepoys) playing game in BASIC back at St. Andrews' College in 1977. A third is to write a server that adjudicates play between two humans. This is clearly less difficult but still provides opportunities for creativity and expression, which is why it is a [favourite interview question](http://weblog.raganwald.com/2006/06/my-favourite-interview-question.html "My favourite interview question").
7 |
8 | So, here is "[Wood & Stones][index]," a pass and play local web application that adjudicates a game of Go between two players. This is an ongoing work, with both feature design, UX design, and software design changing on an almost daily basis. That is a long-winded way of saying that IMHO the code is nearly complete crap. It is as if you picked up an architect's sketch pad and looked at a page to find it covered with scribbles and cross-outs.
9 |
10 | > This is written *specifically* for the iPad at this time. I also test it on OS X Safari. Updated stylesheets for the iPhone/iPod Touch are in the works. I have made no attempt to test it on any other OS or browser. This is a pass-and-play application: It's for playing face-to-face with someone, not for playing the computer or playing with someone over the Internet ([Issue 250][igs]). It turns an iPad into a portable go board that knows something about legal moves, can set up pieces for you, and allows you to go back and review the game.
11 |
12 | help with playing
13 | ---
14 |
15 | To start a new game, open [Wood & Stones][index] using your iPad (it used to work just fine on iPhone, but I haven't gotten around to selecting the correct style sheet depending on whether you're on an iPhone or an iPad. [Issue 275][styles]!):
16 |
17 | ![Start][start]
18 |
19 | If you want, you can give nicknames for each player. If you don't, you will be "Black" and "White" respectively.
20 |
21 | Choose game to play, a board size, and setup. "Classic Go" is exactly what you think it is. The other options are why I had the stones to call this "Wood & Stones." Click "play" and you can start your game.
22 |
23 | ![White to Play][white_to_play]
24 |
25 | In direct violation of [The Design of Everyday Things](http://www.amazon.com/gp/product/0465067107?ie=UTF8&tag=raganwald001-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0465067107 "Amazon.com: The Design of Everyday Things (9780465067107): Donald A. Norman: Books"), Wood & Stones is an experiment with *removing* the visible affordances in the User Interface. I am trying to make as much as possible work with gestures like swiping the screen or drawing simple symbols.
26 |
27 | When it's your turn to play, tap the intersection where you wish to play a stone. If your play kills any of your opponent's stones, they will fade from sight. If you like your play, pass the iPad to your opponent and it's their turn. If you don't like your play, "scrub" the board by swiping rapidly from left to right to left three or more times. It will be your turn again and you can tap a different intersection. You can undo multiple times if you want.
28 |
29 | To pass, draw an "X" using three continuous strokes of your finger:
30 |
31 | ![Pass Gesture][pass]
32 |
33 | If it is the second pass, you will be asked to confirm that you wish to end the game. Yes, you can scrub to undo a pass. If a game ends with two passes, it's up to you and your opponent to figure out who won.
34 |
35 | **history and info**
36 |
37 | If you would like to see a history of the game, you move backwards in time by swiping from left to right. This is like moving the film so that the past becomes visible. Each swipe from left to right moves back one move. You can move forward in the history by swiping from right to left. Once you have returned to the current move, swiping right to left does nothing further.
38 |
39 | You can see the game's current status by swiping towards the bottom of the screen:
40 |
41 | ![Show Info][bottom]
42 |
43 | The game info will slide down from the top of the screen:
44 |
45 | ![Game Info][info]
46 |
47 | To go back to the play of the game, swipe towards the top of the screen:
48 |
49 | ![Return to Play][top]
50 |
51 | **zooming and dragging**
52 |
53 | With larger boards, it can be a challenge to tap the correct stone location on an iPhone or iPod Touch. To zoom in, hold your finger or mouse down on the board. After a moment, the board will zoom. While zoomed in, you can tap to place a stone or drag the board to pan it around. When zoomed in, you cannot go back or forward in the history as the swipe becomes a pan. To zoom back out, hold your finger or mouse down again.
54 |
55 | On multi-touch devices, you can also use the pinch gesture to zoom in or out.
56 |
57 | games with standard rules and victory conditions
58 | ---
59 |
60 | The application is specifically written to support other games, most of which are documented on [Sensei's Go Variant Page][sgv]. Each game offers a variety of setup options. The most 'normal' games to the Go player are those that have the exact same rules and victory conditions, namely territory plus captures. They differ only in how the board is set up at the beginning of play.
61 |
62 | **Classic**: This is the standard game of Go with the standard options for setup: Either black plays first, or black is awarded a handicap of between two and nine stones and white plays first. Handicap stones are placed on the Hoshi points in the conventional manner. Wood & Stones does not score the game but it will end the game after two consecutive passes.
63 |
64 | **Free Placement**: This is also the standard rules for Go, however if black is granted a handicap, black plays the stones wherever he likes rather than having them placed on the standard Hoshi points. For example, if black is given a handicap of three stones, he will play the first three moves in a row and then white will play and the turns will alternate in the normal fashion for the remainder of the game.
65 |
66 | **More Setups**: Once again the rules are the standard rules of Go, however the initial setup differs radically from tranditional Go. The options include:
67 |
68 | * [Pie Rule][pie]: Black plays a single stone first. White has two choices. If he plays a stone, the game continues normally. However, white can also *swap* places by drawing a circle on the board with his finger. The two players switch colours, and the player who was originally black is now white and the player who was originally white is now black. The effect of this rule is that Black does not wish to make too strong an opening play for fear that white will choose to swap. Likewise, black does not wish to make too weak a play either, so he should make a play that ideally is perfectly balanced.
69 |
70 | * [Wild Fuskeki][wild]: This is a standard game, however the first three moves are randomly chosen for each player. Black can have up to six randomly placed handicap stones. Initial positions will never include dead stones, ataris, or stones placed in either of the two edge rows or columns. Wild Fuseki discourages extensive memorization of opening play sequences and encourages strong fundamental style. (*Really Wild Fuseki* is exactly the same thing, however *twelve* stones are placed for each player.)
71 |
72 | ![Wild Fuseki][iwild]
73 |
74 | * [Influence Go][influence] gives each player opposing edges of the board. This game usually involves a fight to secure the center and establish a connection to your strong sides.
75 |
76 | ![Influence Go][iinfluence]
77 |
78 | * [Dots Go][dots] consists of stones on alternate intersections of the board. Games evolve very differently than standard Go.
79 |
80 | ![Dots Go][idots]
81 |
82 | * [Sunjang Baduk][baduk] is an archaic Korean version of Go. There is a prescribed opening position, and the scoring is a little different from Japanese or Chinese go. Even if you don't care to play with different scoring, you might find games with the Sunjang Baduk opening setup a refreshing change of pace.
83 |
84 | * [Classical Chinese Opening][classical] go players started each game with two stones each on corner Hoshi points, leading to fighting. Classical Chinese rules were also different, however choosing this option starts a standard game of Go with the Classical Chinese Opening.
85 |
86 | games where white is trying to live
87 | ---
88 |
89 | Some games have standard rules but different victory conditions. A number of these games share the common theme of a struggle for white to survive against crushing odds. In these games, white wins if he can create life. Black wins the moment there are no white stones on the board.
90 |
91 | * [Corner Go][corner] is a corner invasion exercise: Only one corner is available to White. Corner Go works well on small boards.
92 |
93 | ![Corner Go][icorner]
94 |
95 | * [Shape Go][shape] gives Black unkillable stones all the way around the board, and white has to try to make life with no corners or edges. Best on larger boards.
96 |
97 | ![Shape Go][ibox]
98 |
99 | * In the [Kill-all][killall] game, black is given a large number of free placements and white simply tries to survive. An even game is thought to be seventeen placements on a 19x19 board, however you can choose more or fewer to establish a handicap. You may also choose a smaller board and fewer placements.
100 |
101 | other games with non-standard victory conditions
102 | ---
103 |
104 | * [Atari Go][atari] uses normal rules on a 9x9 board, however the winner is the first to capture an opponent's stone. There is a progression of teaching setups given with the student playing black. The final setup, Cross-cutting, should lead to successive draws. When a student can always draw in this situation, they can move up to Capture Five.
105 |
106 | * *Capture Five* uses normal rules on a small board, however the winner is the first to capture five stones. This introduces the idea of sacrifice into the game. It is a natural progression from Atari Go.
107 |
108 | * [Irensei][irensei] is a game with standard Go rules, however captures and territory are irrelevant to scoring. The winner is the first player to make an unbroken line of seven stones in a row, although a line with stones within two intersections of the edge does not count. Black plays first, and to counter this advantage there is a special rule that black loses if he makes a line of eight or more stones. White can make a line of any length.
109 |
110 | games with slightly different rules
111 | ---
112 |
113 | * In [Gonnect][gonnect], the winner is the first to connect either pair of opposite sides of the board with a single group *or* a player loses when he has no legal move available. *Passing is not allowed*. This difference from normal Go is crucial, as it prevents a deadlock where neither player can connect: each player must eventually fill in their territory until they are vulnerable to capture or have no legal moves available.
114 |
115 | * In [One Eyed Go][oneeye], suicide is never allowed, even if your play would otherwise capture stones. One consequence of this simplification of the rules is that a single eye is enough to make a group safe.
116 |
117 | code confessions, a/k/a estimating the WTFs per LOC
118 | ---
119 |
120 | This is my first [jQuery](http://jquery.com/ "jQuery: The Write Less, Do More, JavaScript Library") project, and it shows. I'm also using [jQTouch](http://www.jqtouch.com/), although I'm using less and less of it as I get more comfortable with Mobile Safari. I've picked up a few other jQuery plugins, including my own [iGesture][igesture] for gestures like swipes and scrubs.
121 |
122 | **license terms**
123 |
124 | (c) 2010 Reg Braithwaite. All rights to the entirety of the program and the parts I have written are reserved with the exception of specific files otherwise licensed. Other licenses apply only to the files where they appear. This may change in time, check back.
125 |
126 | Exemptions include iGesture and Dragscrollable, which I have licensed under the MIT license, plus various jquery plugins written by others.
127 |
128 | All of the images used in the main game board are modified versions of files Dave Peck found on the Wikimedia Commons. These
129 | are distributed with the Creative Commons Attribution 2.0 ShareAlike license. Some other images were hand-drawn by Dave Peck, who put them under the Creative Commons Attribution ShareAlike 2.0 license: http://creativecommons.org/licenses/by-sa/2.0/
130 |
131 | [igesture]: http://github.com/raganwald/iGesture
132 | [index]: http://raganwald.github.com/wood_and_stones/index.html
133 | [start]: http://raganwald.github.com/wood_and_stones/i/about/start.png
134 | [white_to_play]: http://raganwald.github.com/wood_and_stones/i/about/white_to_play.png
135 | [pass]: http://raganwald.github.com/wood_and_stones/i/about/pass.png
136 | [oneeye]: http://senseis.xmp.net/?OneEyedGo
137 | [atari]: http://senseis.xmp.net/?AtariGo
138 | [gonnect]: http://senseis.xmp.net/?Gonnect
139 | [sgv]: http://senseis.xmp.net/?GoVariant
140 | [wild]: http://senseis.xmp.net/?WildFuseki
141 | [corner]: http://senseis.xmp.net/?BiggestCorner
142 | [shape]: http://senseis.xmp.net/?ShapeGameSolid
143 | [influence]: http://senseis.xmp.net/?InfluenceGo
144 | [dots]: http://senseis.xmp.net/?DotsGo
145 | [ibox]: http://raganwald.github.com/wood_and_stones/i/about/box.png
146 | [idots]: http://raganwald.github.com/wood_and_stones/i/about/dots.png
147 | [iinfluence]: http://raganwald.github.com/wood_and_stones/i/about/influence.png
148 | [icorner]: http://raganwald.github.com/wood_and_stones/i/about/corner.png
149 | [iwild]: http://raganwald.github.com/wood_and_stones/i/about/wild.png
150 | [info]: http://raganwald.github.com/wood_and_stones/i/about/info.png
151 | [bottom]: http://raganwald.github.com/wood_and_stones/i/about/bottom.png
152 | [top]: http://raganwald.github.com/wood_and_stones/i/about/top.png
153 | [baduk]: http://senseis.xmp.net/?SunjangBaduk
154 | [classical]: http://senseis.xmp.net/?ChineseClassicalOpening
155 | [killall]: http://senseis.xmp.net/?KillAllGame
156 | [pie]: http://en.wikipedia.org/wiki/Pie_rule
157 | [irensei]: http://en.wikipedia.org/wiki/Irensei
158 | [igs]: http://github.com/raganwald/wood_and_stones/issues/#issue/250
159 | [styles]: http://github.com/raganwald/wood_and_stones/issues/#issue/275
160 | [hn]: http://news.ycombinator.com/item?id=904765
--------------------------------------------------------------------------------
/c/sass/jqtouch.ipad.customized.sass:
--------------------------------------------------------------------------------
1 | body
2 | background: #000
3 | color: #ddd
4 | > *
5 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#333333), to(#5e5e65))
6 |
7 | h1, h2
8 | font: bold 18px Helvetica
9 | text-shadow: rgba(255, 255, 255, 0.2) 0 1px 1px
10 | color: #000
11 | margin: 10px 20px 5px
12 |
13 | /* @group Toolbar
14 |
15 | .toolbar
16 | -webkit-box-sizing: border-box
17 | border-bottom: 1px solid #000
18 | padding: 10px
19 | height: 45px
20 | background: url(../i/themes/jqt/img/toolbar.png) black repeat-x
21 | position: relative
22 |
23 | .black-translucent .toolbar
24 | margin-top: 20px
25 |
26 | .toolbar > h1
27 | position: absolute
28 | overflow: hidden
29 | left: 50%
30 | top: 10px
31 | line-height: 1em
32 | margin: 1px 0 0 -192px
33 | height: 40px
34 | font-size: 20px
35 | width: 384px
36 | font-weight: bold
37 | text-shadow: rgba(0, 0, 0, 1) 0 -1px 1px
38 | text-align: center
39 | text-overflow: ellipsis
40 | white-space: nowrap
41 | color: #fff
42 |
43 | body.landscape .toolbar > h1
44 | margin-left: -256px
45 | width: 512px
46 |
47 | .button, .back, .cancel, .add
48 | position: absolute
49 | overflow: hidden
50 | top: 8px
51 | right: 10px
52 | margin: 0
53 | border-width: 0 5px
54 | padding: 0 3px
55 | width: auto
56 | height: 30px
57 | line-height: 30px
58 | font-family: inherit
59 | font-size: 12px
60 | font-weight: bold
61 | color: #fff
62 | text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0
63 | text-overflow: ellipsis
64 | text-decoration: none
65 | white-space: nowrap
66 | background: none
67 | -webkit-border-image: url(../i/themes/jqt/img/button.png) 0 5 0 5
68 |
69 | .blueButton
70 | -webkit-border-image: url(../i/themes/jqt/img/blueButton.png) 0 5 0 5
71 | border-width: 0 5px
72 |
73 | .back
74 | left: 6px
75 | right: auto
76 | padding: 0
77 | max-width: 55px
78 | border-width: 0 8px 0 14px
79 | -webkit-border-image: url(../i/themes/jqt/img/back_button.png) 0 8 0 14
80 | &.active
81 | -webkit-border-image: url(../i/themes/jqt/img/back_button_clicked.png) 0 8 0 14
82 | color: #aaa
83 |
84 | .leftButton, .cancel
85 | left: 6px
86 | right: auto
87 |
88 | .add
89 | font-size: 24px
90 | line-height: 24px
91 | font-weight: bold
92 |
93 | .whiteButton, .grayButton
94 | display: block
95 | border-width: 0 12px
96 | padding: 10px
97 | text-align: center
98 | font-size: 20px
99 | font-weight: bold
100 | text-decoration: inherit
101 | color: inherit
102 |
103 | .whiteButton
104 | -webkit-border-image: url(../i/themes/jqt/img/whiteButton.png) 0 12 0 12
105 | text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0
106 |
107 | .grayButton
108 | -webkit-border-image: url(../i/themes/jqt/img/grayButton.png) 0 12 0 12
109 | color: #FFFFFF
110 |
111 | /* @end
112 | /* @group Lists
113 |
114 | h1 + ul, h2 + ul, h3 + ul, h4 + ul, h5 + ul, h6 + ul
115 | margin-top: 0
116 |
117 | ul
118 | color: #aaa
119 | border: 1px solid #333333
120 | font: bold 18px Helvetica
121 | padding: 0
122 | margin: 15px 10px 17px 10px
123 | &.rounded
124 | -webkit-border-radius: 8px
125 | -webkit-box-shadow: rgba(0, 0, 0, 0.3) 1px 1px 3px
126 | li
127 | &:first-child
128 | border-top: 0
129 | -webkit-border-top-left-radius: 8px
130 | -webkit-border-top-right-radius: 8px
131 | a
132 | border-top: 0
133 | -webkit-border-top-left-radius: 8px
134 | -webkit-border-top-right-radius: 8px
135 | &:last-child
136 | -webkit-border-bottom-left-radius: 8px
137 | -webkit-border-bottom-right-radius: 8px
138 | a
139 | -webkit-border-bottom-left-radius: 8px
140 | -webkit-border-bottom-right-radius: 8px
141 | li
142 | color: #666
143 | border-top: 1px solid #333
144 | border-bottom: #555858
145 | list-style-type: none
146 | padding: 10px 10px 10px 10px
147 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142))
148 | overflow: hidden
149 | &.arrow
150 | background-image: url(../i/themes/jqt/img/chevron.png), -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142))
151 | background-position: right center
152 | background-repeat: no-repeat
153 | &.forward
154 | background-image: url(../i/themes/jqt/img/chevron_circle.png), -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142))
155 | background-position: right center
156 | background-repeat: no-repeat
157 | a
158 | color: #fff
159 | text-decoration: none
160 | text-overflow: ellipsis
161 | white-space: nowrap
162 | overflow: hidden
163 | display: block
164 | padding: 12px 10px 12px 10px
165 | margin: -10px
166 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0)
167 | text-shadow: rgba(0, 0, 0, 0.2) 0 1px 1px
168 |
169 | /* universal links on list
170 |
171 | li.img a + a
172 | color: #fff
173 | text-decoration: none
174 | text-overflow: ellipsis
175 | white-space: nowrap
176 | overflow: hidden
177 | display: block
178 | padding: 12px 10px 12px 10px
179 | margin: -10px
180 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0)
181 | text-shadow: rgba(0, 0, 0, 0.2) 0 1px 1px
182 |
183 | ul
184 | li
185 | a
186 | &.active, &.button
187 | background-color: #53b401
188 | color: #fff
189 | &.active.loading
190 | background-image: url(../i/themes/jqt/img/loading.gif)
191 | background-position: 95% center
192 | background-repeat: no-repeat
193 | &.arrow a.active
194 | background-image: url(../i/themes/jqt/img/chevron.png)
195 | background-position: right center
196 | background-repeat: no-repeat
197 | &.forward a.active
198 | background-image: url(../i/themes/jqt/img/chevron_circle.png)
199 | background-position: right center
200 | background-repeat: no-repeat
201 | &.img a +
202 | a
203 | margin: -10px 10px -20px -5px
204 | font-size: 17px
205 | font-weight: bold
206 | + a
207 | font-size: 14px
208 | font-weight: normal
209 | margin-left: -10px
210 | margin-bottom: -10px
211 | margin-top: 0
212 | small + a
213 | margin-left: -5px
214 | + a
215 | margin-left: -10px
216 | margin-top: -20px
217 | margin-bottom: -10px
218 | font-size: 14px
219 | font-weight: normal
220 | + a
221 | margin-left: 0px !important
222 | margin-bottom: 0
223 | a + a
224 | color: #000
225 | font: 14px Helvetica
226 | text-overflow: ellipsis
227 | white-space: nowrap
228 | overflow: hidden
229 | display: block
230 | margin: 0
231 | padding: 0
232 | + a
233 | color: #666
234 | font: 13px Helvetica
235 | margin: 0
236 | text-overflow: ellipsis
237 | white-space: nowrap
238 | overflow: hidden
239 | display: block
240 | padding: 0
241 | &.img a +
242 | a + a + a, small + a + a + a
243 | color: #666
244 | font: 13px Helvetica
245 | margin: 0
246 | text-overflow: ellipsis
247 | white-space: nowrap
248 | overflow: hidden
249 | display: block
250 | padding: 0
251 | &.form li
252 | padding: 7px 10px
253 | &.error
254 | border: 2px solid red
255 | + li.error
256 | border-top: 0
257 | li
258 | input
259 | &[type="text"], &[type="password"]
260 | color: #777
261 | background: transparent url(../.png)
262 | border: 0
263 | font: normal 17px Helvetica
264 | padding: 0
265 | display: inline-block
266 | margin-left: 0px
267 | width: 100%
268 | -webkit-appearance: textarea
269 | textarea, select
270 | color: #777
271 | background: transparent url(../.png)
272 | border: 0
273 | font: normal 17px Helvetica
274 | padding: 0
275 | display: inline-block
276 | margin-left: 0px
277 | width: 100%
278 | -webkit-appearance: textarea
279 | textarea
280 | height: 120px
281 | padding: 0
282 | text-indent: -2px
283 | select
284 | text-indent: 0px
285 | background: transparent url(../i/themes/jqt/img/chevron.png) no-repeat right center
286 | -webkit-appearance: textfield
287 | margin-left: -6px
288 | width: 104%
289 | input
290 | &[type="checkbox"], &[type="radio"]
291 | margin: 0
292 | padding: 10px 10px
293 | &[type="checkbox"]:after, &[type="radio"]:after
294 | content: attr(title)
295 | font: 17px Helvetica
296 | display: block
297 | width: 246px
298 | color: #777
299 | margin: -12px 0 0 17px
300 | small
301 | color: #64c114
302 | font: 17px Helvetica
303 | text-align: right
304 | text-overflow: ellipsis
305 | white-space: nowrap
306 | overflow: hidden
307 | display: block
308 | width: 23%
309 | float: right
310 | padding: 0
311 | &.arrow small
312 | padding: 0 15px
313 | small.counter
314 | font-size: 17px
315 | line-height: 13px
316 | font-weight: bold
317 | background: rgba(0, 0, 0, 0.15)
318 | color: #fff
319 | -webkit-border-radius: 11px
320 | padding: 4px 10px 5px 10px
321 | display: block
322 | width: auto
323 | margin-top: -22px
324 | -webkit-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0
325 | &.arrow small.counter
326 | margin-right: 15px
327 | &.individual
328 | border: 0
329 | background: none
330 | clear: both
331 | overflow: hidden
332 | padding-bottom: 3px
333 | -webkit-box-shadow: none
334 | li
335 | background: #4c4d4e
336 | border: 1px solid #333
337 | font-size: 14px
338 | text-align: center
339 | -webkit-border-radius: 8px
340 | -webkit-box-sizing: border-box
341 | width: 48%
342 | float: left
343 | display: block
344 | padding: 11px 10px 14px 10px
345 | -webkit-box-shadow: rgba(0, 0, 0, 0.2) 1px 1px 3px
346 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142))
347 | + li
348 | float: right
349 | a
350 | color: #fff
351 | line-height: 16px
352 | margin: -11px -10px -14px -10px
353 | padding: 11px 10px 14px 10px
354 | -webkit-border-radius: 8px
355 |
356 | /*
357 | *@end
358 | /* @group Forms
359 |
360 | /* @end
361 | /* @group Mini Label
362 |
363 | /* @end
364 | /* @group Individual
365 |
366 | /* @end
367 | /* @group Toggle
368 |
369 | .toggle
370 | width: 94px
371 | position: relative
372 | height: 27px
373 | display: block
374 | overflow: hidden
375 | float: right
376 | input[type="checkbox"]
377 | &:checked
378 | left: 0px
379 | -webkit-appearance: textarea
380 | -webkit-border-radius: 5px
381 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0)
382 | -webkit-transition: left .15s
383 | background-color: transparent
384 | background: white url(../i/themes/jqt/img/on_off.png) 0 0 no-repeat
385 | border: 0
386 | height: 27px
387 | left: -55px
388 | margin: 0
389 | overflow: hidden
390 | position: absolute
391 | top: 0
392 | width: 149px
393 |
394 | /* @end
395 | /* @group Info
396 |
397 | .info
398 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#cccccc), to(#aaaaaa), color-stop(0.6, #cccccc))
399 | font-size: 12px
400 | line-height: 16px
401 | text-align: center
402 | text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0
403 | color: #444
404 | padding: 15px
405 | border-top: 1px solid rgba(255, 255, 255, 0.2)
406 | font-weight: bold
407 |
408 | /* @end
409 | /* @group Edge to edge
410 |
411 | ul.edgetoedge
412 | border-width: 1px 0
413 | margin: 0
414 | padding: 0
415 | li
416 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#1e1f21), to(#272729))
417 | border-bottom: 2px solid #000
418 | border-top: 1px solid #4a4b4d
419 | font-size: 20px
420 | margin-bottom: -1px
421 | &.sep
422 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0.5)))
423 | border-bottom: 1px solid #111113
424 | border-top: 1px solid #666
425 | color: #3e9ac3
426 | font-size: 16px
427 | margin: 1px 0 0 0
428 | padding: 2px 10px
429 | text-shadow: #000 0 1px 0
430 | em
431 | font-weight: normal
432 | font-style: normal
433 |
434 | /* @end
435 | /* @group Plastic
436 |
437 | #plastic
438 | background: #17181a
439 |
440 | ul
441 | &.plastic
442 | background: #17181a
443 | color: #aaa
444 | font: bold 18px Helvetica
445 | margin: 0
446 | padding: 0
447 | border-width: 0 0 1px 0
448 | li
449 | border-width: 1px 0
450 | border-style: solid
451 | border-top-color: #222
452 | border-bottom-color: #000
453 | color: #666
454 | list-style-type: none
455 | overflow: hidden
456 | padding: 10px 10px 10px 10px
457 | a.active.loading
458 | background-image: url(../i/themes/jqt/img/loading.gif)
459 | background-position: 95% center
460 | background-repeat: no-repeat
461 | small
462 | color: #888
463 | font-size: 13px
464 | font-weight: bold
465 | line-height: 24px
466 | text-transform: uppercase
467 | &:nth-child(odd)
468 | background-color: #1c1c1f
469 | &.arrow
470 | background-image: url(../i/themes/jqt/img/chevron.png)
471 | background-position: right center
472 | background-repeat: no-repeat
473 | a.active
474 | background-image: url(../i/themes/jqt/img/chevron.png)
475 | background-position: right center
476 | background-repeat: no-repeat
477 | &.forward
478 | background-image: url(../i/themes/jqt/img/chevron_circle.png)
479 | background-position: right center
480 | background-repeat: no-repeat
481 | a.active
482 | background-image: url(../i/themes/jqt/img/chevron_circle.png)
483 | background-position: right center
484 | background-repeat: no-repeat
485 | &.metal
486 | border-bottom: 0
487 | border-left: 0
488 | border-right: 0
489 | border-top: 0
490 | margin: 0
491 | li
492 | background-image: none
493 | border-top: 1px solid #fff
494 | border-bottom: 1px solid #666
495 | font-size: 26px
496 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(238, 238, 238, 1)), to(rgba(156, 158, 160, 1)))
497 | a
498 | line-height: 26px
499 | margin: 0
500 | text-shadow: #fff 0 1px 0
501 | padding: 13px 0
502 | em
503 | display: block
504 | font-size: 14px
505 | font-style: normal
506 | color: #444
507 | width: 50%
508 | line-height: 14px
509 | &.active
510 | color: rgb(0, 0, 0)
511 | small
512 | float: right
513 | position: relative
514 | margin-top: 10px
515 | font-weight: bold
516 | &.arrow
517 | background-image: url(../i/themes/jqt/img/chevron.png)
518 | background-position: right center
519 | background-repeat: no-repeat
520 | background-image: url(../i/themes/jqt/img/chevron.png), -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(238, 238, 238, 1)), to(rgba(156, 158, 160, 1)))
521 | background-repeat: no-repeat
522 | background-position: right center
523 | a small
524 | padding-right: 15px
525 | line-height: 17px
526 |
527 | /* @group Metal
528 |
529 | /* @end
530 |
--------------------------------------------------------------------------------
/c/sass/board.ipad.sass:
--------------------------------------------------------------------------------
1 | $large: 45px
2 | $medium: 30px
3 | $small: 15px
4 |
5 | $zoom_in_size: $large
6 |
7 | .board.size19
8 | $full_cells: 19
9 | $zoom_out_size: $medium
10 | $zoom_out_cells: $full_cells
11 | $zoom_in_cells: 12
12 | &.zoomin
13 | margin-left: -0.5 * $zoom_in_cells * $zoom_in_size
14 | width: $zoom_in_size * $zoom_in_cells
15 | .intersections
16 | height: $zoom_in_size * $zoom_in_cells
17 | .row
18 | height: $zoom_in_size
19 | width: $zoom_in_size * $full_cells
20 | img
21 | height: $zoom_in_size
22 | width: $zoom_in_size
23 | &.zoomout
24 | margin-left: -0.5 * $zoom_out_cells *$zoom_out_size
25 | width: $zoom_in_size * $zoom_in_cells
26 | .intersections
27 | height: $zoom_in_size * $zoom_in_cells
28 | .row
29 | height: $zoom_out_size
30 | width: $zoom_out_size * $zoom_out_cells
31 | img
32 | height: $zoom_out_size
33 | width: $zoom_out_size
34 |
35 | .board.size17
36 | $full_cells: 17
37 | $zoom_out_size: $large
38 | $zoom_out_cells: $full_cells
39 | $zoom_in_cells: 17
40 | &.zoomin
41 | margin-left: -0.5 * $zoom_in_cells * $zoom_in_size
42 | width: $zoom_in_size * $zoom_in_cells
43 | .intersections
44 | height: $zoom_in_size * $zoom_in_cells
45 | .row
46 | height: $zoom_in_size
47 | width: $zoom_in_size * $full_cells
48 | img
49 | height: $zoom_in_size
50 | width: $zoom_in_size
51 | &.zoomout
52 | margin-left: -0.5 * $zoom_out_cells *$zoom_out_size
53 | width: $zoom_in_size * $zoom_in_cells
54 | .intersections
55 | height: $zoom_in_size * $zoom_in_cells
56 | .row
57 | height: $zoom_out_size
58 | width: $zoom_out_size * $zoom_out_cells
59 | img
60 | height: $zoom_out_size
61 | width: $zoom_out_size
62 |
63 | .board.size15
64 | $full_cells: 15
65 | $zoom_out_size: $large
66 | $zoom_out_cells: $full_cells
67 | $zoom_in_cells: 15
68 | &.zoomin
69 | margin-left: -0.5 * $zoom_in_cells * $zoom_in_size
70 | width: $zoom_in_size * $zoom_in_cells
71 | .intersections
72 | height: $zoom_in_size * $zoom_in_cells
73 | .row
74 | height: $zoom_in_size
75 | width: $zoom_in_size * $full_cells
76 | img
77 | height: $zoom_in_size
78 | width: $zoom_in_size
79 | &.zoomout
80 | margin-left: -0.5 * $zoom_out_cells *$zoom_out_size
81 | width: $zoom_in_size * $zoom_in_cells
82 | .intersections
83 | height: $zoom_in_size * $zoom_in_cells
84 | .row
85 | height: $zoom_out_size
86 | width: $zoom_out_size * $zoom_out_cells
87 | img
88 | height: $zoom_out_size
89 | width: $zoom_out_size
90 |
91 | .board.size13
92 | $full_cells: 13
93 | $zoom_out_size: $large
94 | $zoom_out_cells: $full_cells
95 | $zoom_in_cells: 13
96 | &.zoomin
97 | margin-left: -0.5 * $zoom_in_cells * $zoom_in_size
98 | width: $zoom_in_size * $zoom_in_cells
99 | .intersections
100 | height: $zoom_in_size * $zoom_in_cells
101 | .row
102 | height: $zoom_in_size
103 | width: $zoom_in_size * $full_cells
104 | img
105 | height: $zoom_in_size
106 | width: $zoom_in_size
107 | &.zoomout
108 | margin-left: -0.5 * $zoom_out_cells *$zoom_out_size
109 | width: $zoom_in_size * $zoom_in_cells
110 | .intersections
111 | height: $zoom_in_size * $zoom_in_cells
112 | .row
113 | height: $zoom_out_size
114 | width: $zoom_out_size * $zoom_out_cells
115 | img
116 | height: $zoom_out_size
117 | width: $zoom_out_size
118 |
119 | .board.size11
120 | $full_cells: 11
121 | $zoom_out_size: $large
122 | $zoom_out_cells: $full_cells
123 | $zoom_in_cells: 11
124 | &.zoomin
125 | margin-left: -0.5 * $zoom_in_cells * $zoom_in_size
126 | width: $zoom_in_size * $zoom_in_cells
127 | .intersections
128 | height: $zoom_in_size * $zoom_in_cells
129 | .row
130 | height: $zoom_in_size
131 | width: $zoom_in_size * $full_cells
132 | img
133 | height: $zoom_in_size
134 | width: $zoom_in_size
135 | &.zoomout
136 | margin-left: -0.5 * $zoom_out_cells *$zoom_out_size
137 | width: $zoom_in_size * $zoom_in_cells
138 | .intersections
139 | height: $zoom_in_size * $zoom_in_cells
140 | .row
141 | height: $zoom_out_size
142 | width: $zoom_out_size * $zoom_out_cells
143 | img
144 | height: $zoom_out_size
145 | width: $zoom_out_size
146 |
147 | .board.size9
148 | $full_cells: 9
149 | $zoom_out_size: $large
150 | $zoom_out_cells: $full_cells
151 | $zoom_in_cells: 9
152 | &.zoomin
153 | margin-left: -0.5 * $zoom_in_cells * $zoom_in_size
154 | width: $zoom_in_size * $zoom_in_cells
155 | .intersections
156 | height: $zoom_in_size * $zoom_in_cells
157 | .row
158 | height: $zoom_in_size
159 | width: $zoom_in_size * $full_cells
160 | img
161 | height: $zoom_in_size
162 | width: $zoom_in_size
163 | &.zoomout
164 | margin-left: -0.5 * $zoom_out_cells *$zoom_out_size
165 | width: $zoom_in_size * $zoom_in_cells
166 | .intersections
167 | height: $zoom_in_size * $zoom_in_cells
168 | .row
169 | height: $zoom_out_size
170 | width: $zoom_out_size * $zoom_out_cells
171 | img
172 | height: $zoom_out_size
173 | width: $zoom_out_size
174 |
175 | .board
176 | overflow: hidden
177 | position: relative
178 | left: 50%
179 | .intersections
180 | position: relative
181 | background: black
182 | .intersection
183 | :display inline-block
184 | .row
185 | &:first-child
186 | .intersection
187 | &:first-child
188 | &.black
189 | background: url('../i/board/temporary/tile1nw.png')
190 | &.playable_black,&.playable_white
191 | background: url('../i/board/temporary/tile1nwd.png') !important
192 | &.latest
193 | background: url('../i/board/temporary/tile1nwd.png') !important
194 | &.white
195 | background: url('../i/board/temporary/tile2nw.png')
196 | &.playable_black,&.playable_white
197 | background: url('../i/board/temporary/tile2nwd.png') !important
198 | &.latest
199 | background: url('../i/board/temporary/tile2nwd.png') !important
200 | &:not(.black):not(.white)
201 | background: url('../i/board/temporary/tile0nw.png')
202 | &:not(:first-child):not(:last-child)
203 | &.black
204 | background: url('../i/board/temporary/tile1n.png')
205 | &.playable_black,&.playable_white
206 | background: url('../i/board/temporary/tile1nd.png') !important
207 | &.latest
208 | background: url('../i/board/temporary/tile1nd.png') !important
209 | &.white
210 | background: url('../i/board/temporary/tile2n.png')
211 | &.playable_black,&.playable_white
212 | background: url('../i/board/temporary/tile2nd.png') !important
213 | &.latest
214 | background: url('../i/board/temporary/tile2nd.png') !important
215 | &:not(.black):not(.white)
216 | background: url('../i/board/temporary/tile0n.png')
217 | &:last-child
218 | &.black
219 | background: url('../i/board/temporary/tile1ne.png')
220 | &.playable_black,&.playable_white
221 | background: url('../i/board/temporary/tile1ned.png') !important
222 | &.latest
223 | background: url('../i/board/temporary/tile1ned.png') !important
224 | &.white
225 | background: url('../i/board/temporary/tile2ne.png')
226 | &.playable_black,&.playable_white
227 | background: url('../i/board/temporary/tile2ned.png') !important
228 | &.latest
229 | background: url('../i/board/temporary/tile2ned.png') !important
230 | &:not(.black):not(.white)
231 | background: url('../i/board/temporary/tile0ne.png')
232 | &:not(:first-child):not(:last-child)
233 | .intersection
234 | &:first-child
235 | &.black
236 | background: url('../i/board/temporary/tile1w.png')
237 | &.playable_black,&.playable_white
238 | background: url('../i/board/temporary/tile1wd.png') !important
239 | &.latest
240 | background: url('../i/board/temporary/tile1wd.png') !important
241 | &.white
242 | background: url('../i/board/temporary/tile2w.png')
243 | &.playable_black,&.playable_white
244 | background: url('../i/board/temporary/tile2wd.png') !important
245 | &.latest
246 | background: url('../i/board/temporary/tile2wd.png') !important
247 | &:not(.black):not(.white)
248 | background: url('../i/board/temporary/tile0w.png')
249 | &:not(:first-child):not(:last-child)
250 | &.black
251 | background: url('../i/board/temporary/tile1.png')
252 | &.playable_black,&.playable_white
253 | background: url('../i/board/temporary/tile1d.png') !important
254 | &.latest
255 | background: url('../i/board/temporary/tile1d.png') !important
256 | &.white
257 | background: url('../i/board/temporary/tile2.png')
258 | &.playable_black,&.playable_white
259 | background: url('../i/board/temporary/tile2d.png') !important
260 | &.latest
261 | background: url('../i/board/temporary/tile2d.png') !important
262 | &:last-child
263 | &.black
264 | background: url('../i/board/temporary/tile1e.png')
265 | &.playable_black,&.playable_white
266 | background: url('../i/board/temporary/tile1ed.png') !important
267 | &.latest
268 | background: url('../i/board/temporary/tile1ed.png') !important
269 | &.white
270 | background: url('../i/board/temporary/tile2e.png')
271 | &.playable_black,&.playable_white
272 | background: url('../i/board/temporary/tile2ed.png') !important
273 | &.latest
274 | background: url('../i/board/temporary/tile2ed.png') !important
275 | &:not(.black):not(.white)
276 | background: url('../i/board/temporary/tile0e.png')
277 | &:last-child
278 | .intersection
279 | &:first-child
280 | &.black
281 | background: url('../i/board/temporary/tile1sw.png')
282 | &.playable_black,&.playable_white
283 | background: url('../i/board/temporary/tile1swd.png') !important
284 | &.latest
285 | background: url('../i/board/temporary/tile1swd.png') !important
286 | &.white
287 | background: url('../i/board/temporary/tile2sw.png')
288 | &.playable_black,&.playable_white
289 | background: url('../i/board/temporary/tile2swd.png') !important
290 | &.latest
291 | background: url('../i/board/temporary/tile2swd.png') !important
292 | &:not(.black):not(.white)
293 | background: url('../i/board/temporary/tile0sw.png')
294 | &:not(:first-child):not(:last-child)
295 | &.black
296 | background: url('../i/board/temporary/tile1s.png')
297 | &.playable_black,&.playable_white
298 | background: url('../i/board/temporary/tile1sd.png') !important
299 | &.latest
300 | background: url('../i/board/temporary/tile1sd.png') !important
301 | &.white
302 | background: url('../i/board/temporary/tile2s.png')
303 | &.playable_black,&.playable_white
304 | background: url('../i/board/temporary/tile2sd.png') !important
305 | &.latest
306 | background: url('../i/board/temporary/tile2sd.png') !important
307 | &:not(.black):not(.white)
308 | background: url('../i/board/temporary/tile0s.png')
309 | &:last-child
310 | &.black
311 | background: url('../i/board/temporary/tile1se.png')
312 | &.playable_black,&.playable_white
313 | background: url('../i/board/temporary/tile1sed.png') !important
314 | &.latest
315 | background: url('../i/board/temporary/tile1sed.png') !important
316 | &.white
317 | background: url('../i/board/temporary/tile2se.png')
318 | &.playable_black,&.playable_white
319 | background: url('../i/board/temporary/tile2sed.png') !important
320 | &.latest
321 | background: url('../i/board/temporary/tile2sed.png') !important
322 | &:not(.black):not(.white)
323 | background: url('../i/board/temporary/tile0se.png')
324 | .star
325 | &.black
326 | background: url('../i/board/temporary/tile1.png')
327 | &.playable_black,&.playable_white
328 | background: url('../i/board/temporary/tile1d.png') !important
329 | &.latest
330 | background: url('../i/board/temporary/tile1d.png') !important
331 | &.white
332 | background: url('../i/board/temporary/tile2.png')
333 | &.playable_black,&.playable_white
334 | background: url('../i/board/temporary/tile2d.png') !important
335 | &.latest
336 | background: url('../i/board/temporary/tile2d.png') !important
337 | &:not(.black):not(.white)
338 | background: url('../i/board/temporary/tile0c.png')
339 | &.playable_black,&.playable_white
340 | BEFORE: URL('../i/board/temporary/tile0c.png')
341 |
342 | @mixin interior($corner,$middle)
343 | .row
344 | &:nth-child(#{$corner}),&:nth-child(#{$middle}),&:nth-last-child(#{$corner})
345 | .intersection:not(.black):not(.white)
346 | &:nth-child(#{$corner}),&:nth-child(#{$middle}),&:nth-last-child(#{$corner})
347 | background: url('../i/board/temporary/tile0c.png')
348 | &:not(:nth-child(#{$corner})):not(:nth-child(#{$middle})):not(:nth-last-child(#{$corner})):not(:first-child):not(:last-child)
349 | background: url('../i/board/temporary/tile0.png')
350 | &:not(:nth-child(#{$corner})):not(:nth-child(#{$middle})):not(:nth-last-child(#{$corner})):not(:first-child):not(:last-child)
351 | .intersection:not(.black):not(.white):not(:first-child):not(:last-child)
352 | background: url('../i/board/temporary/tile0.png')
353 |
354 | .board
355 | &.size9
356 | @include interior(3,5)
357 | &.size11
358 | @include interior(3,6)
359 | &.size13
360 | @include interior(4,7)
361 | &.size15
362 | @include interior(4,8)
363 | &.size17
364 | @include interior(4,9)
365 | &.size19
366 | @include interior(4,10)
367 |
368 | .move.play.black
369 | .intersection.playable_black
370 | cursor: pointer
371 | .move.play.white
372 | .intersection.playable_white
373 | cursor: pointer
374 |
375 | .intersection
376 | -o-background-size: 100%
377 | -webkit-background-size: 100%
378 | -khtml-background-size: 100%
379 | -moz-background-size: 100%
380 |
381 | .board
382 | .head
383 | .guest
384 | display: inline
385 | left: 100%
386 | margin-left: -100%
387 |
388 | $stonediameter: 30px
389 |
390 | .head,.foot
391 | height: $stonediameter
392 | padding: 5px 5px 5px 5px
393 |
394 | .profile
395 | .move.play
396 | .board
397 | .head
398 | .guest
399 | display: inline
400 | float: right
401 | -webkit-transform: rotate(180deg)
402 | .foot
403 | .host
404 | display: inline
405 | float: right
406 | .guest
407 | display: none
408 |
409 | .landscape
410 | .move.play
411 | .board
412 | .guest
413 | display: none
414 | .foot
415 | .host
416 | display: inline
417 | float: left
418 | .guest
419 | display: inline
420 | float: right
--------------------------------------------------------------------------------
/c/jqtouch.ipad.customized.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: black;
3 | color: #dddddd; }
4 | body > * {
5 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#333333), to(#5e5e65)); }
6 |
7 | h1, h2 {
8 | font: bold 18px Helvetica;
9 | text-shadow: rgba(255, 255, 255, 0.2) 0 1px 1px;
10 | color: black;
11 | margin: 10px 20px 5px; }
12 |
13 | /* @group Toolbar */
14 | .toolbar {
15 | -webkit-box-sizing: border-box;
16 | border-bottom: 1px solid black;
17 | padding: 10px;
18 | height: 45px;
19 | background: url(../i/themes/jqt/img/toolbar.png) black repeat-x;
20 | position: relative; }
21 |
22 | .black-translucent .toolbar {
23 | margin-top: 20px; }
24 |
25 | .toolbar > h1 {
26 | position: absolute;
27 | overflow: hidden;
28 | left: 50%;
29 | top: 10px;
30 | line-height: 1em;
31 | margin: 1px 0 0 -192px;
32 | height: 40px;
33 | font-size: 20px;
34 | width: 384px;
35 | font-weight: bold;
36 | text-shadow: black 0 -1px 1px;
37 | text-align: center;
38 | text-overflow: ellipsis;
39 | white-space: nowrap;
40 | color: white; }
41 |
42 | body.landscape .toolbar > h1 {
43 | margin-left: -256px;
44 | width: 512px; }
45 |
46 | .button, .back, .cancel, .add {
47 | position: absolute;
48 | overflow: hidden;
49 | top: 8px;
50 | right: 10px;
51 | margin: 0;
52 | border-width: 0 5px;
53 | padding: 0 3px;
54 | width: auto;
55 | height: 30px;
56 | line-height: 30px;
57 | font-family: inherit;
58 | font-size: 12px;
59 | font-weight: bold;
60 | color: white;
61 | text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0;
62 | text-overflow: ellipsis;
63 | text-decoration: none;
64 | white-space: nowrap;
65 | background: none;
66 | -webkit-border-image: url(../i/themes/jqt/img/button.png) 0 5 0 5; }
67 |
68 | .blueButton {
69 | -webkit-border-image: url(../i/themes/jqt/img/blueButton.png) 0 5 0 5;
70 | border-width: 0 5px; }
71 |
72 | .back {
73 | left: 6px;
74 | right: auto;
75 | padding: 0;
76 | max-width: 55px;
77 | border-width: 0 8px 0 14px;
78 | -webkit-border-image: url(../i/themes/jqt/img/back_button.png) 0 8 0 14; }
79 | .back.active {
80 | -webkit-border-image: url(../i/themes/jqt/img/back_button_clicked.png) 0 8 0 14;
81 | color: #aaaaaa; }
82 |
83 | .leftButton, .cancel {
84 | left: 6px;
85 | right: auto; }
86 |
87 | .add {
88 | font-size: 24px;
89 | line-height: 24px;
90 | font-weight: bold; }
91 |
92 | .whiteButton, .grayButton {
93 | display: block;
94 | border-width: 0 12px;
95 | padding: 10px;
96 | text-align: center;
97 | font-size: 20px;
98 | font-weight: bold;
99 | text-decoration: inherit;
100 | color: inherit; }
101 |
102 | .whiteButton {
103 | -webkit-border-image: url(../i/themes/jqt/img/whiteButton.png) 0 12 0 12;
104 | text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0; }
105 |
106 | .grayButton {
107 | -webkit-border-image: url(../i/themes/jqt/img/grayButton.png) 0 12 0 12;
108 | color: white; }
109 |
110 | /* @end */
111 | /* @group Lists */
112 | h1 + ul, h2 + ul, h3 + ul, h4 + ul, h5 + ul, h6 + ul {
113 | margin-top: 0; }
114 |
115 | ul {
116 | color: #aaaaaa;
117 | border: 1px solid #333333;
118 | font: bold 18px Helvetica;
119 | padding: 0;
120 | margin: 15px 10px 17px 10px; }
121 | ul.rounded {
122 | -webkit-border-radius: 8px;
123 | -webkit-box-shadow: rgba(0, 0, 0, 0.3) 1px 1px 3px; }
124 | ul.rounded li:first-child {
125 | border-top: 0;
126 | -webkit-border-top-left-radius: 8px;
127 | -webkit-border-top-right-radius: 8px; }
128 | ul.rounded li:first-child a {
129 | border-top: 0;
130 | -webkit-border-top-left-radius: 8px;
131 | -webkit-border-top-right-radius: 8px; }
132 | ul.rounded li:last-child {
133 | -webkit-border-bottom-left-radius: 8px;
134 | -webkit-border-bottom-right-radius: 8px; }
135 | ul.rounded li:last-child a {
136 | -webkit-border-bottom-left-radius: 8px;
137 | -webkit-border-bottom-right-radius: 8px; }
138 | ul li {
139 | color: #666666;
140 | border-top: 1px solid #333333;
141 | border-bottom: #555858;
142 | list-style-type: none;
143 | padding: 10px 10px 10px 10px;
144 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142));
145 | overflow: hidden; }
146 | ul li.arrow {
147 | background-image: url(../i/themes/jqt/img/chevron.png), -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142));
148 | background-position: right center;
149 | background-repeat: no-repeat; }
150 | ul li.forward {
151 | background-image: url(../i/themes/jqt/img/chevron_circle.png), -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142));
152 | background-position: right center;
153 | background-repeat: no-repeat; }
154 | ul li a {
155 | color: white;
156 | text-decoration: none;
157 | text-overflow: ellipsis;
158 | white-space: nowrap;
159 | overflow: hidden;
160 | display: block;
161 | padding: 12px 10px 12px 10px;
162 | margin: -10px;
163 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
164 | text-shadow: rgba(0, 0, 0, 0.2) 0 1px 1px; }
165 |
166 | /* universal links on list */
167 | li.img a + a {
168 | color: white;
169 | text-decoration: none;
170 | text-overflow: ellipsis;
171 | white-space: nowrap;
172 | overflow: hidden;
173 | display: block;
174 | padding: 12px 10px 12px 10px;
175 | margin: -10px;
176 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
177 | text-shadow: rgba(0, 0, 0, 0.2) 0 1px 1px; }
178 |
179 | ul li a.active, ul li a.button {
180 | background-color: #53b401;
181 | color: white; }
182 | ul li a.active.loading {
183 | background-image: url(../i/themes/jqt/img/loading.gif);
184 | background-position: 95% center;
185 | background-repeat: no-repeat; }
186 | ul li.arrow a.active {
187 | background-image: url(../i/themes/jqt/img/chevron.png);
188 | background-position: right center;
189 | background-repeat: no-repeat; }
190 | ul li.forward a.active {
191 | background-image: url(../i/themes/jqt/img/chevron_circle.png);
192 | background-position: right center;
193 | background-repeat: no-repeat; }
194 | ul li.img a + a {
195 | margin: -10px 10px -20px -5px;
196 | font-size: 17px;
197 | font-weight: bold; }
198 | ul li.img a + a + a {
199 | font-size: 14px;
200 | font-weight: normal;
201 | margin-left: -10px;
202 | margin-bottom: -10px;
203 | margin-top: 0; }
204 | ul li.img a + small + a {
205 | margin-left: -5px; }
206 | ul li.img a + small + a + a {
207 | margin-left: -10px;
208 | margin-top: -20px;
209 | margin-bottom: -10px;
210 | font-size: 14px;
211 | font-weight: normal; }
212 | ul li.img a + small + a + a + a {
213 | margin-left: 0px !important;
214 | margin-bottom: 0; }
215 | ul li a + a {
216 | color: black;
217 | font: 14px Helvetica;
218 | text-overflow: ellipsis;
219 | white-space: nowrap;
220 | overflow: hidden;
221 | display: block;
222 | margin: 0;
223 | padding: 0; }
224 | ul li a + a + a {
225 | color: #666666;
226 | font: 13px Helvetica;
227 | margin: 0;
228 | text-overflow: ellipsis;
229 | white-space: nowrap;
230 | overflow: hidden;
231 | display: block;
232 | padding: 0; }
233 | ul li.img a + a + a + a, ul li.img a + small + a + a + a {
234 | color: #666666;
235 | font: 13px Helvetica;
236 | margin: 0;
237 | text-overflow: ellipsis;
238 | white-space: nowrap;
239 | overflow: hidden;
240 | display: block;
241 | padding: 0; }
242 | ul.form li {
243 | padding: 7px 10px; }
244 | ul.form li.error {
245 | border: 2px solid red; }
246 | ul.form li.error + li.error {
247 | border-top: 0; }
248 | ul li input[type="text"], ul li input[type="password"] {
249 | color: #777777;
250 | background: transparent /* url(../.png) */;
251 | border: 0;
252 | font: normal 17px Helvetica;
253 | padding: 0;
254 | display: inline-block;
255 | margin-left: 0px;
256 | width: 100%;
257 | -webkit-appearance: textarea; }
258 | ul li textarea, ul li select {
259 | color: #777777;
260 | background: transparent /* url(../.png) */;
261 | border: 0;
262 | font: normal 17px Helvetica;
263 | padding: 0;
264 | display: inline-block;
265 | margin-left: 0px;
266 | width: 100%;
267 | -webkit-appearance: textarea; }
268 | ul li textarea {
269 | height: 120px;
270 | padding: 0;
271 | text-indent: -2px; }
272 | ul li select {
273 | text-indent: 0px;
274 | background: transparent url(../i/themes/jqt/img/chevron.png) no-repeat right center;
275 | -webkit-appearance: textfield;
276 | margin-left: -6px;
277 | width: 104%; }
278 | ul li input[type="checkbox"], ul li input[type="radio"] {
279 | margin: 0;
280 | padding: 10px 10px; }
281 | ul li input[type="checkbox"]:after, ul li input[type="radio"]:after {
282 | content: attr(title);
283 | font: 17px Helvetica;
284 | display: block;
285 | width: 246px;
286 | color: #777777;
287 | margin: -12px 0 0 17px; }
288 | ul li small {
289 | color: #64c114;
290 | font: 17px Helvetica;
291 | text-align: right;
292 | text-overflow: ellipsis;
293 | white-space: nowrap;
294 | overflow: hidden;
295 | display: block;
296 | width: 23%;
297 | float: right;
298 | padding: 0; }
299 | ul li.arrow small {
300 | padding: 0 15px; }
301 | ul li small.counter {
302 | font-size: 17px;
303 | line-height: 13px;
304 | font-weight: bold;
305 | background: rgba(0, 0, 0, 0.15);
306 | color: white;
307 | -webkit-border-radius: 11px;
308 | padding: 4px 10px 5px 10px;
309 | display: block;
310 | width: auto;
311 | margin-top: -22px;
312 | -webkit-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0; }
313 | ul li.arrow small.counter {
314 | margin-right: 15px; }
315 | ul.individual {
316 | border: 0;
317 | background: none;
318 | clear: both;
319 | overflow: hidden;
320 | padding-bottom: 3px;
321 | -webkit-box-shadow: none; }
322 | ul.individual li {
323 | background: #4c4d4e;
324 | border: 1px solid #333333;
325 | font-size: 14px;
326 | text-align: center;
327 | -webkit-border-radius: 8px;
328 | -webkit-box-sizing: border-box;
329 | width: 48%;
330 | float: left;
331 | display: block;
332 | padding: 11px 10px 14px 10px;
333 | -webkit-box-shadow: rgba(0, 0, 0, 0.2) 1px 1px 3px;
334 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142)); }
335 | ul.individual li + li {
336 | float: right; }
337 | ul.individual li a {
338 | color: white;
339 | line-height: 16px;
340 | margin: -11px -10px -14px -10px;
341 | padding: 11px 10px 14px 10px;
342 | -webkit-border-radius: 8px; }
343 |
344 | /* *@end */
345 | /* @group Forms */
346 | /* @end */
347 | /* @group Mini Label */
348 | /* @end */
349 | /* @group Individual */
350 | /* @end */
351 | /* @group Toggle */
352 | .toggle {
353 | width: 94px;
354 | position: relative;
355 | height: 27px;
356 | display: block;
357 | overflow: hidden;
358 | float: right; }
359 | .toggle input[type="checkbox"] {
360 | -webkit-appearance: textarea;
361 | -webkit-border-radius: 5px;
362 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
363 | -webkit-transition: left 0.15s;
364 | background-color: transparent;
365 | background: white url(../i/themes/jqt/img/on_off.png) 0 0 no-repeat;
366 | border: 0;
367 | height: 27px;
368 | left: -55px;
369 | margin: 0;
370 | overflow: hidden;
371 | position: absolute;
372 | top: 0;
373 | width: 149px; }
374 | .toggle input[type="checkbox"]:checked {
375 | left: 0px; }
376 |
377 | /* @end */
378 | /* @group Info */
379 | .info {
380 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#cccccc), to(#aaaaaa), color-stop(0.6, #cccccc));
381 | font-size: 12px;
382 | line-height: 16px;
383 | text-align: center;
384 | text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
385 | color: #444444;
386 | padding: 15px;
387 | border-top: 1px solid rgba(255, 255, 255, 0.2);
388 | font-weight: bold; }
389 |
390 | /* @end */
391 | /* @group Edge to edge */
392 | ul.edgetoedge {
393 | border-width: 1px 0;
394 | margin: 0;
395 | padding: 0; }
396 | ul.edgetoedge li {
397 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#1e1f21), to(#272729));
398 | border-bottom: 2px solid black;
399 | border-top: 1px solid #4a4b4d;
400 | font-size: 20px;
401 | margin-bottom: -1px; }
402 | ul.edgetoedge li.sep {
403 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0.5)));
404 | border-bottom: 1px solid #111113;
405 | border-top: 1px solid #666666;
406 | color: #3e9ac3;
407 | font-size: 16px;
408 | margin: 1px 0 0 0;
409 | padding: 2px 10px;
410 | text-shadow: black 0 1px 0; }
411 | ul.edgetoedge li em {
412 | font-weight: normal;
413 | font-style: normal; }
414 |
415 | /* @end */
416 | /* @group Plastic */
417 | #plastic {
418 | background: #17181a; }
419 |
420 | ul.plastic {
421 | background: #17181a;
422 | color: #aaaaaa;
423 | font: bold 18px Helvetica;
424 | margin: 0;
425 | padding: 0;
426 | border-width: 0 0 1px 0; }
427 | ul.plastic li {
428 | border-width: 1px 0;
429 | border-style: solid;
430 | border-top-color: #222222;
431 | border-bottom-color: black;
432 | color: #666666;
433 | list-style-type: none;
434 | overflow: hidden;
435 | padding: 10px 10px 10px 10px; }
436 | ul.plastic li a.active.loading {
437 | background-image: url(../i/themes/jqt/img/loading.gif);
438 | background-position: 95% center;
439 | background-repeat: no-repeat; }
440 | ul.plastic li small {
441 | color: #888888;
442 | font-size: 13px;
443 | font-weight: bold;
444 | line-height: 24px;
445 | text-transform: uppercase; }
446 | ul.plastic li:nth-child(odd) {
447 | background-color: #1c1c1f; }
448 | ul.plastic li.arrow {
449 | background-image: url(../i/themes/jqt/img/chevron.png);
450 | background-position: right center;
451 | background-repeat: no-repeat; }
452 | ul.plastic li.arrow a.active {
453 | background-image: url(../i/themes/jqt/img/chevron.png);
454 | background-position: right center;
455 | background-repeat: no-repeat; }
456 | ul.plastic li.forward {
457 | background-image: url(../i/themes/jqt/img/chevron_circle.png);
458 | background-position: right center;
459 | background-repeat: no-repeat; }
460 | ul.plastic li.forward a.active {
461 | background-image: url(../i/themes/jqt/img/chevron_circle.png);
462 | background-position: right center;
463 | background-repeat: no-repeat; }
464 | ul.metal {
465 | border-bottom: 0;
466 | border-left: 0;
467 | border-right: 0;
468 | border-top: 0;
469 | margin: 0; }
470 | ul.metal li {
471 | background-image: none;
472 | border-top: 1px solid white;
473 | border-bottom: 1px solid #666666;
474 | font-size: 26px;
475 | background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#eeeeee), to(#9c9ea0)); }
476 | ul.metal li a {
477 | line-height: 26px;
478 | margin: 0;
479 | text-shadow: white 0 1px 0;
480 | padding: 13px 0; }
481 | ul.metal li a em {
482 | display: block;
483 | font-size: 14px;
484 | font-style: normal;
485 | color: #444444;
486 | width: 50%;
487 | line-height: 14px; }
488 | ul.metal li a.active {
489 | color: black; }
490 | ul.metal li small {
491 | float: right;
492 | position: relative;
493 | margin-top: 10px;
494 | font-weight: bold; }
495 | ul.metal li.arrow {
496 | background-image: url(../i/themes/jqt/img/chevron.png);
497 | background-position: right center;
498 | background-repeat: no-repeat;
499 | background-image: url(../i/themes/jqt/img/chevron.png), -webkit-gradient(linear, 0% 0%, 0% 100%, from(#eeeeee), to(#9c9ea0));
500 | background-repeat: no-repeat;
501 | background-position: right center; }
502 | ul.metal li.arrow a small {
503 | padding-right: 15px;
504 | line-height: 17px; }
505 |
506 | /* @group Metal */
507 | /* @end */
508 |
--------------------------------------------------------------------------------
/j/go.js:
--------------------------------------------------------------------------------
1 | // (c) 2010 Reg Braithwaite. All rights to the entirety of the program and its parts are reserved with
2 | // the exception of specific files otherwise licensed. Other licenses apply only to the files where
3 | // they appear.
4 |
5 | ;(function ($, F, undefined) {
6 |
7 | var document_ready = function () {
8 | go.dialog = function(options) {
9 | options = $.extend(
10 | {},
11 | {
12 | title: 'hey!',
13 | yes_button: 'Ok',
14 | no_button: 'Cancel',
15 | yes_callback: F.I,
16 | no_callback: F.I
17 | },
18 | (options || {})
19 | );
20 | if (!options.no_button) {
21 | alert(options.message);
22 | options.yes_callback();
23 | }
24 | else if (confirm(options.message))
25 | options.yes_callback();
26 | else options.no_callback();
27 | };
28 | go.message = function (say, optional_button_name) {
29 | go.dialog({
30 | message: say,
31 | no_button: null
32 | });
33 | };
34 | };
35 |
36 | var playing = function (optional_board) {
37 | var move = optional_board ? optional_board.closest('.move') : $('.move.play');
38 | return move.is('.black') ? 'black' : (
39 | move.is('.white') ? 'white' : null
40 | );
41 | };
42 |
43 | var opponent = function (optional_board) {
44 | var move = optional_board ? optional_board.closest('.move') : $('.move.play');
45 | return move.is('.white') ? 'black' : (
46 | move.is('.black') ? 'white' : null
47 | );
48 | };
49 |
50 | var switch_maker = function (board) {
51 | return function(new_player) {
52 | if (new_player == undefined) new_player = opponent(board);
53 | board
54 | .closest('.move')
55 | .addClass(new_player)
56 | .removeClass(new_player == 'white' ? 'black' : 'white');
57 | };
58 | };
59 |
60 | var set_titles = function () {
61 | // $('style:last')
62 | // .text('.move.black:has(.board.play) .toolbar span.playing:before{ content: "' + go.sgf.game_info.PB + ' to play"; } ' +
63 | // '.move.white .toolbar span.playing:before{ content: "' + go.sgf.game_info.PW + ' to play"; }' );
64 | $('style#toolbar_titles')
65 | .text([
66 | '.move.re_black .toolbar h1:before{ content: "' + go.sgf.game_info.PB + ' wins"; } ',
67 | '.move.re_white .toolbar h1:before{ content: "' + go.sgf.game_info.PW + ' wins"; } ',
68 | '.move.re_draw .toolbar h1:before{ content: "Game Ended"; }',
69 |
70 | '.landscape .move.black:not(.swap):not(re_black):not(re_white):not(re_draw) .head .toolbar h1:before{ content: "'
71 | + (go.sgf.game_info.PB.match(/black/i) ? 'Black to play' : go.sgf.game_info.PB + ' to play black') + '"; } ',
72 | '.landscape .move.white:not(.swap) .head .toolbar h1:before{ content: "'
73 | + (go.sgf.game_info.PW.match(/white/i) ? 'White to play' : go.sgf.game_info.PW + ' to play white') + '"; } ',
74 | '.landscape .move.black.swap .head .toolbar h1:before{ content: "'
75 | + (go.sgf.game_info.PB.match(/black/i) ? 'Black to play or swap' : go.sgf.game_info.PB + ' to play black or swap') + '"; } ',
76 | '.landscape .move.white.swap .head .toolbar h1:before{ content: "'
77 | + (go.sgf.game_info.PW.match(/white/i) ? 'White to play or swap' : go.sgf.game_info.PW + ' to play white or swap') + '"; } '
78 | ].concat(
79 | go.sgf.game_info.PB == go.sgf.game_info.PH ? [
80 | '.profile .move.black:not(.swap):not(re_black):not(re_white):not(re_draw) .head .toolbar h1:before{ content: "'
81 | + (go.sgf.game_info.PB.match(/black/i) ? 'Black to play' : go.sgf.game_info.PB + ' to play black') + '"; } ',
82 | '.profile .move.white:not(.swap) .foot .toolbar h1:before{ content: "'
83 | + (go.sgf.game_info.PW.match(/white/i) ? 'White to play' : go.sgf.game_info.PW + ' to play white') + '"; } ',
84 | '.profile .move.black.swap .head .toolbar h1:before{ content: "'
85 | + (go.sgf.game_info.PB.match(/black/i) ? 'Black to play or swap' : go.sgf.game_info.PB + ' to play black or swap') + '"; } ',
86 | '.profile .move.white.swap .foot .toolbar h1:before{ content: "'
87 | + (go.sgf.game_info.PW.match(/white/i) ? 'White to play or swap' : go.sgf.game_info.PW + ' to play white or swap') + '"; } '
88 | ] : [
89 | '.profile .move.black:not(.swap):not(re_black):not(re_white):not(re_draw) .foot .toolbar h1:before{ content: "'
90 | + (go.sgf.game_info.PB.match(/black/i) ? 'Black to play' : go.sgf.game_info.PB + ' to play black') + '"; } ',
91 | '.profile .move.white:not(.swap) .head .toolbar h1:before{ content: "'
92 | + (go.sgf.game_info.PW.match(/white/i) ? 'White to play' : go.sgf.game_info.PW + ' to play white') + '"; } ',
93 | '.profile .move.black.swap .foot .toolbar h1:before{ content: "'
94 | + (go.sgf.game_info.PB.match(/black/i) ? 'Black to play or swap' : go.sgf.game_info.PB + ' to play black or swap') + '"; } ',
95 | '.profile .move.white.swap .head .toolbar h1:before{ content: "'
96 | + (go.sgf.game_info.PW.match(/white/i) ? 'White to play or swap' : go.sgf.game_info.PW + ' to play white or swap') + '"; } '
97 | ]
98 | ).join(' '));
99 | // $('style#bubbles')
100 | // .text([
101 | // '.landscape .move.play .board .toolbar h1:before{ } ',
102 | // '.landscape .move.white:not(.swap) .head .toolbar h1:before{ content: "'
103 | // + (go.sgf.game_info.PW.match(/white/i) ? 'White to play' : go.sgf.game_info.PW + ' to play white') + '"; } ',
104 | // '.landscape .move.black.swap .head .toolbar h1:before{ content: "'
105 | // + (go.sgf.game_info.PB.match(/black/i) ? 'Black to play or swap' : go.sgf.game_info.PB + ' to play black or swap') + '"; } ',
106 | // '.landscape .move.white.swap .head .toolbar h1:before{ content: "'
107 | // + (go.sgf.game_info.PW.match(/white/i) ? 'White to play or swap' : go.sgf.game_info.PW + ' to play white or swap') + '"; } '
108 | // ].concat(
109 | // go.sgf.game_info.PB == go.sgf.game_info.PH ? [
110 | // '.profile .move.black:not(.swap):not(re_black):not(re_white):not(re_draw) .head .toolbar h1:before{ content: "'
111 | // + (go.sgf.game_info.PB.match(/black/i) ? 'Black to play' : go.sgf.game_info.PB + ' to play black') + '"; } ',
112 | // '.profile .move.white:not(.swap) .foot .toolbar h1:before{ content: "'
113 | // + (go.sgf.game_info.PW.match(/white/i) ? 'White to play' : go.sgf.game_info.PW + ' to play white') + '"; } ',
114 | // '.profile .move.black.swap .head .toolbar h1:before{ content: "'
115 | // + (go.sgf.game_info.PB.match(/black/i) ? 'Black to play or swap' : go.sgf.game_info.PB + ' to play black or swap') + '"; } ',
116 | // '.profile .move.white.swap .foot .toolbar h1:before{ content: "'
117 | // + (go.sgf.game_info.PW.match(/white/i) ? 'White to play or swap' : go.sgf.game_info.PW + ' to play white or swap') + '"; } '
118 | // ] : [
119 | // '.profile .move.black:not(.swap):not(re_black):not(re_white):not(re_draw) .foot .toolbar h1:before{ content: "'
120 | // + (go.sgf.game_info.PB.match(/black/i) ? 'Black to play' : go.sgf.game_info.PB + ' to play black') + '"; } ',
121 | // '.profile .move.white:not(.swap) .head .toolbar h1:before{ content: "'
122 | // + (go.sgf.game_info.PW.match(/white/i) ? 'White to play' : go.sgf.game_info.PW + ' to play white') + '"; } ',
123 | // '.profile .move.black.swap .foot .toolbar h1:before{ content: "'
124 | // + (go.sgf.game_info.PB.match(/black/i) ? 'Black to play or swap' : go.sgf.game_info.PB + ' to play black or swap') + '"; } ',
125 | // '.profile .move.white.swap .head .toolbar h1:before{ content: "'
126 | // + (go.sgf.game_info.PW.match(/white/i) ? 'White to play or swap' : go.sgf.game_info.PW + ' to play white or swap') + '"; } '
127 | // ]
128 | // ).join(' '));
129 | };
130 |
131 | var predoit = function (board, this_move) {
132 | return board
133 | .find('.intersection.changd')
134 | .removeClass('changed')
135 | .end();
136 | };
137 |
138 | var postdoit = function(board, this_move) {
139 |
140 | if (board.closest('.move').is(':not(.history)')) {
141 |
142 | board
143 | .K(go.referee.validate);
144 |
145 | if (!sgf.game_info.RE) {
146 | board
147 | .closest('.move')
148 | .removeClass('re_black re_white re_draw');
149 | }
150 | else if ('B' == sgf.game_info.RE[0]) {
151 | board
152 | .closest('.move')
153 | .removeClass('black white')
154 | .addClass('re_black');
155 | }
156 | else if ('W' == sgf.game_info.RE[0]) {
157 | board
158 | .closest('.move')
159 | .removeClass('black white')
160 | .addClass('re_white');
161 | }
162 | else {
163 | board
164 | .closest('.move')
165 | .removeClass('black white')
166 | .addClass('re_draw');
167 | }
168 |
169 | }
170 |
171 | return board;
172 | };
173 |
174 | var floor = function(index) {
175 | while (index >= 0 && (go.sgf.current[index]['MN'] == undefined)) {
176 | --index;
177 | }
178 | return index;
179 | };
180 |
181 | var ceiling = function(index) {
182 | while (go.sgf.current[index] && (go.sgf.current[index]['MN'] == undefined)) {
183 | ++index;
184 | }
185 | return index;
186 | };
187 |
188 | var push = function (this_move) {
189 | go.sgf.current.push(this_move);
190 | doit($('.move.play .board'), this_move);
191 | return this_move;
192 | }
193 |
194 | var pop = function () {
195 | console.error('implement me!');
196 | }
197 |
198 | var blank_stone = $('
')
199 | .attr('src', 'i/dot_clear.gif');
200 |
201 | var doit = function (board, this_move) {
202 |
203 | board = predoit(board, this_move);
204 |
205 | var switch_turns = switch_maker(board);
206 |
207 | var to_play = this_move.PL;
208 |
209 | board
210 | .find('.latest')
211 | .removeClass('latest');
212 |
213 | if (this_move.B != undefined || this_move.AB != undefined || this_move.W != undefined || this_move.AW != undefined)
214 | board
215 | .find('.changed')
216 | .removeClass('changed');
217 |
218 | var play = this_move.B;
219 | if (play && play != '') {
220 | board
221 | .find('#' + play)
222 | .addClass('black latest changed');
223 | switch_turns();
224 | }
225 | else if (play == '') {
226 | switch_turns();
227 | }
228 | else {
229 | play = this_move.W;
230 | if (play && play != '') {
231 | board
232 | .find('#' + play)
233 | .addClass('white latest changed');
234 | switch_turns();
235 | }
236 | else if (play == '') {
237 | switch_turns();
238 | }
239 | }
240 |
241 | var placements = this_move.AB;
242 | if (placements) {
243 | board
244 | .find($.map(placements.split(','), "'#' + _".lambda()).join(','))
245 | .addClass('black changed' + (this_move != go.sgf.game_info ? ' latest' : ''));
246 | }
247 | placements = this_move.AW;
248 | if (placements) {
249 | board
250 | .find($.map(placements.split(','), "'#' + _".lambda()).join(','))
251 | .addClass('white changed' + (this_move != go.sgf.game_info ? ' latest' : ''));
252 | }
253 | if (this_move.K && (this_move.W || this_move.B)) // TODO: figure out undo and stones!
254 | board
255 | .find($.map(this_move['K'].split(','), '"#" + _'.lambda()).join(','))
256 | .filter('.white')
257 | .removeClass('white')
258 | .K(function (whites) {
259 | var z = whites.size();
260 | if (z > 0) {
261 | var c = board.find('.white.captured:visible');
262 | if (c.size() > 0) {
263 | var n = parseInt(c.text());
264 | c.text('' + (n ? n + z : z));
265 | }
266 | else board.find('.white.captured').text(z);
267 | }
268 | })
269 | .end()
270 | .filter('.black')
271 | .removeClass('black')
272 | .K(function (blacks) {
273 | var z = blacks.size();
274 | if (z > 0) {
275 | var c = board.find('.black.captured:visible');
276 | if (c.size() > 0) {
277 | var n = parseInt(c.text());
278 | c.text('' + (n ? n + z : z));
279 | }
280 | else board.find('.black.captured').text(z);
281 | }
282 | })
283 | .end()
284 | .addClass('changed');
285 |
286 | if (to_play)
287 | board
288 | .closest('.move')
289 | .addClass(to_play);
290 |
291 | if (go.sgf.game_info.HA) {
292 | var placed = 0;
293 | $.each(go.sgf.current, function (i, that_move) {
294 | if (that_move.AB)
295 | placed = placed + that_move.AB.split(',').length;
296 | });
297 | if (placed < go.sgf.game_info.HA) {
298 | board
299 | .removeClass('play')
300 | .addClass('place')
301 | .end();
302 | }
303 | else if (this_move.AB || this_move.AW) {
304 | // this is the last play
305 | board
306 | .removeClass('place')
307 | .addClass('play')
308 | .closest('.move')
309 | .addClass(go.sgf.game_info.PI ? 'swap' : '')
310 | .end()
311 | switch_turns();
312 | }
313 | }
314 | if (this_move.PL)
315 | switch_turns(this_move.PL); // wins over all other considerations
316 |
317 | return postdoit(board, this_move);
318 | };
319 |
320 | var undoit = function (board, this_move, optional_previous_move) {
321 |
322 | board = predoit(board, this_move);
323 |
324 | // TODO: Handle other undoables such as placements
325 | // optional previous move is only useful for hilighting the dot to play at this point
326 | // it could be eliminated if we use a comment to annotate it.
327 |
328 | var to_play;
329 | var was_playing;
330 |
331 | var switch_turns = switch_maker(board);
332 |
333 | if (this_move['B'] != undefined) {
334 | to_play = 'white';
335 | was_playing = 'black';
336 | switch_turns(was_playing);
337 | }
338 | else if (this_move['W'] != undefined) {
339 | to_play = 'black';
340 | was_playing = 'white';
341 | switch_turns(was_playing);
342 | }
343 | else return; // not undoable
344 |
345 | var was_playing_index = was_playing[0].toUpperCase();
346 | if (this_move != undefined) {
347 | var position = this_move[was_playing_index];
348 | if (position != undefined) {
349 | if (position) {
350 | board
351 | .find('#' + position)
352 | .removeClass('latest')
353 | .removeClass(was_playing)
354 | .addClass('changed')
355 | .end()
356 | .find(
357 | $.map(
358 | (this_move['K'] && this_move['K'].split(',')) || [],
359 | '"#" + _'.lambda()).join(',')
360 | )
361 | .K(function (removed) {
362 | var z = removed.size();
363 | if (z > 0) {
364 | var restore_colour = (was_playing == 'black' ? 'white' : 'black');
365 | removed.addClass(restore_colour + ' changed');
366 | var c = board.find('.'+restore_colour+'.captured:visible');
367 | if (c.size() > 0) {
368 | var n = parseInt(c.text());
369 | c.text(n == z ? '' : '' + (n - z));
370 | }
371 | else console.error(restore_colour+' should have stones!');
372 | }
373 | })
374 | .end();
375 | }
376 | var to_play_index = to_play[0].toUpperCase();
377 | if (optional_previous_move != undefined) {
378 | var previous_position = optional_previous_move[to_play_index];
379 | if (previous_position)
380 | board
381 | .find('#' + previous_position)
382 | .addClass('latest');
383 | }
384 | // TODO: Deal with titles
385 | }
386 | }
387 |
388 | return postdoit(board, this_move);
389 | };
390 |
391 | var sgf = {
392 |
393 | game_info: undefined,
394 |
395 | current: undefined,
396 |
397 | root: undefined,
398 |
399 | floor: floor,
400 |
401 | ceiling: ceiling,
402 |
403 | doit: doit,
404 |
405 | undoit: undoit,
406 |
407 | push: push,
408 |
409 | pop: pop
410 |
411 | };
412 |
413 | go = {
414 | letters: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's'],
415 | playing: playing,
416 | opponent: opponent,
417 | sgf: sgf,
418 | set_titles: set_titles,
419 | on_document_ready: function (new_document_ready) {
420 | document_ready = (function (old_document_ready) {
421 | return function () {
422 | old_document_ready();
423 | new_document_ready();
424 | }
425 | })(document_ready);
426 | }
427 | };
428 |
429 | $(document).ready(function () { document_ready(); });
430 |
431 | })(jQuery, Functional);
--------------------------------------------------------------------------------
/j/igesture.jquery.mobile_safari.js:
--------------------------------------------------------------------------------
1 | // Copyright 2010 Reginald Braithwaite, Portions Copyright 2008 Nico Goeminne
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // This code modified from jGesture, http://web.siruna.com/nico/jgesture/documentation.html,
16 | // (c) 2008 Nico Goeminne and released under Apache License 2.0
17 | // See: http://www.apache.org/licenses/LICENSE-2.0
18 | //
19 | // Mods (so far) include support for mobile touch events under Mobile Safari,
20 | // storing the target for creating custom events, and expanding the predefined
21 | // events so that things like "close" can be written with eight different
22 | // symmetric gestures.
23 | //
24 | // Warning: May Contain Underscores
25 | // http://ozmm.org/posts/javascript_style.html
26 | //
27 | jQuery.fn.removegesture = function (optional_namespace) {
28 | var namespace = typeof(optional_namespace) == 'undefined' ? '.g' : optional_namespace;
29 | this.unbind(namespace);
30 | return this;
31 | };
32 |
33 | jQuery.fn.gesture = function (events) {
34 |
35 | var handling_element = $(this);
36 |
37 | var return_target = function (target) { return target; };
38 |
39 | var selector_maker = function (selector) {
40 | return function () { return $(selector); };
41 | };
42 |
43 | var stroke_events = {};
44 | var gesture_events = {};
45 | var default_gestures = {
46 | scrub: /^(4([^48]*8[^48]*4)([^48]*8)?)|(8([^48]*4[^48]*8)([^48]*4)?)$/,
47 | open: /^(4.*7.*2)|(4.*1.*6)|(8.*5.*2)|(8.*3.*6)|(2.*7.*4)|(6.*1.*4)|(2.*5.*8)|(6.*3.*8)$/,
48 | close: /^(5.*2.*7)|(1.*6.*3)|(5.*8.*3)|(1.*4.*7)|(7.*2.*5)|(3.*6.*1)|(3.*8.*5)|(7.*4.*1)$/
49 | };
50 | var default_settings = {
51 | startStroke: "touchstart mousedown",
52 | stopStroke: "touchend mouseup",
53 | continueStroke: "touchmove mousemove",
54 | startGesture: "gesturestart",
55 | stopGesture: "gestureend",
56 | continueGesture: "gesturechange",
57 | button: "012",
58 | minDistance: 10,
59 | minScale: 0.25,
60 | minRotation: 22.5,
61 | continuesmode: false,
62 | repeat: false,
63 | disablecontextmenu: true,
64 | hold_time: '2s',
65 | gestures: {},
66 | namespace: '.g',
67 | preventDefault: true
68 | };
69 | var settings = {
70 | gestures: {}
71 | };
72 |
73 | jQuery.each(events, function (i, e) {
74 | if (e == 'scale' || e == 'rotate') {
75 | gesture_events[e] = return_target;
76 | }
77 | else if (typeof(e) == 'string') {
78 | stroke_events[e] = return_target;
79 | }
80 | else {
81 | for (i in e) {
82 | if (typeof(default_settings[i]) == 'undefined') {
83 | var h = (i == 'scale' || i == 'rotate') ? gesture_events : stroke_events;
84 | if (typeof(e[i]) == 'function') {
85 | if (typeof(e[i]).prototype == 'undefined') {
86 | settings.gestures[i] = e[i];
87 | h[i] = return_target;
88 | }
89 | else h[i] = e[i];
90 | }
91 | else if (typeof(e[i]) == 'string'){
92 | h[i] = selector_maker(e[i]);
93 | }
94 | }
95 | else {
96 | settings[i] = e[i];
97 | }
98 | }
99 | }
100 | });
101 |
102 | var care_about_holds_in_general = typeof(stroke_events['hold']) != 'undefined';
103 | var timers_loaded = typeof(handling_element.oneTime) == 'undefined';
104 |
105 | if (care_about_holds_in_general && timers_loaded) {
106 | console.error("You must include jQuery Timers to use gesture_hold: http://plugins.jquery.com/project/timers");
107 | care_about_holds_in_general = false;
108 | stroke_events['hold'] = null;
109 | }
110 |
111 | settings = jQuery.extend(default_settings, settings);
112 | settings.gestures = jQuery.extend(default_gestures, settings.gestures);
113 |
114 | if (!jQuery.isEmptyObject(stroke_events)) {
115 |
116 | var topleft = 1;
117 | var top = 2;
118 | var topright = 3;
119 | var right = 4;
120 | var bottomright = 5;
121 | var bottom = 6;
122 | var bottomleft = 7;
123 | var left = 8;
124 |
125 | var stroke_handler = function (e) {
126 |
127 | if (settings.preventDefault) e.preventDefault();
128 | if (settings.preventDefault) e.stopPropagation();
129 |
130 | var gesture = {
131 | target: $(e.target),
132 | originalEvent: e,
133 | moves: "",
134 | x: -1,
135 | y: -1,
136 | lastmove: "",
137 | continuesmode: settings.continuesmode,
138 | getMoveNameAt: function (i) {
139 | switch (Number(this.moves.charAt(i))) {
140 | case 1:
141 | return "topleft";
142 | case 2:
143 | return "top";
144 | case 3:
145 | return "topright";
146 | case 4:
147 | return "right";
148 | case 5:
149 | return "bottomright";
150 | case 6:
151 | return "bottom";
152 | case 7:
153 | return "bottomleft";
154 | case 8:
155 | return "left";
156 | default:
157 | return "unknown";
158 | }
159 | },
160 | getName: function () {
161 |
162 | if (this.moves.length == 0) {
163 | return 'click';
164 | }
165 |
166 | if (this.continuesmode || this.moves.length == 1) {
167 | return this.getMoveNameAt(this.moves.length - 1);
168 | }
169 |
170 | if (this.moves.length == 2) {
171 | return this.getMoveNameAt(0) + "_" + this.getMoveNameAt(1);
172 | }
173 |
174 | if (this.moves.length < 7) {
175 |
176 | for (var gesture_name in settings.gestures) {
177 | if (this.moves.match(settings.gestures[gesture_name])) {
178 | return gesture_name;
179 | }
180 | }
181 |
182 | }
183 | else {
184 | if ((function (str) {
185 | for (var i = 1; i < 8; i++) {
186 | var pre = Number(str.charAt(i - 1));
187 | var cur = Number(str.charAt(i));
188 | if ((pre + 1 == cur) || (pre == cur + 7)) {
189 | continue;
190 | }
191 | return false;
192 | }
193 | return true;
194 | })(this.moves)) return "circleclockwise";
195 |
196 | if ((function (str) {
197 | for (var i = 1; i < 8; i++) {
198 | var pre = Number(str.charAt(i - 1));
199 | var cur = Number(str.charAt(i));
200 | if ((pre == cur + 1) || (pre + 7 == cur)) {
201 | continue;
202 | }
203 | return false;
204 | }
205 | return true;
206 | })(this.moves)) return "circlecounterclockwise";
207 | }
208 |
209 | return "unknown";
210 | }
211 | };
212 |
213 | if (e.button != null && settings.button.indexOf("" + e.button) == -1) return;
214 |
215 | // disable browser context menu.
216 | if (settings.disablecontextmenu) {
217 | handling_element.bind("contextmenu" + settings.namespace, function (e) { return false; });
218 | }
219 |
220 | gesture.moves = "";
221 | gesture.x = -1;
222 | gesture.y = -1;
223 | gesture.continuesmode = settings.continuesmode;
224 |
225 | var stroke_stopper;
226 | var stroke_continuer;
227 |
228 | var trigger_events = function () {
229 |
230 | var canonical_name = gesture.getName();
231 |
232 | if (typeof(canonical_name) == 'undefined') {
233 | return;
234 | }
235 |
236 | var all_names = [canonical_name];
237 |
238 | if (canonical_name != 'unknown') {
239 | all_names.push('any');
240 | if (gesture.moves.length == 1)
241 | all_names.push('swipe');
242 | if (gesture.moves.length == 2)
243 | all_names.push('elbow');
244 | if (canonical_name == 'circlecounterclockwise' || canonical_name == 'circleclockwise')
245 | all_names.push('circle');
246 | if (canonical_name == 'close') {
247 | all_names.push('no');
248 | all_names.push('reject');
249 | all_names.push('dismiss');
250 | }
251 | if (canonical_name == 'bottomright_topright') {
252 | all_names.push('ok');
253 | all_names.push('accept');
254 | all_names.push('dismiss');
255 | }
256 | }
257 |
258 | jQuery.each(all_names, function (index, gesture_name) {
259 | if (stroke_events[gesture_name]) {
260 | var gesture_event = jQuery.Event("gesture_" + gesture_name);
261 | gesture_event.gesture_data = gesture;
262 | stroke_events[gesture_name](gesture.target).trigger(gesture_event);
263 | }
264 | });
265 |
266 | };
267 |
268 | stroke_continuer = function (e) {
269 |
270 | if (checking_for_hold_on_this_stroke && gesture.moves.length > 0) {
271 | checking_for_hold_on_this_stroke = false;
272 | gesture.target.stopTime('hold_detection');
273 | }
274 | var x;
275 | var y;
276 | if (typeof(e.screenX) != 'undefined') {
277 | x = e.screenX;
278 | y = e.screenY;
279 | }
280 | else if (typeof(e.targetTouches) != 'undefined') {
281 | x = e.targetTouches[0].pageX;
282 | y = e.targetTouches[0].pageY;
283 | }
284 | else if (typeof(e.originalEvent) == 'undefined') {
285 | var str = '';
286 | for (i in e) {
287 | str += ', ' + i + ': ' + e[i];
288 | }
289 | console.error("don't understand x and y for " + e.type + ' event: ' + str);
290 | }
291 | else if (typeof(e.originalEvent.screenX) != 'undefined') {
292 | x = e.originalEvent.screenX;
293 | y = e.originalEvent.screenY;
294 | }
295 | else if (typeof(e.originalEvent.targetTouches) != 'undefined') {
296 | if (typeof(e.originalEvent.targetTouches[0]) == 'undefined') {
297 | var str = '';
298 | for (i in e.originalEvent) {
299 | str += ', ' + i + ': ' + e.originalEvent[i];
300 | }
301 | console.error("don't understand x and y for " + e.originalEvent.type + ' event: ' + str);
302 | }
303 | x = e.originalEvent.targetTouches[0].pageX;
304 | y = e.originalEvent.targetTouches[0].pageY;
305 | if (e.originalEvent.targetTouches.length > 1) {
306 | handling_element.unbind(settings.continueStroke + settings.namespace);
307 | handling_element.unbind(settings.stopStroke + settings.namespace);
308 | return;
309 | }
310 | }
311 |
312 | if ((gesture.x == -1) && (gesture.y == -1)) {
313 | gesture.x = x;
314 | gesture.y = y;
315 | return;
316 | }
317 | var distance = Math.sqrt(Math.pow(x - gesture.x, 2) + Math.pow(y - gesture.y, 2));
318 | if (distance > settings.minDistance) {
319 | var angle = Math.atan2(x - gesture.x, y - gesture.y) / Math.PI + 1;
320 | var dir = 0;
321 | if (3 / 8 < angle && angle < 5 / 8) dir = 8;
322 | if (5 / 8 < angle && angle < 7 / 8) dir = 7;
323 | if (7 / 8 < angle && angle < 9 / 8) dir = 6;
324 | if (9 / 8 < angle && angle < 11 / 8) dir = 5;
325 | if (11 / 8 < angle && angle < 13 / 8) dir = 4;
326 | if (13 / 8 < angle && angle < 15 / 8) dir = 3;
327 | if (15 / 8 < angle || angle < 1 / 8) dir = 2;
328 | if (1 / 8 < angle && angle < 3 / 8) dir = 1;
329 |
330 | gesture.x = x;
331 | gesture.y = y;
332 |
333 | if (gesture.moves.length == 0) {
334 | gesture.moves += dir;
335 | gesture.lastmove = "" + dir;
336 | }
337 | else {
338 | if (settings.repeat || (gesture.moves.charAt(gesture.moves.length - 1) != dir)) {
339 | gesture.moves += dir;
340 | gesture.lastmove = "" + dir;
341 | }
342 | }
343 | if (settings.continuesmode)
344 | trigger_events(); // I believe this is broken and that we only care about the last stroke.
345 | }
346 |
347 | };
348 |
349 | stroke_stopper = function (e) {
350 |
351 | if (checking_for_hold_on_this_stroke) {
352 | gesture.target.stopTime('hold_detection');
353 | }
354 |
355 | if (e.button != null && settings.button.indexOf("" + e.button) == -1) {
356 | return;
357 | }
358 |
359 | if (!settings.disablecontextmenu) {
360 | handling_element.unbind("contextmenu" + settings.namespace);
361 | }
362 | handling_element.unbind(settings.continueStroke + settings.namespace, stroke_continuer);
363 | handling_element.unbind(e);
364 |
365 | trigger_events();
366 |
367 | if (settings.preventDefault) return false;
368 | };
369 |
370 | handling_element
371 | .bind(settings.continueStroke + settings.namespace, stroke_continuer)
372 | .bind(settings.stopStroke + settings.namespace, stroke_stopper);
373 |
374 | var checking_for_hold_on_this_stroke = care_about_holds_in_general;
375 |
376 | if (checking_for_hold_on_this_stroke) {
377 | gesture.target.oneTime(settings.hold_time, 'hold_detection', function () {
378 | handling_element.unbind(settings.continueStroke + settings.namespace, stroke_continuer);
379 | handling_element.unbind(settings.stopStroke + settings.namespace, stroke_stopper);
380 | gesture.getName = function () { return 'hold'; };
381 | trigger_events();
382 | });
383 | }
384 |
385 | if (settings.preventDefault) return false;
386 |
387 | };
388 |
389 | this.bind(settings.startStroke + settings.namespace, stroke_handler);
390 |
391 | };
392 |
393 | if (!jQuery.isEmptyObject(gesture_events)) {
394 |
395 | var gesture_handler = function (e) {
396 |
397 | var gesture = {
398 | target: $(e.target),
399 | originalEvent: e,
400 | continuesmode: settings.continuesmode
401 | };
402 |
403 | // disable browser context menu.
404 | if (settings.disablecontextmenu) {
405 | handling_element.bind("contextmenu" + settings.namespace, function (e) { return false; });
406 | }
407 |
408 | gesture.moves = "";
409 | gesture.x = -1;
410 | gesture.y = -1;
411 | gesture.continuesmode = settings.continuesmode;
412 |
413 | gesture.scale = 1.0;
414 | gesture.rotation = 0;
415 |
416 | handling_element
417 | .filter(':not(.in_gesture)')
418 | .addClass('in_gesture')
419 | .bind(settings.continueGesture + settings.namespace, function (e) {
420 | if (settings.preventDefault) e.preventDefault();
421 | if (settings.preventDefault) e.stopPropagation();
422 | var scale_diff = e.originalEvent.scale - 1.0;
423 | gesture.scale += scale_diff;
424 | var rotation_diff = e.originalEvent.rotation - gesture.rotation
425 | gesture.rotation = e.originalEvent.rotation
426 | if (settings.continuesmode) {
427 | if (Math.abs(gesture.scale - 1.0) >= settings.minScale && gesture_events['scale']) {
428 | var gesture_event = jQuery.Event('gesture_scale');
429 | gesture_event.gesture_data = jQuery.extend(gesture, { name: 'scale' });
430 | gesture_event.scale = gesture.scale;
431 | gesture_events['scale'](gesture.target).trigger(gesture_event);
432 | gesture.scale = 1.0;
433 | }
434 | if (Math.abs(rotation_diff % 360) >= settings.minRotation && gesture_events['rotate']) {
435 | var gesture_event = jQuery.Event('gesture_rotate');
436 | gesture_event.gesture_data = jQuery.extend(gesture, { name: 'rotate' });
437 | gesture_event.rotation = rotation_diff;
438 | gesture_events['rotate'](gesture.target).trigger(gesture_event);
439 | gesture.rotation = 0;
440 | }
441 | }
442 | if (settings.preventDefault) e.preventDefault();
443 | })
444 | .bind(settings.stopGesture + settings.namespace, function (e) {
445 | if (Math.abs(gesture.scale - 1.0) >= settings.minScale && gesture_events['scale']) {
446 | var gesture_event = jQuery.Event('gesture_scale');
447 | gesture_event.gesture_data = jQuery.extend(gesture, { name: 'scale' });
448 | gesture_event.scale = gesture.scale;
449 | gesture_events['scale'](gesture.target).trigger(gesture_event);
450 | }
451 | if (Math.abs(gesture.rotation % 360) >= settings.minRotation && gesture_events['rotate']) {
452 | var gesture_event = jQuery.Event('gesture_rotate');
453 | gesture_event.gesture_data = jQuery.extend(gesture, { name: 'rotate' });
454 | gesture_event.rotation = gesture.rotation;
455 | gesture_events['rotate'](gesture.target).trigger(gesture_event);
456 | }
457 | if (settings.preventDefault) e.preventDefault();
458 | if (settings.preventDefault) e.stopPropagation();
459 | handling_element
460 | .unbind(settings.continueGesture + settings.namespace)
461 | .unbind(settings.stopGesture + settings.namespace)
462 | .removeClass('in_gesture');
463 | });
464 |
465 | };
466 |
467 | this
468 | .bind(settings.startGesture + settings.namespace, gesture_handler);
469 |
470 | };
471 |
472 | return this;
473 |
474 | };
--------------------------------------------------------------------------------