├── .gitignore ├── .nlint.json ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── build ├── build.js ├── clean.sh ├── full.sh ├── headers.txt ├── libs.js ├── lint.js └── test.js ├── demo ├── .nlint.json ├── counter │ ├── css.css │ ├── index.html │ ├── jquery.js │ ├── js.js │ └── textarea.js ├── css.css ├── index.html ├── jquery.js ├── js.js └── textarea.js ├── index.js ├── lib ├── AtRule.js ├── CSSTree.js ├── Comment.js ├── Position.js ├── Rule.js └── Selector.js ├── package.json └── test ├── munit.js ├── positions ├── box-model │ ├── sheet.css │ └── tree.js ├── compressed-media │ ├── sheet.css │ └── tree.js ├── compressed │ ├── sheet.css │ └── tree.js ├── media │ ├── sheet.css │ └── tree.js └── nested-comments │ ├── sheet.css │ └── tree.js ├── sheets ├── box-model │ ├── sheet.css │ └── tree.js ├── comment-ie5-mac │ ├── sheet.css │ └── tree.js ├── complex-properties │ ├── sheet.css │ └── tree.js ├── complex-selector │ ├── sheet.css │ └── tree.js ├── escapables │ ├── sheet.css │ └── tree.js ├── imports │ ├── sheet.css │ └── tree.js ├── media-empty │ ├── sheet.css │ └── tree.js ├── media │ ├── sheet.css │ └── tree.js ├── nested-escape │ ├── sheet.css │ └── tree.js ├── opacity-hell │ ├── sheet.css │ └── tree.js ├── preserve-newline │ ├── sheet.css │ └── tree.js ├── preserve-string │ ├── sheet.css │ └── tree.js ├── semi-colons │ ├── sheet.css │ └── tree.js ├── simple │ ├── sheet.css │ └── tree.js └── star-underscore │ ├── sheet.css │ └── tree.js ├── test-AtRule.js ├── test-CSSTree.js ├── test-Comment.js ├── test-Position.js ├── test-Rule.js ├── test-Selector.js └── test-files.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/results 3 | dist/ 4 | demo/CSSTree.js 5 | -------------------------------------------------------------------------------- /.nlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": [ 3 | "test/*.css", 4 | ".git/", 5 | "node_modules/", 6 | "dist/", 7 | "demo/CSSTree.js" 8 | ], 9 | "linters": { 10 | "jshint": { 11 | "node": true 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.11" 4 | - "0.10" 5 | - "0.8" 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v0.0.3 2 | 3 | Installed StringIterator utility to replace manual loops 4 | 5 | 6 | ## v0.0.2 7 | 8 | **Bug Fixes** 9 | * **[Issue #1](https://github.com/codenothing/CSSTree/pull/1)**: Fix global variable leakage 10 | * **[Issue #2](https://github.com/codenothing/CSSTree/pull/2)**: Better handling of escaped characters in nested blocks 11 | 12 | 13 | ## v0.0.1 14 | 15 | Initial Release 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2013 Corey Hart 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all test 2 | 3 | all: build 4 | 5 | clean: 6 | @./build/clean.sh 7 | 8 | lint: 9 | @node build/lint.js 10 | 11 | build: clean lint 12 | @node build/build.js 13 | 14 | test: build 15 | @node build/test.js 16 | 17 | test-all: 18 | @NODE_TEST_NO_SKIP=1 make test 19 | 20 | test-full: 21 | @./build/full.sh 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSSTree 2 | 3 | CSS AST Builder 4 | 5 | [![NPM version](https://badge.fury.io/js/csstree.png)](http://badge.fury.io/js/csstree) 6 | [![Build Status](https://travis-ci.org/codenothing/CSSTree.png?branch=master)](https://travis-ci.org/codenothing/CSSTree) 7 | [![Code Climate](https://codeclimate.com/github/codenothing/CSSTree.png)](https://codeclimate.com/github/codenothing/CSSTree) 8 | 9 | ### Installation 10 | 11 | ```bash 12 | $ npm install csstree 13 | ``` 14 | 15 | CSSTree may also be run in a browser enviornment. 16 | 17 | ```html 18 | 19 | ``` 20 | 21 | 22 | ### Usage 23 | 24 | ```js 25 | var instance = new CSSTree( css ); 26 | 27 | // CSS Tree 28 | console.log( instance.branches ); 29 | ``` 30 | 31 | 32 | ### Example 33 | 34 | ```js 35 | var instance = new CSSTree( "html body { background: red; margin: 10px 5px; }" ); 36 | 37 | console.log( instance.branches ); 38 | ``` 39 | 40 | Will give an object format of the following: 41 | 42 | ```js 43 | { 44 | selector: 'html body', 45 | parts: [ 46 | 'html', 47 | 'body' 48 | ], 49 | rules: [ 50 | { 51 | property: 'background', 52 | value: 'red', 53 | parts: [ 54 | 'red' 55 | ] 56 | }, 57 | { 58 | property: 'margin', 59 | value: '10px 5px', 60 | parts: [ 61 | '10px', 62 | '5px' 63 | ] 64 | } 65 | ] 66 | } 67 | ``` 68 | 69 | 70 | 71 | ### Position Objects 72 | 73 | Every selector, rule, atrule and comment includes a 'Position' object which contains useful 74 | information about that fragments section of the stylesheet. Comes in the following form: 75 | 76 | ```js 77 | { 78 | property: 'background', 79 | value: 'red', 80 | parts: [ 81 | 'red' 82 | ], 83 | position: { 84 | range: { 85 | start: 40, 86 | end: 60, 87 | length: 20 88 | }, 89 | start: { 90 | line: 2, 91 | character: 2 92 | }, 93 | end: { 94 | line: 2, 95 | character: 22 96 | }, 97 | chunks: [ 98 | { 99 | start: 40, 100 | end: 60, 101 | length: 20 102 | } 103 | ] 104 | } 105 | } 106 | ``` 107 | 108 | * **range**: Contains the start and end indexes of the fragment within the stylesheet 109 | * **start**: Contains the starting line/character info of the fragment based on line breaks (\r\n|\r|\n) 110 | * **end**: Contains the ending line/character info of the fragment based on line breaks (\r\n|\r|\n) 111 | * **chunks**: When a comment exists between the start & end indexes, chunks represents only the sections that belong to this position. 112 | 113 | 114 | ### License 115 | 116 | ``` 117 | The MIT License 118 | 119 | Copyright (c) 2013 Corey Hart 120 | 121 | Permission is hereby granted, free of charge, to any person obtaining a copy 122 | of this software and associated documentation files (the "Software"), to deal 123 | in the Software without restriction, including without limitation the rights 124 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 125 | copies of the Software, and to permit persons to whom the Software is 126 | furnished to do so, subject to the following conditions: 127 | 128 | The above copyright notice and this permission notice shall be included in 129 | all copies or substantial portions of the Software. 130 | 131 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 132 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 133 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 134 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 135 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 136 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 137 | THE SOFTWARE. 138 | ``` 139 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | var fs = require( 'fs' ), 2 | async = require( 'async' ), 3 | libs = require( './libs.js' ), 4 | StringIterator = require( "string-iterator" ), 5 | ROOT_DIR = __dirname + '/../', 6 | LIB_DIR = ROOT_DIR + 'lib/', 7 | DIST_DIR = ROOT_DIR + 'dist/', 8 | DEMO_DIR = ROOT_DIR + 'demo/'; 9 | 10 | 11 | libs.unshift( 'headers.txt', 'CSSTree.js' ); 12 | libs.unshift( StringIterator ); 13 | async.map( libs, 14 | function( file, callback ) { 15 | if ( file === StringIterator ) { 16 | StringIterator.exportScript( callback ); 17 | } 18 | else { 19 | fs.readFile( ( file == 'headers.txt' ? __dirname + '/' : LIB_DIR ) + file, 'utf8', callback ); 20 | } 21 | }, 22 | function( e, results ) { 23 | if ( e ) { 24 | throw e; 25 | } 26 | 27 | var contents = results.shift() + results.shift(); 28 | while ( results.length ) { 29 | contents += "(function( global, undefined ) {\n\n" + 30 | results.shift() + 31 | "\n\n})( this );" + 32 | ( results.length ? "\n\n" : "" ); 33 | } 34 | 35 | async.map( [ DIST_DIR, DEMO_DIR ], 36 | function( dir, callback ) { 37 | fs.exists( dir, function( exists ) { 38 | if ( exists ) { 39 | fs.writeFile( dir + 'CSSTree.js', contents, 'utf8', callback ); 40 | } 41 | else { 42 | fs.mkdir( dir, function( e ) { 43 | if ( e ) { 44 | throw e; 45 | } 46 | 47 | fs.writeFile( dir + 'CSSTree.js', contents, 'utf8', callback ); 48 | }); 49 | } 50 | }); 51 | }, 52 | function( e ) { 53 | if ( e ) { 54 | throw e; 55 | } 56 | 57 | console.log( "\n\nCSSTree Built Out.\n\n\n" ); 58 | } 59 | ); 60 | } 61 | ); 62 | -------------------------------------------------------------------------------- /build/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd `dirname $0` 3 | cd ../ 4 | 5 | # Clean out test results 6 | if [ -d build/results/ ]; then 7 | rm -rf build/results/ 8 | fi 9 | 10 | # Build result 11 | if [ -d dist/ ]; then 12 | rm -rf dist/ 13 | fi 14 | 15 | # Demo result 16 | if [ -f demo/CSSTree.js ]; then 17 | rm demo/CSSTree.js 18 | fi 19 | -------------------------------------------------------------------------------- /build/full.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd `dirname $0` 3 | cd ../ 4 | SRCROOT=${PWD} 5 | 6 | # Clean out and rebuild before running through each enviorment 7 | make clean 8 | 9 | echo "===== NVM DIR::: $NVM_DIR ====" 10 | 11 | # Find each availiable node version and test with that version 12 | for i in $( ls $NVM_DIR ) 13 | do 14 | if [[ $i =~ ^v ]]; then 15 | echo "" 16 | echo "" 17 | echo "=== Node $i ===" 18 | echo "" 19 | 20 | # Run test suite 21 | "$NVM_DIR/$i/bin/node" "$SRCROOT/build/test.js" 22 | 23 | # Any non successful exit should be treated as full error 24 | RESULT=$? 25 | if [[ $RESULT != 0 ]]; then 26 | exit 1 27 | fi 28 | fi 29 | done 30 | -------------------------------------------------------------------------------- /build/headers.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * CSSTree 0.0.3 3 | * Corey Hart @ http://www.codenothing.com 4 | * MIT License http://www.codenothing.com/license 5 | */ 6 | -------------------------------------------------------------------------------- /build/libs.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | 'Position.js', 3 | 'Comment.js', 4 | 'AtRule.js', 5 | 'Rule.js', 6 | 'Selector.js' 7 | ]; 8 | -------------------------------------------------------------------------------- /build/lint.js: -------------------------------------------------------------------------------- 1 | require( 'nlint' ).render( __dirname + '/../' ); 2 | -------------------------------------------------------------------------------- /build/test.js: -------------------------------------------------------------------------------- 1 | var munit = global.munit = require( 'munit' ); 2 | 3 | // Only stop test suite when running make test 4 | if ( ! process.env.NODE_TEST_NO_SKIP ) { 5 | munit.defaults.settings.stopOnFail = true; 6 | } 7 | 8 | // Run tests 9 | munit.render( __dirname + '/../test/', { 10 | results: __dirname + '/results/' 11 | }); 12 | -------------------------------------------------------------------------------- /demo/.nlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignore": [ 3 | "jquery.js", 4 | "textarea.js", 5 | "counter/jquery.js", 6 | "counter/textarea.js" 7 | ], 8 | "linters": { 9 | "jshint": { 10 | "node": false, 11 | "browser": true 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /demo/counter/css.css: -------------------------------------------------------------------------------- 1 | * { 2 | -moz-box-sizing: border-box; 3 | -webkit-box-sizing: border-box; 4 | box-sizing: border-box; 5 | } 6 | 7 | html, body { 8 | font: 14px Helvetica; 9 | color: #333; 10 | background: #f5f5f5; 11 | padding: 0; 12 | margin: 0; 13 | height: 100%; 14 | text-shadow: 0 1px 0 #eee; 15 | } 16 | 17 | h1 { 18 | width: 75%; 19 | line-height: 30px; 20 | margin: 20px auto 0; 21 | padding: 0; 22 | font-size: 18px; 23 | } 24 | 25 | textarea { 26 | display: block; 27 | width: 75%; 28 | height: 400px; 29 | margin: 0 auto 10px; 30 | } 31 | 32 | form { 33 | display: block; 34 | margin: 0 auto; 35 | width: 75%; 36 | } 37 | 38 | form input[type=text] { 39 | width: 100px; 40 | } 41 | -------------------------------------------------------------------------------- /demo/counter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CSSTree Counter 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

CSSTree Counter

12 | 13 |
14 | Position: 0
15 | Start:
16 | End:
17 | 18 |
19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /demo/counter/js.js: -------------------------------------------------------------------------------- 1 | window.jQuery(function( jQuery ) { 2 | var alert = window.alert, 3 | textbox = jQuery( 'textarea' ), 4 | selectStart = jQuery( 'input[name=start]' ), 5 | selectEnd = jQuery( 'input[name=end]' ), 6 | positionInfo = jQuery( '#position' ); 7 | 8 | // Highlighting input ranges 9 | function select( start, end ) { 10 | var element = textbox[ 0 ], range; 11 | 12 | if ( start >= end ) { 13 | alert( 'Start Must Be Less Than End' ); 14 | return; 15 | } 16 | else if ( element.createTextRange ) { 17 | range = element.createTextRange(); 18 | range.collapse( true ); 19 | range.moveStart( 'character', start ); 20 | range.moveEnd( 'character', end ); 21 | range.select(); 22 | } 23 | else if ( element.setSelectionRange ) { 24 | element.setSelectionRange( start, end ); 25 | } 26 | else if ( element.selectionStart ) { 27 | element.selectionStart = start; 28 | element.selectionEnd = end; 29 | } 30 | } 31 | 32 | // Scroll text area to highlighted section (centered if possible) 33 | function scroll(){ 34 | var current = textbox.scrollTop(), 35 | caret = textbox.textareaHelper( 'caretPos' ).top, 36 | height = textbox.height(), 37 | ypos = current + caret - parseInt( height / 2, 10 ); 38 | 39 | if ( ypos < 0 ) { 40 | ypos = 0; 41 | } 42 | 43 | textbox.scrollTop( ypos ); 44 | } 45 | 46 | // Greps the current caret position in relation to the string in the textbox (not x,y coord) 47 | function caretPos(){ 48 | var element = textbox[ 0 ], pos = 0; 49 | 50 | if ( element.selectionStart ) { 51 | pos = element.selectionStart; 52 | } 53 | 54 | return pos; 55 | } 56 | 57 | // Update character position info 58 | function updatePosition(){ 59 | positionInfo.html( caretPos() ); 60 | } 61 | 62 | // Update caret position on any user action 63 | textbox.on( 'keyup', updatePosition ) 64 | .on( 'click', updatePosition ) 65 | .on( 'focus', updatePosition ); 66 | 67 | // Watch for highlight trigger 68 | jQuery( 'form' ).on( 'submit', function( event ) { 69 | select( 70 | parseInt( selectStart.val() || '0', 10 ), 71 | parseInt( selectEnd.val() || '0', 10 ) + 1 72 | ); 73 | 74 | scroll(); 75 | return false; 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /demo/counter/textarea.js: -------------------------------------------------------------------------------- 1 | // Textarea Helper from Codecademy 2 | // https://github.com/Codecademy/textarea-helper 3 | (function($) { 4 | var caretClass = 'textarea-helper-caret', 5 | dataKey = 'textarea-helper' 6 | 7 | // Styles that could influence size of the mirrored element. 8 | , 9 | mirrorStyles = [ 10 | // Box Styles. 11 | 'box-sizing', 'height', 'width', 'padding-bottom', 'padding-left', 'padding-right', 'padding-top' 12 | 13 | // Font stuff. 14 | , 15 | 'font-family', 'font-size', 'font-style', 'font-variant', 'font-weight' 16 | 17 | // Spacing etc. 18 | , 19 | 'word-spacing', 'letter-spacing', 'line-height', 'text-decoration', 'text-indent', 'text-transform']; 20 | 21 | var TextareaHelper = function(elem) { 22 | if (elem.nodeName.toLowerCase() !== 'textarea') return; 23 | this.$text = $(elem); 24 | this.$mirror = $('
') 25 | .css({ 26 | 'position': 'absolute', 27 | 'overflow': 'auto', 28 | 'white-space': 'pre-wrap', 29 | 'word-wrap': 'break-word', 30 | 'top': 0, 31 | 'left': -9999 32 | }) 33 | .insertAfter(this.$text); 34 | }; 35 | 36 | (function() { 37 | this.update = function() { 38 | 39 | // Copy styles. 40 | var styles = {}; 41 | for (var i = 0, style; style = mirrorStyles[i]; i++) { 42 | styles[style] = this.$text.css(style); 43 | } 44 | this.$mirror.css(styles) 45 | .empty(); 46 | 47 | // Update content and insert caret. 48 | var caretPos = this.getOriginalCaretPos(), 49 | str = this.$text.val(), 50 | pre = document.createTextNode(str.substring(0, caretPos)), 51 | post = document.createTextNode(str.substring(caretPos)), 52 | $car = $('') 53 | .addClass(caretClass) 54 | .html(' '); 55 | this.$mirror.append(pre, $car, post) 56 | .scrollTop(this.$text.scrollTop()); 57 | }; 58 | 59 | this.destroy = function() { 60 | this.$mirror.remove(); 61 | this.$text.removeData(dataKey); 62 | return null; 63 | }; 64 | 65 | this.caretPos = function() { 66 | this.update(); 67 | return this.$mirror.find('.' + caretClass) 68 | .position(); 69 | }; 70 | 71 | this.height = function() { 72 | this.update(); 73 | this.$mirror.css('height', ''); 74 | return this.$mirror.height(); 75 | }; 76 | 77 | // XBrowser caret position 78 | // Adapted from http://stackoverflow.com/questions/263743/how-to-get-caret-position-in-textarea 79 | this.getOriginalCaretPos = function() { 80 | var text = this.$text[0]; 81 | if (text.selectionStart) { 82 | return text.selectionStart; 83 | } else if (document.selection) { 84 | text.focus(); 85 | var r = document.selection.createRange(); 86 | if (r == null) { 87 | return 0; 88 | } 89 | var re = text.createTextRange(), 90 | rc = re.duplicate(); 91 | re.moveToBookmark(r.getBookmark()); 92 | rc.setEndPoint('EndToStart', re); 93 | return rc.text.length; 94 | } 95 | return 0; 96 | }; 97 | 98 | }) 99 | .call(TextareaHelper.prototype); 100 | 101 | $.fn.textareaHelper = function(method) { 102 | this.each(function() { 103 | var $this = $(this), 104 | instance = $this.data(dataKey); 105 | if (!instance) { 106 | instance = new TextareaHelper(this); 107 | $this.data(dataKey, instance); 108 | } 109 | }); 110 | if (method) { 111 | var instance = this.first() 112 | .data(dataKey); 113 | return instance[method](); 114 | } else { 115 | return this; 116 | } 117 | }; 118 | 119 | })(jQuery); 120 | -------------------------------------------------------------------------------- /demo/css.css: -------------------------------------------------------------------------------- 1 | * { 2 | -moz-box-sizing: border-box; 3 | -webkit-box-sizing: border-box; 4 | box-sizing: border-box; 5 | } 6 | 7 | html, body { 8 | font: 14px Helvetica; 9 | color: #333; 10 | background: #f5f5f5; 11 | padding: 0; 12 | margin: 0; 13 | height: 100%; 14 | text-shadow: 0 1px 0 #eee; 15 | } 16 | 17 | .hide { 18 | display: none !important; 19 | } 20 | 21 | #body { 22 | width: 80%; 23 | min-width: 900px; 24 | margin: 40px auto; 25 | } 26 | 27 | h2 { 28 | margin: 0; 29 | padding: 10px 0; 30 | } 31 | 32 | .content { 33 | position: relative; 34 | width: 100%; 35 | height: 400px; 36 | } 37 | 38 | textarea { 39 | width: 100%; 40 | height: 100%; 41 | border: 1px solid #737373; 42 | } 43 | 44 | pre { 45 | display: block; 46 | position: absolute; 47 | top: 0; 48 | right: 0; 49 | width: 49.8%; 50 | height: 100%; 51 | overflow: auto; 52 | border: 1px solid #737373; 53 | background: #e3fbfd; 54 | margin: 0; 55 | padding: 4px; 56 | } 57 | 58 | .content.active textarea { 59 | width: 49.8%; 60 | } 61 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CSS Tree 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |

CSS Tree

15 |
16 | 17 |

18 | 	
19 | 20 | 23 | 26 |
27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /demo/jquery.js: -------------------------------------------------------------------------------- 1 | 2 | /*! jQuery v1.9.0 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license */(function(e,t){"use strict";function n(e){var t=e.length,n=st.type(e);return st.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}function r(e){var t=Tt[e]={};return st.each(e.match(lt)||[],function(e,n){t[n]=!0}),t}function i(e,n,r,i){if(st.acceptData(e)){var o,a,s=st.expando,u="string"==typeof n,l=e.nodeType,c=l?st.cache:e,f=l?e[s]:e[s]&&s;if(f&&c[f]&&(i||c[f].data)||!u||r!==t)return f||(l?e[s]=f=K.pop()||st.guid++:f=s),c[f]||(c[f]={},l||(c[f].toJSON=st.noop)),("object"==typeof n||"function"==typeof n)&&(i?c[f]=st.extend(c[f],n):c[f].data=st.extend(c[f].data,n)),o=c[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[st.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[st.camelCase(n)])):a=o,a}}function o(e,t,n){if(st.acceptData(e)){var r,i,o,a=e.nodeType,u=a?st.cache:e,l=a?e[st.expando]:st.expando;if(u[l]){if(t&&(r=n?u[l]:u[l].data)){st.isArray(t)?t=t.concat(st.map(t,st.camelCase)):t in r?t=[t]:(t=st.camelCase(t),t=t in r?[t]:t.split(" "));for(i=0,o=t.length;o>i;i++)delete r[t[i]];if(!(n?s:st.isEmptyObject)(r))return}(n||(delete u[l].data,s(u[l])))&&(a?st.cleanData([e],!0):st.support.deleteExpando||u!=u.window?delete u[l]:u[l]=null)}}}function a(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(Nt,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:wt.test(r)?st.parseJSON(r):r}catch(o){}st.data(e,n,r)}else r=t}return r}function s(e){var t;for(t in e)if(("data"!==t||!st.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function u(){return!0}function l(){return!1}function c(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function f(e,t,n){if(t=t||0,st.isFunction(t))return st.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return st.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=st.grep(e,function(e){return 1===e.nodeType});if(Wt.test(t))return st.filter(t,r,!n);t=st.filter(t,r)}return st.grep(e,function(e){return st.inArray(e,t)>=0===n})}function p(e){var t=zt.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function d(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function h(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function g(e){var t=nn.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function m(e,t){for(var n,r=0;null!=(n=e[r]);r++)st._data(n,"globalEval",!t||st._data(t[r],"globalEval"))}function y(e,t){if(1===t.nodeType&&st.hasData(e)){var n,r,i,o=st._data(e),a=st._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)st.event.add(t,n,s[n][r])}a.data&&(a.data=st.extend({},a.data))}}function v(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!st.support.noCloneEvent&&t[st.expando]){r=st._data(t);for(i in r.events)st.removeEvent(t,i,r.handle);t.removeAttribute(st.expando)}"script"===n&&t.text!==e.text?(h(t).text=e.text,g(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),st.support.html5Clone&&e.innerHTML&&!st.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Zt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}function b(e,n){var r,i,o=0,a=e.getElementsByTagName!==t?e.getElementsByTagName(n||"*"):e.querySelectorAll!==t?e.querySelectorAll(n||"*"):t;if(!a)for(a=[],r=e.childNodes||e;null!=(i=r[o]);o++)!n||st.nodeName(i,n)?a.push(i):st.merge(a,b(i,n));return n===t||n&&st.nodeName(e,n)?st.merge([e],a):a}function x(e){Zt.test(e.type)&&(e.defaultChecked=e.checked)}function T(e,t){if(t in e)return t;for(var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Nn.length;i--;)if(t=Nn[i]+n,t in e)return t;return r}function w(e,t){return e=t||e,"none"===st.css(e,"display")||!st.contains(e.ownerDocument,e)}function N(e,t){for(var n,r=[],i=0,o=e.length;o>i;i++)n=e[i],n.style&&(r[i]=st._data(n,"olddisplay"),t?(r[i]||"none"!==n.style.display||(n.style.display=""),""===n.style.display&&w(n)&&(r[i]=st._data(n,"olddisplay",S(n.nodeName)))):r[i]||w(n)||st._data(n,"olddisplay",st.css(n,"display")));for(i=0;o>i;i++)n=e[i],n.style&&(t&&"none"!==n.style.display&&""!==n.style.display||(n.style.display=t?r[i]||"":"none"));return e}function C(e,t,n){var r=mn.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function k(e,t,n,r,i){for(var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;4>o;o+=2)"margin"===n&&(a+=st.css(e,n+wn[o],!0,i)),r?("content"===n&&(a-=st.css(e,"padding"+wn[o],!0,i)),"margin"!==n&&(a-=st.css(e,"border"+wn[o]+"Width",!0,i))):(a+=st.css(e,"padding"+wn[o],!0,i),"padding"!==n&&(a+=st.css(e,"border"+wn[o]+"Width",!0,i)));return a}function E(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=ln(e),a=st.support.boxSizing&&"border-box"===st.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=un(e,t,o),(0>i||null==i)&&(i=e.style[t]),yn.test(i))return i;r=a&&(st.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+k(e,t,n||(a?"border":"content"),r,o)+"px"}function S(e){var t=V,n=bn[e];return n||(n=A(e,t),"none"!==n&&n||(cn=(cn||st("