diff --git a/.gitignore b/.gitignore index 25213893..f31703fb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ # git diff files *.diff +dist/ node_modules/ website/*.html website/css/chessboard.css website/js/chessboard.js +website/examples/ diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..3b7fc38b --- /dev/null +++ b/.npmignore @@ -0,0 +1,7 @@ +data/ +examples/ +scripts/ +templates/ +website/ +.editorconfig +changes.diff diff --git a/CHANGELOG.md b/CHANGELOG.md index b328542e..c0c6b2fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. -## [Unreleased] +## [1.0.0] - 2019-06-11 - Orientation methods now return current orientation. [Issue #64] - Drop support for IE8 - Do not check for `window.JSON` (Error #1004) diff --git a/LICENSE.md b/LICENSE.md index 51dd8955..20b7d615 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright 2013 Chris Oakman +Copyright 2019 Chris Oakman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index be161237..0c99b412 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,18 @@ -# chessboard.js +# chessboard.js [![npm](https://img.shields.io/npm/v/@chrisoakman/chessboardjs.svg)](https://www.npmjs.com/package/@chrisoakman/chessboardjs) [![MIT License](https://img.shields.io/npm/l/@chrisoakman/chessboardjs)](https://github.com/oakmac/chessboardjs/blob/master/LICENSE.md) -chessboard.js is a JavaScript chessboard component. It depends on [jQuery]. +> **NOTE:** chessboard.js can be found on npm as `@chrisoakman/chessboardjs` + +chessboard.js is a JavaScript chessboard component. It depends on [jQuery] v3.4.1 (or higher). Please see [chessboardjs.com] for documentation and examples. -## What is chessboard.js? +## Project Status (Dec 2022) -chessboard.js is a JavaScript chessboard component with a flexible "just a -board" API that +I am currently focusing my efforts on [chessboard2]. + +[chessboard2]:https://github.com/oakmac/chessboard2 + +## What is chessboard.js? chessboard.js is a standalone JavaScript Chess Board. It is designed to be "just a board" and expose a powerful API so that it can be used in different ways. @@ -27,47 +32,38 @@ ease. ## What can chessboard.js **not** do? The scope of chessboard.js is limited to "just a board." This is intentional and -makes chessboard.js flexible for handling a multitude of chess-related problems. - -This is a common source of confusion for new users. [remove?] - -Specifically, chessboard.js does not understand anything about how the game of -chess is played: how a knight moves, who's turn is it, is White in check?, etc. +makes chessboard.js flexible for building a variety of chess-related +applications. -Fortunately, the powerful [chess.js] library deals with exactly this sort of -problem domain and plays nicely with chessboard.js's flexible API. Some examples -of chessboard.js combined with chess.js: 5000, 5001, 5002 +To be specific, chessboard.js does not understand anything about how the game of +chess is played: how a knight moves, whose turn is it, is White in check?, etc. -Please see the powerful [chess.js] library for an API to deal with these sorts -of questions. +Fortunately, the [chess.js] library deals with exactly this sort of problem and +plays nicely with chessboard.js's flexible API. Some examples of chessboard.js +combined with chess.js: [Example 5000], [Example 5001], [Example 5002] +## Docs and Examples -This logic is distinct from the logic of the board. Please see the powerful -[chess.js] library for this aspect of your application. - - - -Here is a list of things that chessboard.js is **not**: - -- A chess engine -- A legal move validator -- A PGN parser +- Docs - +- Examples - -chessboard.js is designed to work well with any of those things, but the idea -behind chessboard.js is that the logic that controls the board should be -independent of those other problems. +## Developer Tools -## Docs and Examples +```sh +# create a build in the build/ directory +npm run build -- Docs - -- Examples - +# re-build the website +npm run website +``` ## License -chessboard.js is released under the terms of the [MIT License]. +[MIT License](LICENSE.md) [jQuery]:https://jquery.com/ -[chessboardjs.com]:http://chessboardjs.com +[chessboardjs.com]:https://chessboardjs.com [chess.js]:https://github.com/jhlywa/chess.js -[Example 5000]:http://chessboardjs.com/examples#5000 -[MIT License]:LICENSE.md +[Example 5000]:https://chessboardjs.com/examples#5000 +[Example 5001]:https://chessboardjs.com/examples#5001 +[Example 5002]:https://chessboardjs.com/examples#5002 diff --git a/examples/1004-multiple-boards.example b/examples/1004-multiple-boards.example index 7dcf0358..54c45e6d 100644 --- a/examples/1004-multiple-boards.example +++ b/examples/1004-multiple-boards.example @@ -7,7 +7,14 @@ Multiple Boards ===== Description You can have multiple boards on the same page. -===== HTML +===== CSS +.small-board { + display: inline-block; + margin-right: 5px; + width: 200px; +} + +===== HTML
diff --git a/src/chessboard.css b/lib/chessboard.css similarity index 78% rename from src/chessboard.css rename to lib/chessboard.css index 722715c0..27ffdccb 100644 --- a/src/chessboard.css +++ b/lib/chessboard.css @@ -1,12 +1,4 @@ -/*! - * chessboard.js $version$ - * - * Copyright 2013 Chris Oakman - * Released under the MIT license - * https://github.com/oakmac/chessboardjs/blob/master/LICENSE - * - * Date: $date$ - */ +/*! chessboard.js v@VERSION | (c) 2019 Chris Oakman | MIT License chessboardjs.com/license */ .clearfix-7da63 { clear: both; diff --git a/src/chessboard.js b/lib/chessboard.js similarity index 95% rename from src/chessboard.js rename to lib/chessboard.js index c5b565e6..ed27db18 100644 --- a/src/chessboard.js +++ b/lib/chessboard.js @@ -1,7 +1,7 @@ // chessboard.js v@VERSION // https://github.com/oakmac/chessboardjs/ // -// Copyright (c) 2017, Chris Oakman +// Copyright (c) 2019, Chris Oakman // Released under the MIT license // https://github.com/oakmac/chessboardjs/blob/master/LICENSE.md @@ -405,22 +405,22 @@ function squeezeFenEmptySquares (fen) { return fen.replace(/11111111/g, '8') - .replace(/1111111/g, '7') - .replace(/111111/g, '6') - .replace(/11111/g, '5') - .replace(/1111/g, '4') - .replace(/111/g, '3') - .replace(/11/g, '2') + .replace(/1111111/g, '7') + .replace(/111111/g, '6') + .replace(/11111/g, '5') + .replace(/1111/g, '4') + .replace(/111/g, '3') + .replace(/11/g, '2') } function expandFenEmptySquares (fen) { return fen.replace(/8/g, '11111111') - .replace(/7/g, '1111111') - .replace(/6/g, '111111') - .replace(/5/g, '11111') - .replace(/4/g, '1111') - .replace(/3/g, '111') - .replace(/2/g, '11') + .replace(/7/g, '1111111') + .replace(/6/g, '111111') + .replace(/5/g, '11111') + .replace(/4/g, '1111') + .replace(/3/g, '111') + .replace(/2/g, '11') } // returns the distance between two squares @@ -686,22 +686,22 @@ // ------------------------------------------------------------------------- function error (code, msg, obj) { - // do nothing if showErrors is not set + // do nothing if showErrors is not set if ( - config.hasOwnProperty('showErrors') !== true || + config.hasOwnProperty('showErrors') !== true || config.showErrors === false - ) { + ) { return } var errorText = 'Chessboard Error ' + code + ': ' + msg - // print to console + // print to console if ( - config.showErrors === 'console' && + config.showErrors === 'console' && typeof console === 'object' && typeof console.log === 'function' - ) { + ) { console.log(errorText) if (arguments.length >= 2) { console.log(obj) @@ -709,7 +709,7 @@ return } - // alert errors + // alert errors if (config.showErrors === 'alert') { if (obj) { errorText += '\n\n' + JSON.stringify(obj) @@ -737,10 +737,10 @@ currentPosition = deepCopy(config.position) } else { error( - 7263, - 'Invalid value passed to config.position.', - config.position - ) + 7263, + 'Invalid value passed to config.position.', + config.position + ) } } } @@ -1202,11 +1202,11 @@ // run their onSnapbackEnd function if (isFunction(config.onSnapbackEnd)) { config.onSnapbackEnd( - draggedPiece, - draggedPieceSource, - deepCopy(currentPosition), - currentOrientation - ) + draggedPiece, + draggedPieceSource, + deepCopy(currentPosition), + currentOrientation + ) } } @@ -1342,13 +1342,13 @@ // run onDragMove if (isFunction(config.onDragMove)) { config.onDragMove( - location, - draggedPieceLocation, - draggedPieceSource, - draggedPiece, - deepCopy(currentPosition), - currentOrientation - ) + location, + draggedPieceLocation, + draggedPieceSource, + draggedPiece, + deepCopy(currentPosition), + currentOrientation + ) } // update state @@ -1395,13 +1395,13 @@ var oldPosition = deepCopy(currentPosition) var result = config.onDrop( - draggedPieceSource, - location, - draggedPiece, - newPosition, - oldPosition, - currentOrientation - ) + draggedPieceSource, + location, + draggedPiece, + newPosition, + oldPosition, + currentOrientation + ) if (result === 'snapback' || result === 'trash') { action = result } @@ -1589,7 +1589,7 @@ } function mousedownSquare (evt) { - // do nothing if we're not draggable + // do nothing if we're not draggable if (!config.draggable) return // do nothing if there is no piece on this square @@ -1611,11 +1611,11 @@ e = e.originalEvent beginDraggingPiece( - square, - currentPosition[square], - e.changedTouches[0].pageX, - e.changedTouches[0].pageY - ) + square, + currentPosition[square], + e.changedTouches[0].pageX, + e.changedTouches[0].pageY + ) } function mousedownSparePiece (evt) { @@ -1635,11 +1635,11 @@ e = e.originalEvent beginDraggingPiece( - 'spare', - piece, - e.changedTouches[0].pageX, - e.changedTouches[0].pageY - ) + 'spare', + piece, + e.changedTouches[0].pageX, + e.changedTouches[0].pageY + ) } function mousemoveWindow (evt) { @@ -1658,7 +1658,7 @@ evt.preventDefault() updateDraggedPiece(evt.originalEvent.changedTouches[0].pageX, - evt.originalEvent.changedTouches[0].pageY) + evt.originalEvent.changedTouches[0].pageY) } var throttledTouchmoveWindow = throttle(touchmoveWindow, config.dragThrottleRate) @@ -1679,7 +1679,7 @@ // get the location var location = isXYOnSquare(evt.originalEvent.changedTouches[0].pageX, - evt.originalEvent.changedTouches[0].pageY) + evt.originalEvent.changedTouches[0].pageY) stopDraggedPiece(location) } @@ -1815,3 +1815,9 @@ window['Chessboard']['fenToObj'] = fenToObj window['Chessboard']['objToFen'] = objToFen })() // end anonymous wrapper + +/* export Chessboard object if using node or any other CommonJS compatible + * environment */ +if (typeof exports !== 'undefined') { + exports.Chessboard = window.Chessboard +} diff --git a/package.json b/package.json index 20540de2..bf071a30 100644 --- a/package.json +++ b/package.json @@ -1,23 +1,29 @@ { "author": "Chris Oakman (http://chrisoakman.com/)", - "name": "oakmac-chessboard", + "name": "@chrisoakman/chessboardjs", "description": "JavaScript chessboard widget", + "homepage": "https://chessboardjs.com", + "license": "MIT", "version": "1.0.0", "repository": { "type": "git", "url": "git://github.com/oakmac/chessboardjs.git" }, - "main": "src/chessboard.js", + "files": ["dist/"], "dependencies": { - "jquery": ">=1.8.3" + "jquery": ">=3.4.1" }, "devDependencies": { + "csso": "3.5.1", + "fs-plus": "3.1.1", "kidif": "1.1.0", "mustache": "2.3.0", - "standard": "10.0.2" + "standard": "10.0.2", + "uglify-js": "3.6.0" }, "scripts": { - "test": "mocha" - }, - "license": "MIT" + "build": "standard lib/chessboard.js && node scripts/build.js", + "standard": "standard --fix lib/*.js website/js/*.js", + "website": "node scripts/website.js" + } } diff --git a/pages/404.php b/pages/404.php deleted file mode 100644 index 2b1cd920..00000000 --- a/pages/404.php +++ /dev/null @@ -1,9 +0,0 @@ - -

Page Not Found

-

Would you like to go to the homepage?

- \ No newline at end of file diff --git a/pages/docs.php b/pages/docs.php deleted file mode 100644 index 57473caf..00000000 --- a/pages/docs.php +++ /dev/null @@ -1,335 +0,0 @@ - - -
-

Config

- - - - - - - - - - - - - -
Property / TypeRequiredDefaultDescriptionExample
-
- -
- -
-

Methods

- - - - - - - - - - - - -
MethodArgsDescriptionExample
-
- -
- -
-

Position Object

-

You can use a JavaScript object to represent a board position.

-

The object property names must be algebraic squares (ie: e4, b2, c6, etc) and the values must be a valid piece codes (ie: wP, bK, wQ, etc).

-

See an example of using an object to represent a position here.

-

ChessBoard exposes the ChessBoard.objToFen method to help convert between Position Objects and FEN Strings.

-
- -
- -
-

FEN String

-

You can use Forsyth-Edwards Notation (FEN) to represent a board position.

-

Note that FEN notation captures more information than ChessBoard requires, like who's move it is and whether or not castling is allowed. This information will be ignored; only the position information is used.

-

See an example of using a FEN String to represent a position here and here.

-

ChessBoard exposes the ChessBoard.fenToObj method to help convert a FEN String to a Position Object.

-
- -
- -
-

Errors

-

ChessBoard has an error system designed to inform you when you use the API incorrectly.

-

Every alert has a unique code associated with it and you can control how the errors are presented with the showErrors config option.

- - - - - - - - - - - -
Error IDError TextMore Information
-
- - - - - -'."\n"; - - // property and type - $html .= ' '."\n"; - $html .= buildPropertyAndType($propType, $prop['name'], $prop['type']); - $html .= ' '."\n"; - - // required - $html .= ' '.buildReq($prop['req']).''."\n"; - - // default - if (array_key_exists('leftAlignDefault', $prop) === true) { - $html .= ' '.buildDefault($prop['default']).''."\n"; - } - else { - $html .= ' '.buildDefault($prop['default']).''."\n"; - } - - // description - $html .= ' '."\n"; - $html .= buildDesc($prop['desc']); - $html .= ' '."\n"; - - // examples - $html .= ' '."\n"; - $html .= buildExamplesCell($prop['examples'], $examples); - $html .= ' '."\n"; - - $html .= ''."\n"; - - return $html; -} - -function buildMethodRow($method, $examples) { - $nameNoParens = preg_replace('/\(.+$/', '', $method['name']); - - $html = ''; - - // table row - if (array_key_exists('noId', $method) === true) { - $html .= "\n"; - } - else { - $html .= ''."\n"; - } - - // name - $html .= ' '.$method['name'].''."\n"; - - // args - if (array_key_exists('args', $method) === true) { - $html .= ' '."\n"; - foreach ($method['args'] as $arg) { - $html .= '

'.$arg[0].' - '.$arg[1].'

'."\n"; - } - $html .= ' '."\n"; - } - else { - $html .= ' none'."\n"; - } - - // description - $html .= ' '."\n"; - $html .= buildDesc($method['desc']); - $html .= ' '."\n"; - - // examples - $html .= ' '."\n"; - $html .= buildExamplesCell($method['examples'], $examples); - $html .= ' '."\n"; - - $html .= "\n"; - - return $html; -} - -function getExampleByNumber($number, $examples) { - $number = (int) $number; - foreach ($examples as $ex) { - if (intval($ex['number'], 10) === $number && - $ex['js'] !== '') { - return $ex; - } - } - return false; -} - -function buildPropertyAndType($section, $name, $type) { - $html = '

'.$name.'

'."\n"; - $html .= '

'.buildType($type).'

'."\n"; - return $html; -} - -function buildType($type) { - if (is_array($type) !== true) { - $type = array($type); - } - - $html = ''; - for ($i = 0; $i < count($type); $i++) { - if ($i !== 0) { - $html .= ' or
'; - } - $html .= $type[$i]; - } - - return $html; -} - -function buildReq($req) { - if ($req === false) { - return 'no'; - } - if ($req === true) { - return 'yes'; - } - return $req; -} - -function buildDesc($desc) { - if (is_array($desc) !== true) { - $desc = array($desc); - } - $html = ''; - foreach ($desc as $d) { - $html .= '

'.$d.'

'."\n"; - } - return $html; -} - -function buildDefault($default) { - if ($default === false) { - return 'n/a'; - } - return $default; -} - -function buildExamplesCell($ex, $allExamples) { - if (is_array($ex) !== true) { - $ex = array($ex); - } - - $html = ''; - foreach ($ex as $exNum) { - if (array_key_exists($exNum, $allExamples) !== true) continue; - - $example = $allExamples[$exNum]; - - $html .= '

'.$example['Name'].'

'."\n"; - } - return $html; -} - -function buildErrorRow($error) { - $html = ''; - - // table row - $html .= ''."\n"; - - // id - $html .= ' '.$error['id'].''."\n"; - - // desc - $html .= ' '.htmlspecialchars($error['desc']).''."\n"; - - // more information - if (array_key_exists('fix', $error) === true) { - if (is_array($error['fix']) !== true) { - $error['fix'] = array($error['fix']); - } - - $html .= ' '."\n"; - foreach ($error['fix'] as $p) { - $html .= '

'.$p.'

'."\n"; - } - $html .= ' '."\n"; - } - else { - $html .= ' n/a'."\n"; - } - - $html .= "\n"; - - return $html; -} - -?> \ No newline at end of file diff --git a/pages/download.php b/pages/download.php deleted file mode 100644 index d93b74de..00000000 --- a/pages/download.php +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - -
-

Development

-

GitHub

-
- -'."\n"; - $html .= '

v'.$v.' released on '.$release['date'].'

'."\n"; - $html .= '
    '."\n"; - foreach ($release['files'] as $file) { - $html .= '
  • '.$file['name'].' '.$file['size'].'
  • '."\n"; - } - $html .= '
'."\n"; - $html .= '
Changes:
'."\n"; - $html .= '
    '."\n"; - foreach ($release['changes'] as $change) { - $html .= '
  • '.htmlspecialchars($change).'
  • '."\n"; - } - $html .= '
'."\n"; - $html .= ''."\n\n"; - - return $html; -} - -?> \ No newline at end of file diff --git a/pages/examples.php b/pages/examples.php deleted file mode 100644 index 7827c869..00000000 --- a/pages/examples.php +++ /dev/null @@ -1,156 +0,0 @@ - - -
- -
-
- -
-
- -
-

-

View example in new window.

-

-
-

JavaScript

-
-

HTML

-
-
- -
- - - - - - - -'.$group['group'].''."\n"; - $html .= ''."\n"; - - $groupIndex++; - } - - return $html; -} -?> \ No newline at end of file diff --git a/pages/footer.php b/pages/footer.php deleted file mode 100644 index bc5194c2..00000000 --- a/pages/footer.php +++ /dev/null @@ -1,18 +0,0 @@ - - - - - diff --git a/pages/header.php b/pages/header.php deleted file mode 100644 index d4cf35e9..00000000 --- a/pages/header.php +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - <?php echo PROJECT_NAME; ?><?php if (isset($page_title)) echo ' » '.$page_title; ?> - - - - - - - - - - - - - -
-
diff --git a/pages/home.php b/pages/home.php deleted file mode 100644 index 7ec72a01..00000000 --- a/pages/home.php +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - chessboard.js » Home - - - - - - - - - -
-
- Black King -

chessboard.js

-

The easiest way to embed a chess board on your site.

- Download v0.3.0 -
-
- - - -
- -
- -
-

As easy as two lines.

-

HTML

-
<div id="board1" style="width: 400px"></div>
-

JavaScript

-
var board1 = ChessBoard('board1', 'start');
-
-
-
-
-
- -
-

Customize with a powerful API.

-

HTML

-
<div id="board2" style="width: 400px"></div>
-<input type="button" id="startBtn" value="Start" />
-<input type="button" id="clearBtn" value="Clear" />
-

JavaScript

-
var board2 = ChessBoard('board2', {
-  draggable: true,
-  dropOffBoard: 'trash',
-  sparePieces: true
-});
-$('#startBtn').on('click', board2.start);
-$('#clearBtn').on('click', board2.clear);
-
-
-
- - -
-
- -
- -
-
-
-

chessboard.js is released under the MIT License

-

the code can be found on GitHub

-
- -
-
-
- - - - - - - - diff --git a/pages/single_example.php b/pages/single_example.php deleted file mode 100644 index 774e2efc..00000000 --- a/pages/single_example.php +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - <?php echo $example['Name']; ?> Example - - - - - -

← Back to all examples.

- -

- - - - - - - - - - - \ No newline at end of file diff --git a/scripts/build.js b/scripts/build.js new file mode 100644 index 00000000..798bec10 --- /dev/null +++ b/scripts/build.js @@ -0,0 +1,46 @@ +// ----------------------------------------------------------------------------- +// This file creates a build in the dist/ folder +// ----------------------------------------------------------------------------- + +// libraries +const fs = require('fs-plus') +const csso = require('csso') +const uglify = require('uglify-js') + +const encoding = {encoding: 'utf8'} + +const package = JSON.parse(fs.readFileSync('package.json', encoding)) +const version = package.version +const year = new Date().getFullYear() +const cssSrc = fs.readFileSync('lib/chessboard.css', encoding) + .replace('@VERSION', version) +const jsSrc = fs.readFileSync('lib/chessboard.js', encoding) + .replace('@VERSION', version) + .replace('RUN_ASSERTS = true', 'RUN_ASSERTS = false') + +// TODO: need to remove the RUN_ASSERTS calls from the non-minified file + +const minifiedCSS = csso.minify(cssSrc).css +const uglifyResult = uglify.minify(jsSrc) +const minifiedJS = uglifyResult.code + +// quick sanity checks +console.assert(!uglifyResult.error, 'error minifying JS!') +console.assert(typeof minifiedCSS === 'string' && minifiedCSS !== '', 'error minifying CSS!') + +// add license to the top of minified files +const minifiedJSWithBanner = banner() + minifiedJS + +// create a fresh dist/ folder +fs.removeSync('dist') +fs.makeTreeSync('dist') + +// copy lib files to dist/ +fs.writeFileSync('dist/chessboard-' + version + '.css', cssSrc, encoding) +fs.writeFileSync('dist/chessboard-' + version + '.min.css', minifiedCSS, encoding) +fs.writeFileSync('dist/chessboard-' + version + '.js', jsSrc, encoding) +fs.writeFileSync('dist/chessboard-' + version + '.min.js', minifiedJSWithBanner, encoding) + +function banner () { + return '/*! chessboard.js v' + version + ' | (c) ' + year + ' Chris Oakman | MIT License chessboardjs.com/license */\n' +} diff --git a/rename.js b/scripts/rename.js similarity index 90% rename from rename.js rename to scripts/rename.js index e889b6d5..c6a99385 100644 --- a/rename.js +++ b/scripts/rename.js @@ -1,3 +1,5 @@ +// TODO: this is unfinished / not working + var fs = require('fs') var glob = require('glob') diff --git a/build-website.js b/scripts/website.js old mode 100644 new mode 100755 similarity index 81% rename from build-website.js rename to scripts/website.js index 28c573da..1b107fa1 --- a/build-website.js +++ b/scripts/website.js @@ -1,30 +1,46 @@ +#! /usr/bin/env node + // ----------------------------------------------------------------------------- -// This files builds the .html files in the website/ folder +// This file builds the contents of the website/ folder. // ----------------------------------------------------------------------------- // libraries -const fs = require('fs') +const fs = require('fs-plus') const kidif = require('kidif') const mustache = require('mustache') -const docs = require('./data/docs.json') +const docs = require('../data/docs.json') const encoding = {encoding: 'utf8'} +// toggle development version +const useDevFile = false +const jsCDNLink = '' +const cssCDNLink = 'https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.css' + +let chessboardJsScript = jsCDNLink +if (useDevFile) { + chessboardJsScript = '' +} + // grab some mustache templates const docsTemplate = fs.readFileSync('templates/docs.mustache', encoding) const downloadTemplate = fs.readFileSync('templates/download.mustache', encoding) const examplesTemplate = fs.readFileSync('templates/examples.mustache', encoding) const homepageTemplate = fs.readFileSync('templates/homepage.mustache', encoding) const singleExampleTemplate = fs.readFileSync('templates/single-example.mustache', encoding) +const licensePageTemplate = fs.readFileSync('templates/license.mustache', encoding) const headTemplate = fs.readFileSync('templates/_head.mustache', encoding) const headerTemplate = fs.readFileSync('templates/_header.mustache', encoding) const footerTemplate = fs.readFileSync('templates/_footer.mustache', encoding) -const latestChessboardJS = fs.readFileSync('src/chessboard.js', encoding) -const latestChessboardCSS = fs.readFileSync('src/chessboard.css', encoding) +const latestChessboardJS = fs.readFileSync('lib/chessboard.js', encoding) +const latestChessboardCSS = fs.readFileSync('lib/chessboard.css', encoding) // grab the examples const examplesArr = kidif('examples/*.example') +console.assert(examplesArr, 'Could not load the Example files') +console.assert(examplesArr.length > 1, 'Zero examples loaded') + const examplesObj = examplesArr.reduce(function (examplesObj, example, idx) { examplesObj[example.id] = example return examplesObj @@ -74,9 +90,10 @@ function writeHomepage () { const headHTML = mustache.render(headTemplate, {pageTitle: 'Homepage'}) const html = mustache.render(homepageTemplate, { + chessboardJsScript: chessboardJsScript, + example2: homepageExample2, footer: footerTemplate, - head: headHTML, - example2: homepageExample2 + head: headHTML }) fs.writeFileSync('website/index.html', html, encoding) } @@ -86,6 +103,7 @@ function writeExamplesPage () { const headerHTML = mustache.render(headerTemplate, {examplesActive: true}) const html = mustache.render(examplesTemplate, { + chessboardJsScript: chessboardJsScript, examplesJavaScript: buildExamplesJS(), footer: footerTemplate, head: headHTML, @@ -110,6 +128,23 @@ const errorRowsHTML = docs.errors.reduce(function (html, itm) { return html + buildErrorRowHTML(itm) }, '') +function isIntegrationExample (example) { + return (example.id + '').startsWith('5') +} + +function writeSingleExamplePage (example) { + if (isIntegrationExample(example)) { + example.includeChessJS = true + } + example.chessboardJsScript = chessboardJsScript + const html = mustache.render(singleExampleTemplate, example) + fs.writeFileSync('website/examples/' + example.id + '.html', html, encoding) +} + +function writeSingleExamplesPages () { + examplesArr.forEach(writeSingleExamplePage) +} + function writeDocsPage () { const headHTML = mustache.render(headTemplate, {pageTitle: 'Documentation'}) const headerHTML = mustache.render(headerTemplate, {docsActive: true}) @@ -137,12 +172,19 @@ function writeDownloadPage () { fs.writeFileSync('website/download.html', html, encoding) } +function writeLicensePage () { + const html = mustache.render(licensePageTemplate) + fs.writeFileSync('website/license.html', html, encoding) +} + function writeWebsite () { writeSrcFiles() writeHomepage() writeExamplesPage() + writeSingleExamplesPages() writeDocsPage() writeDownloadPage() + writeLicensePage() } writeWebsite() @@ -153,13 +195,13 @@ writeWebsite() function htmlEscape (str) { return (str + '') - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, ''') - .replace(/\//g, '/') - .replace(/`/g, '`') + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/\//g, '/') + .replace(/`/g, '`') } function buildExampleGroupHTML (idx, groupName, examplesInGroup) { diff --git a/src/tests.html b/src/tests.html deleted file mode 100644 index d6afc18c..00000000 --- a/src/tests.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - Chessboard Tests - - - -
-
- - - - - diff --git a/templates/_footer.mustache b/templates/_footer.mustache index ec1fcfe9..8f21118e 100644 --- a/templates/_footer.mustache +++ b/templates/_footer.mustache @@ -4,5 +4,8 @@

chessboard.js is released under the MIT License

the code can be found on GitHub

+
+

by Chris Oakman

+
diff --git a/templates/_head.mustache b/templates/_head.mustache index 5a389b67..07511c7e 100644 --- a/templates/_head.mustache +++ b/templates/_head.mustache @@ -3,8 +3,13 @@ chessboardjs.com » {{pageTitle}} - + + + + + + - - + + diff --git a/templates/_header.mustache b/templates/_header.mustache index 78d17359..f4ecf8c8 100644 --- a/templates/_header.mustache +++ b/templates/_header.mustache @@ -5,9 +5,9 @@ diff --git a/templates/docs.mustache b/templates/docs.mustache index 7339f914..39c0ce23 100644 --- a/templates/docs.mustache +++ b/templates/docs.mustache @@ -21,7 +21,7 @@
-

Config Properties

+

Config Properties

@@ -37,7 +37,7 @@
-

Methods

+

Methods

@@ -53,7 +53,7 @@
-

Position Object

+

Position Object

You can use a JavaScript object to represent a board position.

The object property names must be algebraic squares (ie: e4, b2, c6, etc) and the values must be a valid piece codes (ie: wP, bK, wQ, etc).

See an example of using an object to represent a position here.

@@ -62,7 +62,7 @@
-

FEN String

+

FEN String

You can use Forsyth-Edwards Notation (FEN) to represent a board position.

Note that FEN notation captures more information than chessboard.js requires, like who's move it is and whether or not castling is allowed. This information will be ignored; only the position information is used.

See an example of using a FEN String to represent a position here and here.

@@ -71,7 +71,7 @@
-

Errors

+

Errors

Chessboard.js has an error system designed to inform you when you use the API incorrectly.

Every alert has a unique code associated with it and you can control how the errors are presented with the showErrors config option.

@@ -92,7 +92,7 @@ {{{footer}}} - + + diff --git a/templates/examples.mustache b/templates/examples.mustache index 01c543f4..f11d4f45 100644 --- a/templates/examples.mustache +++ b/templates/examples.mustache @@ -16,9 +16,9 @@ - + - +{{{chessboardJsScript}}} diff --git a/templates/homepage.mustache b/templates/homepage.mustache index dd8a4ec3..0ff8ee63 100644 --- a/templates/homepage.mustache +++ b/templates/homepage.mustache @@ -5,19 +5,19 @@
- Black King + Black King

chessboard.js

The easiest way to embed a chess board on your site.

- Download v0.3.0 + Download v1.0.0
-
","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ma.optgroup=ma.option,ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead,ma.th=ma.td;function na(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&B(a,b)?r.merge([a],c):c}function oa(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=na(l.appendChild(f),"script"),j&&oa(g),c){k=0;while(f=g[k++])la.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var ra=d.documentElement,sa=/^key/,ta=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ua=/^([^.]*)(?:\.(.+)|)/;function va(){return!0}function wa(){return!1}function xa(){try{return d.activeElement}catch(a){}}function ya(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ya(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=wa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(ra,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(L)||[""],j=b.length;while(j--)h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.hasData(a)&&W.get(a);if(q&&(i=q.events)){b=(b||"").match(L)||[""],j=b.length;while(j--)if(h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&W.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(W.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i\x20\t\r\n\f]*)[^>]*)\/>/gi,Aa=/\s*$/g;function Ea(a,b){return B(a,"table")&&B(11!==b.nodeType?b:b.firstChild,"tr")?r(">tbody",a)[0]||a:a}function Fa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ga(a){var b=Ca.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ha(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(W.hasData(a)&&(f=W.access(a),g=W.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&Ba.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ja(f,b,c,d)});if(m&&(e=qa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(na(e,"script"),Fa),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=na(h),f=na(a),d=0,e=f.length;d0&&oa(g,!i&&na(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(U(c)){if(b=c[W.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[W.expando]=void 0}c[X.expando]&&(c[X.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ka(this,a,!0)},remove:function(a){return Ka(this,a)},text:function(a){return T(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.appendChild(a)}})},prepend:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(na(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return T(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!Aa.test(a)&&!ma[(ka.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}});function _a(a,b,c,d,e){return new _a.prototype.init(a,b,c,d,e)}r.Tween=_a,_a.prototype={constructor:_a,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=_a.propHooks[this.prop];return a&&a.get?a.get(this):_a.propHooks._default.get(this)},run:function(a){var b,c=_a.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):_a.propHooks._default.set(this),this}},_a.prototype.init.prototype=_a.prototype,_a.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},_a.propHooks.scrollTop=_a.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=_a.prototype.init,r.fx.step={};var ab,bb,cb=/^(?:toggle|show|hide)$/,db=/queueHooks$/;function eb(){bb&&(d.hidden===!1&&a.requestAnimationFrame?a.requestAnimationFrame(eb):a.setTimeout(eb,r.fx.interval),r.fx.tick())}function fb(){return a.setTimeout(function(){ab=void 0}),ab=r.now()}function gb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ca[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function hb(a,b,c){for(var d,e=(kb.tweeners[b]||[]).concat(kb.tweeners["*"]),f=0,g=e.length;f1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?lb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b), -null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&B(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(L);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),lb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=mb[b]||r.find.attr;mb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=mb[g],mb[g]=e,e=null!=c(a,b,d)?g:null,mb[g]=f),e}});var nb=/^(?:input|select|textarea|button)$/i,ob=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return T(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):nb.test(a.nodeName)||ob.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function pb(a){var b=a.match(L)||[];return b.join(" ")}function qb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,qb(this)))});if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,qb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,qb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(L)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=qb(this),b&&W.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":W.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+pb(qb(c))+" ").indexOf(b)>-1)return!0;return!1}});var rb=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":Array.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:pb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(Array.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var sb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!sb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,sb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(W.get(h,"events")||{})[b.type]&&W.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&U(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!U(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=W.access(d,b);e||d.addEventListener(a,c,!0),W.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=W.access(d,b)-1;e?W.access(d,b,e):(d.removeEventListener(a,c,!0),W.remove(d,b))}}});var tb=a.location,ub=r.now(),vb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var wb=/\[\]$/,xb=/\r?\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(Array.isArray(b))r.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)Ab(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(Array.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!ja.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:Array.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(xb,"\r\n")}}):{name:b.name,value:c.replace(xb,"\r\n")}}).get()}});var Bb=/%20/g,Cb=/#.*$/,Db=/([?&])_=[^&]*/,Eb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Fb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Gb=/^(?:GET|HEAD)$/,Hb=/^\/\//,Ib={},Jb={},Kb="*/".concat("*"),Lb=d.createElement("a");Lb.href=tb.href;function Mb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(L)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Nb(a,b,c,d){var e={},f=a===Jb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Ob(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Pb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Qb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:tb.href,type:"GET",isLocal:Fb.test(tb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Kb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Ob(Ob(a,r.ajaxSettings),b):Ob(r.ajaxSettings,a)},ajaxPrefilter:Mb(Ib),ajaxTransport:Mb(Jb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Eb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||tb.href)+"").replace(Hb,tb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(L)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Lb.protocol+"//"+Lb.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Nb(Ib,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Gb.test(o.type),f=o.url.replace(Cb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(Bb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(vb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Db,"$1"),n=(vb.test(f)?"&":"?")+"_="+ub++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Kb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Nb(Jb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Pb(o,y,d)),v=Qb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Rb={0:200,1223:204},Sb=r.ajaxSettings.xhr();o.cors=!!Sb&&"withCredentials"in Sb,o.ajax=Sb=!!Sb,r.ajaxTransport(function(b){var c,d;if(o.cors||Sb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Rb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("