publish~
diff --git a/.gitignore b/.gitignore
index 0e50252..d8c1578 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,164 @@
-dep/
+#################
+## Eclipse 
+#################
+
+*.pydevproject
+.project
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+.svn
+local.properties
+.classpath
+.settings/
+.loadpath
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath
+
+
+#################
+## Visual Studio
+#################
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+[Dd]ebug/
+[Rr]elease/
+*_i.c
+*_p.c
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.vspscc
+.builds
+*.dotCover
+
+## TODO: If you have NuGet Package Restore enabled, uncomment this
+#packages/
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+
+# Visual Studio profiler
+*.psess
+*.vsp
+
+# ReSharper is a .NET coding add-in
+_ReSharper*
+
+# Installshield output folder
+[Ee]xpress
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish
+
+# Others
+[Bb]in
+[Oo]bj
+sql
+TestResults
+*.Cache
+ClientBin
+stylecop.*
+~$*
+*.dbmdl
+Generated_Code #added for RIA/Silverlight projects
+
+# Backup & report files from converting an old project file to a newer
+# Visual Studio version. Backup files are not needed, because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+
+
+
+############
+## Windows
+############
+
+# Windows image file caches
+Thumbs.db
+
+# Folder config file
+Desktop.ini
+
+
+#############
+## Python
+#############
+
+*.py[co]
+
+# Packages
+*.egg
+*.egg-info
+dist
+build
+eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+
+#Translations
+*.mo
+
+#Mr Developer
+.mr.developer.cfg
+
+# Mac crap
+.DS_Store
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..68bc978
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,65 @@
+{
+    "bitwise": false,
+    "camelcase": true,
+    "curly": true,
+    "eqeqeq": false,
+    "forin": false,
+    "immed": true,
+    "latedef": false,
+    "newcap": true,
+    "noarg": false,
+    "noempty": true,
+    "nonew": true,
+    "plusplus": false,
+    "quotmark": "single",
+    "regexp": false,
+    "undef": false,
+    "unused": true,
+    "strict": false,
+    "trailing": false,
+    "maxparams": 20,
+    "maxdepth": 6,
+    "maxlen": 80,
+
+    "asi": false,
+    "boss": false,
+    "debug": false,
+    "eqnull": true,
+    "esnext": false,
+    "evil": true,
+    "expr": true,
+    "funcscope": false,
+    "globalstrict": false,
+    "iterator": false,
+    "lastsemic": false,
+    "laxbreak": true,
+    "laxcomma": false,
+    "loopfunc": false,
+    "multistr": false,
+    "onecase": false,
+    "proto": false,
+    "regexdash": false,
+    "scripturl": false,
+    "smarttabs": false,
+    "shadow": true,
+    "sub": true,
+    "supernew": false,
+    "validthis": true,
+
+    "browser": true,
+    "couch": false,
+    "devel": true,
+    "dojo": false,
+    "jquery": true,
+    "mootools": false,
+    "node": false,
+    "nonstandard": false,
+    "prototypejs": false,
+    "rhino": false,
+    "wsh": false,
+
+    "nomen": false,
+    "onevar": false,
+    "passfail": false,
+    "white": false
+}
\ No newline at end of file
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..9723a0c
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,28 @@
+Copyright (c) 2013, Baidu Inc.
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms, with or 
+without modification, are permitted provided that the following conditions 
+are met:
+
+Redistributions of source code must retain the above copyright notice, this 
+list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, 
+this list of conditions and the following disclaimer in the documentation 
+and/or other materials provided with the distribution.
+
+Neither the name of Baidu Inc. nor the names of its contributors may be used
+to endorse or promote products derived from this software without specific 
+prior written permission of Baidu Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/doc/asset/css/bootstrap-responsive.css b/doc/asset/css/bootstrap-responsive.css
new file mode 100644
index 0000000..fcd72f7
--- /dev/null
+++ b/doc/asset/css/bootstrap-responsive.css
@@ -0,0 +1,1109 @@
+/*!
+ * Bootstrap Responsive v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+
+.clearfix {
+  *zoom: 1;
+}
+
+.clearfix:before,
+.clearfix:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.clearfix:after {
+  clear: both;
+}
+
+.hide-text {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.input-block-level {
+  display: block;
+  width: 100%;
+  min-height: 30px;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+@-ms-viewport {
+  width: device-width;
+}
+
+.hidden {
+  display: none;
+  visibility: hidden;
+}
+
+.visible-phone {
+  display: none !important;
+}
+
+.visible-tablet {
+  display: none !important;
+}
+
+.hidden-desktop {
+  display: none !important;
+}
+
+.visible-desktop {
+  display: inherit !important;
+}
+
+@media (min-width: 768px) and (max-width: 979px) {
+  .hidden-desktop {
+    display: inherit !important;
+  }
+  .visible-desktop {
+    display: none !important ;
+  }
+  .visible-tablet {
+    display: inherit !important;
+  }
+  .hidden-tablet {
+    display: none !important;
+  }
+}
+
+@media (max-width: 767px) {
+  .hidden-desktop {
+    display: inherit !important;
+  }
+  .visible-desktop {
+    display: none !important;
+  }
+  .visible-phone {
+    display: inherit !important;
+  }
+  .hidden-phone {
+    display: none !important;
+  }
+}
+
+.visible-print {
+  display: none !important;
+}
+
+@media print {
+  .visible-print {
+    display: inherit !important;
+  }
+  .hidden-print {
+    display: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .row {
+    margin-left: -30px;
+    *zoom: 1;
+  }
+  .row:before,
+  .row:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row:after {
+    clear: both;
+  }
+  [class*="span"] {
+    float: left;
+    min-height: 1px;
+    margin-left: 30px;
+  }
+  .container,
+  .navbar-static-top .container,
+  .navbar-fixed-top .container,
+  .navbar-fixed-bottom .container {
+    width: 1170px;
+  }
+  .span12 {
+    width: 1170px;
+  }
+  .span11 {
+    width: 1070px;
+  }
+  .span10 {
+    width: 970px;
+  }
+  .span9 {
+    width: 870px;
+  }
+  .span8 {
+    width: 770px;
+  }
+  .span7 {
+    width: 670px;
+  }
+  .span6 {
+    width: 570px;
+  }
+  .span5 {
+    width: 470px;
+  }
+  .span4 {
+    width: 370px;
+  }
+  .span3 {
+    width: 270px;
+  }
+  .span2 {
+    width: 170px;
+  }
+  .span1 {
+    width: 70px;
+  }
+  .offset12 {
+    margin-left: 1230px;
+  }
+  .offset11 {
+    margin-left: 1130px;
+  }
+  .offset10 {
+    margin-left: 1030px;
+  }
+  .offset9 {
+    margin-left: 930px;
+  }
+  .offset8 {
+    margin-left: 830px;
+  }
+  .offset7 {
+    margin-left: 730px;
+  }
+  .offset6 {
+    margin-left: 630px;
+  }
+  .offset5 {
+    margin-left: 530px;
+  }
+  .offset4 {
+    margin-left: 430px;
+  }
+  .offset3 {
+    margin-left: 330px;
+  }
+  .offset2 {
+    margin-left: 230px;
+  }
+  .offset1 {
+    margin-left: 130px;
+  }
+  .row-fluid {
+    width: 100%;
+    *zoom: 1;
+  }
+  .row-fluid:before,
+  .row-fluid:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row-fluid:after {
+    clear: both;
+  }
+  .row-fluid [class*="span"] {
+    display: block;
+    float: left;
+    width: 100%;
+    min-height: 30px;
+    margin-left: 2.564102564102564%;
+    *margin-left: 2.5109110747408616%;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .row-fluid [class*="span"]:first-child {
+    margin-left: 0;
+  }
+  .row-fluid .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 2.564102564102564%;
+  }
+  .row-fluid .span12 {
+    width: 100%;
+    *width: 99.94680851063829%;
+  }
+  .row-fluid .span11 {
+    width: 91.45299145299145%;
+    *width: 91.39979996362975%;
+  }
+  .row-fluid .span10 {
+    width: 82.90598290598291%;
+    *width: 82.8527914166212%;
+  }
+  .row-fluid .span9 {
+    width: 74.35897435897436%;
+    *width: 74.30578286961266%;
+  }
+  .row-fluid .span8 {
+    width: 65.81196581196582%;
+    *width: 65.75877432260411%;
+  }
+  .row-fluid .span7 {
+    width: 57.26495726495726%;
+    *width: 57.21176577559556%;
+  }
+  .row-fluid .span6 {
+    width: 48.717948717948715%;
+    *width: 48.664757228587014%;
+  }
+  .row-fluid .span5 {
+    width: 40.17094017094017%;
+    *width: 40.11774868157847%;
+  }
+  .row-fluid .span4 {
+    width: 31.623931623931625%;
+    *width: 31.570740134569924%;
+  }
+  .row-fluid .span3 {
+    width: 23.076923076923077%;
+    *width: 23.023731587561375%;
+  }
+  .row-fluid .span2 {
+    width: 14.52991452991453%;
+    *width: 14.476723040552828%;
+  }
+  .row-fluid .span1 {
+    width: 5.982905982905983%;
+    *width: 5.929714493544281%;
+  }
+  .row-fluid .offset12 {
+    margin-left: 105.12820512820512%;
+    *margin-left: 105.02182214948171%;
+  }
+  .row-fluid .offset12:first-child {
+    margin-left: 102.56410256410257%;
+    *margin-left: 102.45771958537915%;
+  }
+  .row-fluid .offset11 {
+    margin-left: 96.58119658119658%;
+    *margin-left: 96.47481360247316%;
+  }
+  .row-fluid .offset11:first-child {
+    margin-left: 94.01709401709402%;
+    *margin-left: 93.91071103837061%;
+  }
+  .row-fluid .offset10 {
+    margin-left: 88.03418803418803%;
+    *margin-left: 87.92780505546462%;
+  }
+  .row-fluid .offset10:first-child {
+    margin-left: 85.47008547008548%;
+    *margin-left: 85.36370249136206%;
+  }
+  .row-fluid .offset9 {
+    margin-left: 79.48717948717949%;
+    *margin-left: 79.38079650845607%;
+  }
+  .row-fluid .offset9:first-child {
+    margin-left: 76.92307692307693%;
+    *margin-left: 76.81669394435352%;
+  }
+  .row-fluid .offset8 {
+    margin-left: 70.94017094017094%;
+    *margin-left: 70.83378796144753%;
+  }
+  .row-fluid .offset8:first-child {
+    margin-left: 68.37606837606839%;
+    *margin-left: 68.26968539734497%;
+  }
+  .row-fluid .offset7 {
+    margin-left: 62.393162393162385%;
+    *margin-left: 62.28677941443899%;
+  }
+  .row-fluid .offset7:first-child {
+    margin-left: 59.82905982905982%;
+    *margin-left: 59.72267685033642%;
+  }
+  .row-fluid .offset6 {
+    margin-left: 53.84615384615384%;
+    *margin-left: 53.739770867430444%;
+  }
+  .row-fluid .offset6:first-child {
+    margin-left: 51.28205128205128%;
+    *margin-left: 51.175668303327875%;
+  }
+  .row-fluid .offset5 {
+    margin-left: 45.299145299145295%;
+    *margin-left: 45.1927623204219%;
+  }
+  .row-fluid .offset5:first-child {
+    margin-left: 42.73504273504273%;
+    *margin-left: 42.62865975631933%;
+  }
+  .row-fluid .offset4 {
+    margin-left: 36.75213675213675%;
+    *margin-left: 36.645753773413354%;
+  }
+  .row-fluid .offset4:first-child {
+    margin-left: 34.18803418803419%;
+    *margin-left: 34.081651209310785%;
+  }
+  .row-fluid .offset3 {
+    margin-left: 28.205128205128204%;
+    *margin-left: 28.0987452264048%;
+  }
+  .row-fluid .offset3:first-child {
+    margin-left: 25.641025641025642%;
+    *margin-left: 25.53464266230224%;
+  }
+  .row-fluid .offset2 {
+    margin-left: 19.65811965811966%;
+    *margin-left: 19.551736679396257%;
+  }
+  .row-fluid .offset2:first-child {
+    margin-left: 17.094017094017094%;
+    *margin-left: 16.98763411529369%;
+  }
+  .row-fluid .offset1 {
+    margin-left: 11.11111111111111%;
+    *margin-left: 11.004728132387708%;
+  }
+  .row-fluid .offset1:first-child {
+    margin-left: 8.547008547008547%;
+    *margin-left: 8.440625568285142%;
+  }
+  input,
+  textarea,
+  .uneditable-input {
+    margin-left: 0;
+  }
+  .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 30px;
+  }
+  input.span12,
+  textarea.span12,
+  .uneditable-input.span12 {
+    width: 1156px;
+  }
+  input.span11,
+  textarea.span11,
+  .uneditable-input.span11 {
+    width: 1056px;
+  }
+  input.span10,
+  textarea.span10,
+  .uneditable-input.span10 {
+    width: 956px;
+  }
+  input.span9,
+  textarea.span9,
+  .uneditable-input.span9 {
+    width: 856px;
+  }
+  input.span8,
+  textarea.span8,
+  .uneditable-input.span8 {
+    width: 756px;
+  }
+  input.span7,
+  textarea.span7,
+  .uneditable-input.span7 {
+    width: 656px;
+  }
+  input.span6,
+  textarea.span6,
+  .uneditable-input.span6 {
+    width: 556px;
+  }
+  input.span5,
+  textarea.span5,
+  .uneditable-input.span5 {
+    width: 456px;
+  }
+  input.span4,
+  textarea.span4,
+  .uneditable-input.span4 {
+    width: 356px;
+  }
+  input.span3,
+  textarea.span3,
+  .uneditable-input.span3 {
+    width: 256px;
+  }
+  input.span2,
+  textarea.span2,
+  .uneditable-input.span2 {
+    width: 156px;
+  }
+  input.span1,
+  textarea.span1,
+  .uneditable-input.span1 {
+    width: 56px;
+  }
+  .thumbnails {
+    margin-left: -30px;
+  }
+  .thumbnails > li {
+    margin-left: 30px;
+  }
+  .row-fluid .thumbnails {
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 768px) and (max-width: 979px) {
+  .row {
+    margin-left: -20px;
+    *zoom: 1;
+  }
+  .row:before,
+  .row:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row:after {
+    clear: both;
+  }
+  [class*="span"] {
+    float: left;
+    min-height: 1px;
+    margin-left: 20px;
+  }
+  .container,
+  .navbar-static-top .container,
+  .navbar-fixed-top .container,
+  .navbar-fixed-bottom .container {
+    width: 724px;
+  }
+  .span12 {
+    width: 724px;
+  }
+  .span11 {
+    width: 662px;
+  }
+  .span10 {
+    width: 600px;
+  }
+  .span9 {
+    width: 538px;
+  }
+  .span8 {
+    width: 476px;
+  }
+  .span7 {
+    width: 414px;
+  }
+  .span6 {
+    width: 352px;
+  }
+  .span5 {
+    width: 290px;
+  }
+  .span4 {
+    width: 228px;
+  }
+  .span3 {
+    width: 166px;
+  }
+  .span2 {
+    width: 104px;
+  }
+  .span1 {
+    width: 42px;
+  }
+  .offset12 {
+    margin-left: 764px;
+  }
+  .offset11 {
+    margin-left: 702px;
+  }
+  .offset10 {
+    margin-left: 640px;
+  }
+  .offset9 {
+    margin-left: 578px;
+  }
+  .offset8 {
+    margin-left: 516px;
+  }
+  .offset7 {
+    margin-left: 454px;
+  }
+  .offset6 {
+    margin-left: 392px;
+  }
+  .offset5 {
+    margin-left: 330px;
+  }
+  .offset4 {
+    margin-left: 268px;
+  }
+  .offset3 {
+    margin-left: 206px;
+  }
+  .offset2 {
+    margin-left: 144px;
+  }
+  .offset1 {
+    margin-left: 82px;
+  }
+  .row-fluid {
+    width: 100%;
+    *zoom: 1;
+  }
+  .row-fluid:before,
+  .row-fluid:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row-fluid:after {
+    clear: both;
+  }
+  .row-fluid [class*="span"] {
+    display: block;
+    float: left;
+    width: 100%;
+    min-height: 30px;
+    margin-left: 2.7624309392265194%;
+    *margin-left: 2.709239449864817%;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .row-fluid [class*="span"]:first-child {
+    margin-left: 0;
+  }
+  .row-fluid .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 2.7624309392265194%;
+  }
+  .row-fluid .span12 {
+    width: 100%;
+    *width: 99.94680851063829%;
+  }
+  .row-fluid .span11 {
+    width: 91.43646408839778%;
+    *width: 91.38327259903608%;
+  }
+  .row-fluid .span10 {
+    width: 82.87292817679558%;
+    *width: 82.81973668743387%;
+  }
+  .row-fluid .span9 {
+    width: 74.30939226519337%;
+    *width: 74.25620077583166%;
+  }
+  .row-fluid .span8 {
+    width: 65.74585635359117%;
+    *width: 65.69266486422946%;
+  }
+  .row-fluid .span7 {
+    width: 57.18232044198895%;
+    *width: 57.12912895262725%;
+  }
+  .row-fluid .span6 {
+    width: 48.61878453038674%;
+    *width: 48.56559304102504%;
+  }
+  .row-fluid .span5 {
+    width: 40.05524861878453%;
+    *width: 40.00205712942283%;
+  }
+  .row-fluid .span4 {
+    width: 31.491712707182323%;
+    *width: 31.43852121782062%;
+  }
+  .row-fluid .span3 {
+    width: 22.92817679558011%;
+    *width: 22.87498530621841%;
+  }
+  .row-fluid .span2 {
+    width: 14.3646408839779%;
+    *width: 14.311449394616199%;
+  }
+  .row-fluid .span1 {
+    width: 5.801104972375691%;
+    *width: 5.747913483013988%;
+  }
+  .row-fluid .offset12 {
+    margin-left: 105.52486187845304%;
+    *margin-left: 105.41847889972962%;
+  }
+  .row-fluid .offset12:first-child {
+    margin-left: 102.76243093922652%;
+    *margin-left: 102.6560479605031%;
+  }
+  .row-fluid .offset11 {
+    margin-left: 96.96132596685082%;
+    *margin-left: 96.8549429881274%;
+  }
+  .row-fluid .offset11:first-child {
+    margin-left: 94.1988950276243%;
+    *margin-left: 94.09251204890089%;
+  }
+  .row-fluid .offset10 {
+    margin-left: 88.39779005524862%;
+    *margin-left: 88.2914070765252%;
+  }
+  .row-fluid .offset10:first-child {
+    margin-left: 85.6353591160221%;
+    *margin-left: 85.52897613729868%;
+  }
+  .row-fluid .offset9 {
+    margin-left: 79.8342541436464%;
+    *margin-left: 79.72787116492299%;
+  }
+  .row-fluid .offset9:first-child {
+    margin-left: 77.07182320441989%;
+    *margin-left: 76.96544022569647%;
+  }
+  .row-fluid .offset8 {
+    margin-left: 71.2707182320442%;
+    *margin-left: 71.16433525332079%;
+  }
+  .row-fluid .offset8:first-child {
+    margin-left: 68.50828729281768%;
+    *margin-left: 68.40190431409427%;
+  }
+  .row-fluid .offset7 {
+    margin-left: 62.70718232044199%;
+    *margin-left: 62.600799341718584%;
+  }
+  .row-fluid .offset7:first-child {
+    margin-left: 59.94475138121547%;
+    *margin-left: 59.838368402492065%;
+  }
+  .row-fluid .offset6 {
+    margin-left: 54.14364640883978%;
+    *margin-left: 54.037263430116376%;
+  }
+  .row-fluid .offset6:first-child {
+    margin-left: 51.38121546961326%;
+    *margin-left: 51.27483249088986%;
+  }
+  .row-fluid .offset5 {
+    margin-left: 45.58011049723757%;
+    *margin-left: 45.47372751851417%;
+  }
+  .row-fluid .offset5:first-child {
+    margin-left: 42.81767955801105%;
+    *margin-left: 42.71129657928765%;
+  }
+  .row-fluid .offset4 {
+    margin-left: 37.01657458563536%;
+    *margin-left: 36.91019160691196%;
+  }
+  .row-fluid .offset4:first-child {
+    margin-left: 34.25414364640884%;
+    *margin-left: 34.14776066768544%;
+  }
+  .row-fluid .offset3 {
+    margin-left: 28.45303867403315%;
+    *margin-left: 28.346655695309746%;
+  }
+  .row-fluid .offset3:first-child {
+    margin-left: 25.69060773480663%;
+    *margin-left: 25.584224756083227%;
+  }
+  .row-fluid .offset2 {
+    margin-left: 19.88950276243094%;
+    *margin-left: 19.783119783707537%;
+  }
+  .row-fluid .offset2:first-child {
+    margin-left: 17.12707182320442%;
+    *margin-left: 17.02068884448102%;
+  }
+  .row-fluid .offset1 {
+    margin-left: 11.32596685082873%;
+    *margin-left: 11.219583872105325%;
+  }
+  .row-fluid .offset1:first-child {
+    margin-left: 8.56353591160221%;
+    *margin-left: 8.457152932878806%;
+  }
+  input,
+  textarea,
+  .uneditable-input {
+    margin-left: 0;
+  }
+  .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 20px;
+  }
+  input.span12,
+  textarea.span12,
+  .uneditable-input.span12 {
+    width: 710px;
+  }
+  input.span11,
+  textarea.span11,
+  .uneditable-input.span11 {
+    width: 648px;
+  }
+  input.span10,
+  textarea.span10,
+  .uneditable-input.span10 {
+    width: 586px;
+  }
+  input.span9,
+  textarea.span9,
+  .uneditable-input.span9 {
+    width: 524px;
+  }
+  input.span8,
+  textarea.span8,
+  .uneditable-input.span8 {
+    width: 462px;
+  }
+  input.span7,
+  textarea.span7,
+  .uneditable-input.span7 {
+    width: 400px;
+  }
+  input.span6,
+  textarea.span6,
+  .uneditable-input.span6 {
+    width: 338px;
+  }
+  input.span5,
+  textarea.span5,
+  .uneditable-input.span5 {
+    width: 276px;
+  }
+  input.span4,
+  textarea.span4,
+  .uneditable-input.span4 {
+    width: 214px;
+  }
+  input.span3,
+  textarea.span3,
+  .uneditable-input.span3 {
+    width: 152px;
+  }
+  input.span2,
+  textarea.span2,
+  .uneditable-input.span2 {
+    width: 90px;
+  }
+  input.span1,
+  textarea.span1,
+  .uneditable-input.span1 {
+    width: 28px;
+  }
+}
+
+@media (max-width: 767px) {
+  body {
+    padding-right: 20px;
+    padding-left: 20px;
+  }
+  .navbar-fixed-top,
+  .navbar-fixed-bottom,
+  .navbar-static-top {
+    margin-right: -20px;
+    margin-left: -20px;
+  }
+  .container-fluid {
+    padding: 0;
+  }
+  .dl-horizontal dt {
+    float: none;
+    width: auto;
+    clear: none;
+    text-align: left;
+  }
+  .dl-horizontal dd {
+    margin-left: 0;
+  }
+  .container {
+    width: auto;
+  }
+  .row-fluid {
+    width: 100%;
+  }
+  .row,
+  .thumbnails {
+    margin-left: 0;
+  }
+  .thumbnails > li {
+    float: none;
+    margin-left: 0;
+  }
+  [class*="span"],
+  .uneditable-input[class*="span"],
+  .row-fluid [class*="span"] {
+    display: block;
+    float: none;
+    width: 100%;
+    margin-left: 0;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .span12,
+  .row-fluid .span12 {
+    width: 100%;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .row-fluid [class*="offset"]:first-child {
+    margin-left: 0;
+  }
+  .input-large,
+  .input-xlarge,
+  .input-xxlarge,
+  input[class*="span"],
+  select[class*="span"],
+  textarea[class*="span"],
+  .uneditable-input {
+    display: block;
+    width: 100%;
+    min-height: 30px;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .input-prepend input,
+  .input-append input,
+  .input-prepend input[class*="span"],
+  .input-append input[class*="span"] {
+    display: inline-block;
+    width: auto;
+  }
+  .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 0;
+  }
+  .modal {
+    position: fixed;
+    top: 20px;
+    right: 20px;
+    left: 20px;
+    width: auto;
+    margin: 0;
+  }
+  .modal.fade {
+    top: -100px;
+  }
+  .modal.fade.in {
+    top: 20px;
+  }
+}
+
+@media (max-width: 480px) {
+  .nav-collapse {
+    -webkit-transform: translate3d(0, 0, 0);
+  }
+  .page-header h1 small {
+    display: block;
+    line-height: 20px;
+  }
+  input[type="checkbox"],
+  input[type="radio"] {
+    border: 1px solid #ccc;
+  }
+  .form-horizontal .control-label {
+    float: none;
+    width: auto;
+    padding-top: 0;
+    text-align: left;
+  }
+  .form-horizontal .controls {
+    margin-left: 0;
+  }
+  .form-horizontal .control-list {
+    padding-top: 0;
+  }
+  .form-horizontal .form-actions {
+    padding-right: 10px;
+    padding-left: 10px;
+  }
+  .media .pull-left,
+  .media .pull-right {
+    display: block;
+    float: none;
+    margin-bottom: 10px;
+  }
+  .media-object {
+    margin-right: 0;
+    margin-left: 0;
+  }
+  .modal {
+    top: 10px;
+    right: 10px;
+    left: 10px;
+  }
+  .modal-header .close {
+    padding: 10px;
+    margin: -10px;
+  }
+  .carousel-caption {
+    position: static;
+  }
+}
+
+@media (max-width: 979px) {
+  body {
+    padding-top: 0;
+  }
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    position: static;
+  }
+  .navbar-fixed-top {
+    margin-bottom: 20px;
+  }
+  .navbar-fixed-bottom {
+    margin-top: 20px;
+  }
+  .navbar-fixed-top .navbar-inner,
+  .navbar-fixed-bottom .navbar-inner {
+    padding: 5px;
+  }
+  .navbar .container {
+    width: auto;
+    padding: 0;
+  }
+  .navbar .brand {
+    padding-right: 10px;
+    padding-left: 10px;
+    margin: 0 0 0 -5px;
+  }
+  .nav-collapse {
+    clear: both;
+  }
+  .nav-collapse .nav {
+    float: none;
+    margin: 0 0 10px;
+  }
+  .nav-collapse .nav > li {
+    float: none;
+  }
+  .nav-collapse .nav > li > a {
+    margin-bottom: 2px;
+  }
+  .nav-collapse .nav > .divider-vertical {
+    display: none;
+  }
+  .nav-collapse .nav .nav-header {
+    color: #777777;
+    text-shadow: none;
+  }
+  .nav-collapse .nav > li > a,
+  .nav-collapse .dropdown-menu a {
+    padding: 9px 15px;
+    font-weight: bold;
+    color: #777777;
+    -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+            border-radius: 3px;
+  }
+  .nav-collapse .btn {
+    padding: 4px 10px 4px;
+    font-weight: normal;
+    -webkit-border-radius: 4px;
+       -moz-border-radius: 4px;
+            border-radius: 4px;
+  }
+  .nav-collapse .dropdown-menu li + li a {
+    margin-bottom: 2px;
+  }
+  .nav-collapse .nav > li > a:hover,
+  .nav-collapse .nav > li > a:focus,
+  .nav-collapse .dropdown-menu a:hover,
+  .nav-collapse .dropdown-menu a:focus {
+    background-color: #f2f2f2;
+  }
+  .navbar-inverse .nav-collapse .nav > li > a,
+  .navbar-inverse .nav-collapse .dropdown-menu a {
+    color: #999999;
+  }
+  .navbar-inverse .nav-collapse .nav > li > a:hover,
+  .navbar-inverse .nav-collapse .nav > li > a:focus,
+  .navbar-inverse .nav-collapse .dropdown-menu a:hover,
+  .navbar-inverse .nav-collapse .dropdown-menu a:focus {
+    background-color: #111111;
+  }
+  .nav-collapse.in .btn-group {
+    padding: 0;
+    margin-top: 5px;
+  }
+  .nav-collapse .dropdown-menu {
+    position: static;
+    top: auto;
+    left: auto;
+    display: none;
+    float: none;
+    max-width: none;
+    padding: 0;
+    margin: 0 15px;
+    background-color: transparent;
+    border: none;
+    -webkit-border-radius: 0;
+       -moz-border-radius: 0;
+            border-radius: 0;
+    -webkit-box-shadow: none;
+       -moz-box-shadow: none;
+            box-shadow: none;
+  }
+  .nav-collapse .open > .dropdown-menu {
+    display: block;
+  }
+  .nav-collapse .dropdown-menu:before,
+  .nav-collapse .dropdown-menu:after {
+    display: none;
+  }
+  .nav-collapse .dropdown-menu .divider {
+    display: none;
+  }
+  .nav-collapse .nav > li > .dropdown-menu:before,
+  .nav-collapse .nav > li > .dropdown-menu:after {
+    display: none;
+  }
+  .nav-collapse .navbar-form,
+  .nav-collapse .navbar-search {
+    float: none;
+    padding: 10px 15px;
+    margin: 10px 0;
+    border-top: 1px solid #f2f2f2;
+    border-bottom: 1px solid #f2f2f2;
+    -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+       -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+            box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+  }
+  .navbar-inverse .nav-collapse .navbar-form,
+  .navbar-inverse .nav-collapse .navbar-search {
+    border-top-color: #111111;
+    border-bottom-color: #111111;
+  }
+  .navbar .nav-collapse .nav.pull-right {
+    float: none;
+    margin-left: 0;
+  }
+  .nav-collapse,
+  .nav-collapse.collapse {
+    height: 0;
+    overflow: hidden;
+  }
+  .navbar .btn-navbar {
+    display: block;
+  }
+  .navbar-static .navbar-inner {
+    padding-right: 10px;
+    padding-left: 10px;
+  }
+}
+
+@media (min-width: 980px) {
+  .nav-collapse.collapse {
+    height: auto !important;
+    overflow: visible !important;
+  }
+}
diff --git a/doc/asset/css/bootstrap.css b/doc/asset/css/bootstrap.css
new file mode 100644
index 0000000..2f56af3
--- /dev/null
+++ b/doc/asset/css/bootstrap.css
@@ -0,0 +1,6158 @@
+/*!
+ * Bootstrap v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+
+.clearfix {
+  *zoom: 1;
+}
+
+.clearfix:before,
+.clearfix:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.clearfix:after {
+  clear: both;
+}
+
+.hide-text {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.input-block-level {
+  display: block;
+  width: 100%;
+  min-height: 30px;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+nav,
+section {
+  display: block;
+}
+
+audio,
+canvas,
+video {
+  display: inline-block;
+  *display: inline;
+  *zoom: 1;
+}
+
+audio:not([controls]) {
+  display: none;
+}
+
+html {
+  font-size: 100%;
+  -webkit-text-size-adjust: 100%;
+      -ms-text-size-adjust: 100%;
+}
+
+a:focus {
+  outline: thin dotted #333;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+a:hover,
+a:active {
+  outline: 0;
+}
+
+sub,
+sup {
+  position: relative;
+  font-size: 75%;
+  line-height: 0;
+  vertical-align: baseline;
+}
+
+sup {
+  top: -0.5em;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+img {
+  width: auto\9;
+  height: auto;
+  max-width: 100%;
+  vertical-align: middle;
+  border: 0;
+  -ms-interpolation-mode: bicubic;
+}
+
+#map_canvas img,
+.google-maps img {
+  max-width: none;
+}
+
+button,
+input,
+select,
+textarea {
+  margin: 0;
+  font-size: 100%;
+  vertical-align: middle;
+}
+
+button,
+input {
+  *overflow: visible;
+  line-height: normal;
+}
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+  cursor: pointer;
+  -webkit-appearance: button;
+}
+
+label,
+select,
+button,
+input[type="button"],
+input[type="reset"],
+input[type="submit"],
+input[type="radio"],
+input[type="checkbox"] {
+  cursor: pointer;
+}
+
+input[type="search"] {
+  -webkit-box-sizing: content-box;
+     -moz-box-sizing: content-box;
+          box-sizing: content-box;
+  -webkit-appearance: textfield;
+}
+
+input[type="search"]::-webkit-search-decoration,
+input[type="search"]::-webkit-search-cancel-button {
+  -webkit-appearance: none;
+}
+
+textarea {
+  overflow: auto;
+  vertical-align: top;
+}
+
+@media print {
+  * {
+    color: #000 !important;
+    text-shadow: none !important;
+    background: transparent !important;
+    box-shadow: none !important;
+  }
+  a,
+  a:visited {
+    text-decoration: underline;
+  }
+  a[href]:after {
+    content: " (" attr(href) ")";
+  }
+  abbr[title]:after {
+    content: " (" attr(title) ")";
+  }
+  .ir a:after,
+  a[href^="javascript:"]:after,
+  a[href^="#"]:after {
+    content: "";
+  }
+  pre,
+  blockquote {
+    border: 1px solid #999;
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  img {
+    max-width: 100% !important;
+  }
+  @page  {
+    margin: 0.5cm;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+}
+
+body {
+  margin: 0;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 14px;
+  line-height: 20px;
+  color: #333333;
+  background-color: #ffffff;
+}
+
+a {
+  color: #0088cc;
+  text-decoration: none;
+}
+
+a:hover,
+a:focus {
+  color: #005580;
+  text-decoration: underline;
+}
+
+.img-rounded {
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+}
+
+.img-polaroid {
+  padding: 4px;
+  background-color: #fff;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+
+.img-circle {
+  -webkit-border-radius: 500px;
+     -moz-border-radius: 500px;
+          border-radius: 500px;
+}
+
+.row {
+  margin-left: -20px;
+  *zoom: 1;
+}
+
+.row:before,
+.row:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.row:after {
+  clear: both;
+}
+
+[class*="span"] {
+  float: left;
+  min-height: 1px;
+  margin-left: 20px;
+}
+
+.container,
+.navbar-static-top .container,
+.navbar-fixed-top .container,
+.navbar-fixed-bottom .container {
+  width: 940px;
+}
+
+.span12 {
+  width: 940px;
+}
+
+.span11 {
+  width: 860px;
+}
+
+.span10 {
+  width: 780px;
+}
+
+.span9 {
+  width: 700px;
+}
+
+.span8 {
+  width: 620px;
+}
+
+.span7 {
+  width: 540px;
+}
+
+.span6 {
+  width: 460px;
+}
+
+.span5 {
+  width: 380px;
+}
+
+.span4 {
+  width: 300px;
+}
+
+.span3 {
+  width: 220px;
+}
+
+.span2 {
+  width: 140px;
+}
+
+.span1 {
+  width: 60px;
+}
+
+.offset12 {
+  margin-left: 980px;
+}
+
+.offset11 {
+  margin-left: 900px;
+}
+
+.offset10 {
+  margin-left: 820px;
+}
+
+.offset9 {
+  margin-left: 740px;
+}
+
+.offset8 {
+  margin-left: 660px;
+}
+
+.offset7 {
+  margin-left: 580px;
+}
+
+.offset6 {
+  margin-left: 500px;
+}
+
+.offset5 {
+  margin-left: 420px;
+}
+
+.offset4 {
+  margin-left: 340px;
+}
+
+.offset3 {
+  margin-left: 260px;
+}
+
+.offset2 {
+  margin-left: 180px;
+}
+
+.offset1 {
+  margin-left: 100px;
+}
+
+.row-fluid {
+  width: 100%;
+  *zoom: 1;
+}
+
+.row-fluid:before,
+.row-fluid:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.row-fluid:after {
+  clear: both;
+}
+
+.row-fluid [class*="span"] {
+  display: block;
+  float: left;
+  width: 100%;
+  min-height: 30px;
+  margin-left: 2.127659574468085%;
+  *margin-left: 2.074468085106383%;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.row-fluid [class*="span"]:first-child {
+  margin-left: 0;
+}
+
+.row-fluid .controls-row [class*="span"] + [class*="span"] {
+  margin-left: 2.127659574468085%;
+}
+
+.row-fluid .span12 {
+  width: 100%;
+  *width: 99.94680851063829%;
+}
+
+.row-fluid .span11 {
+  width: 91.48936170212765%;
+  *width: 91.43617021276594%;
+}
+
+.row-fluid .span10 {
+  width: 82.97872340425532%;
+  *width: 82.92553191489361%;
+}
+
+.row-fluid .span9 {
+  width: 74.46808510638297%;
+  *width: 74.41489361702126%;
+}
+
+.row-fluid .span8 {
+  width: 65.95744680851064%;
+  *width: 65.90425531914893%;
+}
+
+.row-fluid .span7 {
+  width: 57.44680851063829%;
+  *width: 57.39361702127659%;
+}
+
+.row-fluid .span6 {
+  width: 48.93617021276595%;
+  *width: 48.88297872340425%;
+}
+
+.row-fluid .span5 {
+  width: 40.42553191489362%;
+  *width: 40.37234042553192%;
+}
+
+.row-fluid .span4 {
+  width: 31.914893617021278%;
+  *width: 31.861702127659576%;
+}
+
+.row-fluid .span3 {
+  width: 23.404255319148934%;
+  *width: 23.351063829787233%;
+}
+
+.row-fluid .span2 {
+  width: 14.893617021276595%;
+  *width: 14.840425531914894%;
+}
+
+.row-fluid .span1 {
+  width: 6.382978723404255%;
+  *width: 6.329787234042553%;
+}
+
+.row-fluid .offset12 {
+  margin-left: 104.25531914893617%;
+  *margin-left: 104.14893617021275%;
+}
+
+.row-fluid .offset12:first-child {
+  margin-left: 102.12765957446808%;
+  *margin-left: 102.02127659574467%;
+}
+
+.row-fluid .offset11 {
+  margin-left: 95.74468085106382%;
+  *margin-left: 95.6382978723404%;
+}
+
+.row-fluid .offset11:first-child {
+  margin-left: 93.61702127659574%;
+  *margin-left: 93.51063829787232%;
+}
+
+.row-fluid .offset10 {
+  margin-left: 87.23404255319149%;
+  *margin-left: 87.12765957446807%;
+}
+
+.row-fluid .offset10:first-child {
+  margin-left: 85.1063829787234%;
+  *margin-left: 84.99999999999999%;
+}
+
+.row-fluid .offset9 {
+  margin-left: 78.72340425531914%;
+  *margin-left: 78.61702127659572%;
+}
+
+.row-fluid .offset9:first-child {
+  margin-left: 76.59574468085106%;
+  *margin-left: 76.48936170212764%;
+}
+
+.row-fluid .offset8 {
+  margin-left: 70.2127659574468%;
+  *margin-left: 70.10638297872339%;
+}
+
+.row-fluid .offset8:first-child {
+  margin-left: 68.08510638297872%;
+  *margin-left: 67.9787234042553%;
+}
+
+.row-fluid .offset7 {
+  margin-left: 61.70212765957446%;
+  *margin-left: 61.59574468085106%;
+}
+
+.row-fluid .offset7:first-child {
+  margin-left: 59.574468085106375%;
+  *margin-left: 59.46808510638297%;
+}
+
+.row-fluid .offset6 {
+  margin-left: 53.191489361702125%;
+  *margin-left: 53.085106382978715%;
+}
+
+.row-fluid .offset6:first-child {
+  margin-left: 51.063829787234035%;
+  *margin-left: 50.95744680851063%;
+}
+
+.row-fluid .offset5 {
+  margin-left: 44.68085106382979%;
+  *margin-left: 44.57446808510638%;
+}
+
+.row-fluid .offset5:first-child {
+  margin-left: 42.5531914893617%;
+  *margin-left: 42.4468085106383%;
+}
+
+.row-fluid .offset4 {
+  margin-left: 36.170212765957444%;
+  *margin-left: 36.06382978723405%;
+}
+
+.row-fluid .offset4:first-child {
+  margin-left: 34.04255319148936%;
+  *margin-left: 33.93617021276596%;
+}
+
+.row-fluid .offset3 {
+  margin-left: 27.659574468085104%;
+  *margin-left: 27.5531914893617%;
+}
+
+.row-fluid .offset3:first-child {
+  margin-left: 25.53191489361702%;
+  *margin-left: 25.425531914893618%;
+}
+
+.row-fluid .offset2 {
+  margin-left: 19.148936170212764%;
+  *margin-left: 19.04255319148936%;
+}
+
+.row-fluid .offset2:first-child {
+  margin-left: 17.02127659574468%;
+  *margin-left: 16.914893617021278%;
+}
+
+.row-fluid .offset1 {
+  margin-left: 10.638297872340425%;
+  *margin-left: 10.53191489361702%;
+}
+
+.row-fluid .offset1:first-child {
+  margin-left: 8.51063829787234%;
+  *margin-left: 8.404255319148938%;
+}
+
+[class*="span"].hide,
+.row-fluid [class*="span"].hide {
+  display: none;
+}
+
+[class*="span"].pull-right,
+.row-fluid [class*="span"].pull-right {
+  float: right;
+}
+
+.container {
+  margin-right: auto;
+  margin-left: auto;
+  *zoom: 1;
+}
+
+.container:before,
+.container:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.container:after {
+  clear: both;
+}
+
+.container-fluid {
+  padding-right: 20px;
+  padding-left: 20px;
+  *zoom: 1;
+}
+
+.container-fluid:before,
+.container-fluid:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.container-fluid:after {
+  clear: both;
+}
+
+p {
+  margin: 0 0 10px;
+}
+
+.lead {
+  margin-bottom: 20px;
+  font-size: 21px;
+  font-weight: 200;
+  line-height: 30px;
+}
+
+small {
+  font-size: 85%;
+}
+
+strong {
+  font-weight: bold;
+}
+
+em {
+  font-style: italic;
+}
+
+cite {
+  font-style: normal;
+}
+
+.muted {
+  color: #999999;
+}
+
+a.muted:hover,
+a.muted:focus {
+  color: #808080;
+}
+
+.text-warning {
+  color: #c09853;
+}
+
+a.text-warning:hover,
+a.text-warning:focus {
+  color: #a47e3c;
+}
+
+.text-error {
+  color: #b94a48;
+}
+
+a.text-error:hover,
+a.text-error:focus {
+  color: #953b39;
+}
+
+.text-info {
+  color: #3a87ad;
+}
+
+a.text-info:hover,
+a.text-info:focus {
+  color: #2d6987;
+}
+
+.text-success {
+  color: #468847;
+}
+
+a.text-success:hover,
+a.text-success:focus {
+  color: #356635;
+}
+
+.text-left {
+  text-align: left;
+}
+
+.text-right {
+  text-align: right;
+}
+
+.text-center {
+  text-align: center;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+  margin: 10px 0;
+  font-family: inherit;
+  font-weight: bold;
+  line-height: 20px;
+  color: inherit;
+  text-rendering: optimizelegibility;
+}
+
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small {
+  font-weight: normal;
+  line-height: 1;
+  color: #999999;
+}
+
+h1,
+h2,
+h3 {
+  line-height: 40px;
+}
+
+h1 {
+  font-size: 38.5px;
+}
+
+h2 {
+  font-size: 31.5px;
+}
+
+h3 {
+  font-size: 24.5px;
+}
+
+h4 {
+  font-size: 17.5px;
+}
+
+h5 {
+  font-size: 14px;
+}
+
+h6 {
+  font-size: 11.9px;
+}
+
+h1 small {
+  font-size: 24.5px;
+}
+
+h2 small {
+  font-size: 17.5px;
+}
+
+h3 small {
+  font-size: 14px;
+}
+
+h4 small {
+  font-size: 14px;
+}
+
+.page-header {
+  padding-bottom: 9px;
+  margin: 20px 0 30px;
+  border-bottom: 1px solid #eeeeee;
+}
+
+ul,
+ol {
+  padding: 0;
+  margin: 0 0 10px 25px;
+}
+
+ul ul,
+ul ol,
+ol ol,
+ol ul {
+  margin-bottom: 0;
+}
+
+li {
+  line-height: 20px;
+}
+
+ul.unstyled,
+ol.unstyled {
+  margin-left: 0;
+  list-style: none;
+}
+
+ul.inline,
+ol.inline {
+  margin-left: 0;
+  list-style: none;
+}
+
+ul.inline > li,
+ol.inline > li {
+  display: inline-block;
+  *display: inline;
+  padding-right: 5px;
+  padding-left: 5px;
+  *zoom: 1;
+}
+
+dl {
+  margin-bottom: 20px;
+}
+
+dt,
+dd {
+  line-height: 20px;
+}
+
+dt {
+  font-weight: bold;
+}
+
+dd {
+  margin-left: 10px;
+}
+
+.dl-horizontal {
+  *zoom: 1;
+}
+
+.dl-horizontal:before,
+.dl-horizontal:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.dl-horizontal:after {
+  clear: both;
+}
+
+.dl-horizontal dt {
+  float: left;
+  width: 160px;
+  overflow: hidden;
+  clear: left;
+  text-align: right;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.dl-horizontal dd {
+  margin-left: 180px;
+}
+
+hr {
+  margin: 20px 0;
+  border: 0;
+  border-top: 1px solid #eeeeee;
+  border-bottom: 1px solid #ffffff;
+}
+
+abbr[title],
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted #999999;
+}
+
+abbr.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+
+blockquote {
+  padding: 0 0 0 15px;
+  margin: 0 0 20px;
+  border-left: 5px solid #eeeeee;
+}
+
+blockquote p {
+  margin-bottom: 0;
+  font-size: 17.5px;
+  font-weight: 300;
+  line-height: 1.25;
+}
+
+blockquote small {
+  display: block;
+  line-height: 20px;
+  color: #999999;
+}
+
+blockquote small:before {
+  content: '\2014 \00A0';
+}
+
+blockquote.pull-right {
+  float: right;
+  padding-right: 15px;
+  padding-left: 0;
+  border-right: 5px solid #eeeeee;
+  border-left: 0;
+}
+
+blockquote.pull-right p,
+blockquote.pull-right small {
+  text-align: right;
+}
+
+blockquote.pull-right small:before {
+  content: '';
+}
+
+blockquote.pull-right small:after {
+  content: '\00A0 \2014';
+}
+
+q:before,
+q:after,
+blockquote:before,
+blockquote:after {
+  content: "";
+}
+
+address {
+  display: block;
+  margin-bottom: 20px;
+  font-style: normal;
+  line-height: 20px;
+}
+
+code,
+pre {
+  padding: 0 3px 2px;
+  font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
+  font-size: 12px;
+  color: #333333;
+  -webkit-border-radius: 3px;
+     -moz-border-radius: 3px;
+          border-radius: 3px;
+}
+
+code {
+  padding: 2px 4px;
+  color: #d14;
+  white-space: nowrap;
+  background-color: #f7f7f9;
+  border: 1px solid #e1e1e8;
+}
+
+pre {
+  display: block;
+  padding: 9.5px;
+  margin: 0 0 10px;
+  font-size: 13px;
+  line-height: 20px;
+  word-break: break-all;
+  word-wrap: break-word;
+  white-space: pre;
+  white-space: pre-wrap;
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+pre.prettyprint {
+  margin-bottom: 20px;
+}
+
+pre code {
+  padding: 0;
+  color: inherit;
+  white-space: pre;
+  white-space: pre-wrap;
+  background-color: transparent;
+  border: 0;
+}
+
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+
+form {
+  margin: 0 0 20px;
+}
+
+fieldset {
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: 20px;
+  font-size: 21px;
+  line-height: 40px;
+  color: #333333;
+  border: 0;
+  border-bottom: 1px solid #e5e5e5;
+}
+
+legend small {
+  font-size: 15px;
+  color: #999999;
+}
+
+label,
+input,
+button,
+select,
+textarea {
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 20px;
+}
+
+input,
+button,
+select,
+textarea {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+label {
+  display: block;
+  margin-bottom: 5px;
+}
+
+select,
+textarea,
+input[type="text"],
+input[type="password"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="date"],
+input[type="month"],
+input[type="time"],
+input[type="week"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="search"],
+input[type="tel"],
+input[type="color"],
+.uneditable-input {
+  display: inline-block;
+  height: 20px;
+  padding: 4px 6px;
+  margin-bottom: 10px;
+  font-size: 14px;
+  line-height: 20px;
+  color: #555555;
+  vertical-align: middle;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+input,
+textarea,
+.uneditable-input {
+  width: 206px;
+}
+
+textarea {
+  height: auto;
+}
+
+textarea,
+input[type="text"],
+input[type="password"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="date"],
+input[type="month"],
+input[type="time"],
+input[type="week"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="search"],
+input[type="tel"],
+input[type="color"],
+.uneditable-input {
+  background-color: #ffffff;
+  border: 1px solid #cccccc;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
+     -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
+       -o-transition: border linear 0.2s, box-shadow linear 0.2s;
+          transition: border linear 0.2s, box-shadow linear 0.2s;
+}
+
+textarea:focus,
+input[type="text"]:focus,
+input[type="password"]:focus,
+input[type="datetime"]:focus,
+input[type="datetime-local"]:focus,
+input[type="date"]:focus,
+input[type="month"]:focus,
+input[type="time"]:focus,
+input[type="week"]:focus,
+input[type="number"]:focus,
+input[type="email"]:focus,
+input[type="url"]:focus,
+input[type="search"]:focus,
+input[type="tel"]:focus,
+input[type="color"]:focus,
+.uneditable-input:focus {
+  border-color: rgba(82, 168, 236, 0.8);
+  outline: 0;
+  outline: thin dotted \9;
+  /* IE6-9 */
+
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+}
+
+input[type="radio"],
+input[type="checkbox"] {
+  margin: 4px 0 0;
+  margin-top: 1px \9;
+  *margin-top: 0;
+  line-height: normal;
+}
+
+input[type="file"],
+input[type="image"],
+input[type="submit"],
+input[type="reset"],
+input[type="button"],
+input[type="radio"],
+input[type="checkbox"] {
+  width: auto;
+}
+
+select,
+input[type="file"] {
+  height: 30px;
+  /* In IE7, the height of the select element cannot be changed by height, only font-size */
+
+  *margin-top: 4px;
+  /* For IE7, add top margin to align select with labels */
+
+  line-height: 30px;
+}
+
+select {
+  width: 220px;
+  background-color: #ffffff;
+  border: 1px solid #cccccc;
+}
+
+select[multiple],
+select[size] {
+  height: auto;
+}
+
+select:focus,
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+  outline: thin dotted #333;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+.uneditable-input,
+.uneditable-textarea {
+  color: #999999;
+  cursor: not-allowed;
+  background-color: #fcfcfc;
+  border-color: #cccccc;
+  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+}
+
+.uneditable-input {
+  overflow: hidden;
+  white-space: nowrap;
+}
+
+.uneditable-textarea {
+  width: auto;
+  height: auto;
+}
+
+input:-moz-placeholder,
+textarea:-moz-placeholder {
+  color: #999999;
+}
+
+input:-ms-input-placeholder,
+textarea:-ms-input-placeholder {
+  color: #999999;
+}
+
+input::-webkit-input-placeholder,
+textarea::-webkit-input-placeholder {
+  color: #999999;
+}
+
+.radio,
+.checkbox {
+  min-height: 20px;
+  padding-left: 20px;
+}
+
+.radio input[type="radio"],
+.checkbox input[type="checkbox"] {
+  float: left;
+  margin-left: -20px;
+}
+
+.controls > .radio:first-child,
+.controls > .checkbox:first-child {
+  padding-top: 5px;
+}
+
+.radio.inline,
+.checkbox.inline {
+  display: inline-block;
+  padding-top: 5px;
+  margin-bottom: 0;
+  vertical-align: middle;
+}
+
+.radio.inline + .radio.inline,
+.checkbox.inline + .checkbox.inline {
+  margin-left: 10px;
+}
+
+.input-mini {
+  width: 60px;
+}
+
+.input-small {
+  width: 90px;
+}
+
+.input-medium {
+  width: 150px;
+}
+
+.input-large {
+  width: 210px;
+}
+
+.input-xlarge {
+  width: 270px;
+}
+
+.input-xxlarge {
+  width: 530px;
+}
+
+input[class*="span"],
+select[class*="span"],
+textarea[class*="span"],
+.uneditable-input[class*="span"],
+.row-fluid input[class*="span"],
+.row-fluid select[class*="span"],
+.row-fluid textarea[class*="span"],
+.row-fluid .uneditable-input[class*="span"] {
+  float: none;
+  margin-left: 0;
+}
+
+.input-append input[class*="span"],
+.input-append .uneditable-input[class*="span"],
+.input-prepend input[class*="span"],
+.input-prepend .uneditable-input[class*="span"],
+.row-fluid input[class*="span"],
+.row-fluid select[class*="span"],
+.row-fluid textarea[class*="span"],
+.row-fluid .uneditable-input[class*="span"],
+.row-fluid .input-prepend [class*="span"],
+.row-fluid .input-append [class*="span"] {
+  display: inline-block;
+}
+
+input,
+textarea,
+.uneditable-input {
+  margin-left: 0;
+}
+
+.controls-row [class*="span"] + [class*="span"] {
+  margin-left: 20px;
+}
+
+input.span12,
+textarea.span12,
+.uneditable-input.span12 {
+  width: 926px;
+}
+
+input.span11,
+textarea.span11,
+.uneditable-input.span11 {
+  width: 846px;
+}
+
+input.span10,
+textarea.span10,
+.uneditable-input.span10 {
+  width: 766px;
+}
+
+input.span9,
+textarea.span9,
+.uneditable-input.span9 {
+  width: 686px;
+}
+
+input.span8,
+textarea.span8,
+.uneditable-input.span8 {
+  width: 606px;
+}
+
+input.span7,
+textarea.span7,
+.uneditable-input.span7 {
+  width: 526px;
+}
+
+input.span6,
+textarea.span6,
+.uneditable-input.span6 {
+  width: 446px;
+}
+
+input.span5,
+textarea.span5,
+.uneditable-input.span5 {
+  width: 366px;
+}
+
+input.span4,
+textarea.span4,
+.uneditable-input.span4 {
+  width: 286px;
+}
+
+input.span3,
+textarea.span3,
+.uneditable-input.span3 {
+  width: 206px;
+}
+
+input.span2,
+textarea.span2,
+.uneditable-input.span2 {
+  width: 126px;
+}
+
+input.span1,
+textarea.span1,
+.uneditable-input.span1 {
+  width: 46px;
+}
+
+.controls-row {
+  *zoom: 1;
+}
+
+.controls-row:before,
+.controls-row:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.controls-row:after {
+  clear: both;
+}
+
+.controls-row [class*="span"],
+.row-fluid .controls-row [class*="span"] {
+  float: left;
+}
+
+.controls-row .checkbox[class*="span"],
+.controls-row .radio[class*="span"] {
+  padding-top: 5px;
+}
+
+input[disabled],
+select[disabled],
+textarea[disabled],
+input[readonly],
+select[readonly],
+textarea[readonly] {
+  cursor: not-allowed;
+  background-color: #eeeeee;
+}
+
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"][readonly],
+input[type="checkbox"][readonly] {
+  background-color: transparent;
+}
+
+.control-group.warning .control-label,
+.control-group.warning .help-block,
+.control-group.warning .help-inline {
+  color: #c09853;
+}
+
+.control-group.warning .checkbox,
+.control-group.warning .radio,
+.control-group.warning input,
+.control-group.warning select,
+.control-group.warning textarea {
+  color: #c09853;
+}
+
+.control-group.warning input,
+.control-group.warning select,
+.control-group.warning textarea {
+  border-color: #c09853;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.warning input:focus,
+.control-group.warning select:focus,
+.control-group.warning textarea:focus {
+  border-color: #a47e3c;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+}
+
+.control-group.warning .input-prepend .add-on,
+.control-group.warning .input-append .add-on {
+  color: #c09853;
+  background-color: #fcf8e3;
+  border-color: #c09853;
+}
+
+.control-group.error .control-label,
+.control-group.error .help-block,
+.control-group.error .help-inline {
+  color: #b94a48;
+}
+
+.control-group.error .checkbox,
+.control-group.error .radio,
+.control-group.error input,
+.control-group.error select,
+.control-group.error textarea {
+  color: #b94a48;
+}
+
+.control-group.error input,
+.control-group.error select,
+.control-group.error textarea {
+  border-color: #b94a48;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.error input:focus,
+.control-group.error select:focus,
+.control-group.error textarea:focus {
+  border-color: #953b39;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+}
+
+.control-group.error .input-prepend .add-on,
+.control-group.error .input-append .add-on {
+  color: #b94a48;
+  background-color: #f2dede;
+  border-color: #b94a48;
+}
+
+.control-group.success .control-label,
+.control-group.success .help-block,
+.control-group.success .help-inline {
+  color: #468847;
+}
+
+.control-group.success .checkbox,
+.control-group.success .radio,
+.control-group.success input,
+.control-group.success select,
+.control-group.success textarea {
+  color: #468847;
+}
+
+.control-group.success input,
+.control-group.success select,
+.control-group.success textarea {
+  border-color: #468847;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.success input:focus,
+.control-group.success select:focus,
+.control-group.success textarea:focus {
+  border-color: #356635;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+}
+
+.control-group.success .input-prepend .add-on,
+.control-group.success .input-append .add-on {
+  color: #468847;
+  background-color: #dff0d8;
+  border-color: #468847;
+}
+
+.control-group.info .control-label,
+.control-group.info .help-block,
+.control-group.info .help-inline {
+  color: #3a87ad;
+}
+
+.control-group.info .checkbox,
+.control-group.info .radio,
+.control-group.info input,
+.control-group.info select,
+.control-group.info textarea {
+  color: #3a87ad;
+}
+
+.control-group.info input,
+.control-group.info select,
+.control-group.info textarea {
+  border-color: #3a87ad;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.info input:focus,
+.control-group.info select:focus,
+.control-group.info textarea:focus {
+  border-color: #2d6987;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+}
+
+.control-group.info .input-prepend .add-on,
+.control-group.info .input-append .add-on {
+  color: #3a87ad;
+  background-color: #d9edf7;
+  border-color: #3a87ad;
+}
+
+input:focus:invalid,
+textarea:focus:invalid,
+select:focus:invalid {
+  color: #b94a48;
+  border-color: #ee5f5b;
+}
+
+input:focus:invalid:focus,
+textarea:focus:invalid:focus,
+select:focus:invalid:focus {
+  border-color: #e9322d;
+  -webkit-box-shadow: 0 0 6px #f8b9b7;
+     -moz-box-shadow: 0 0 6px #f8b9b7;
+          box-shadow: 0 0 6px #f8b9b7;
+}
+
+.form-actions {
+  padding: 19px 20px 20px;
+  margin-top: 20px;
+  margin-bottom: 20px;
+  background-color: #f5f5f5;
+  border-top: 1px solid #e5e5e5;
+  *zoom: 1;
+}
+
+.form-actions:before,
+.form-actions:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.form-actions:after {
+  clear: both;
+}
+
+.help-block,
+.help-inline {
+  color: #595959;
+}
+
+.help-block {
+  display: block;
+  margin-bottom: 10px;
+}
+
+.help-inline {
+  display: inline-block;
+  *display: inline;
+  padding-left: 5px;
+  vertical-align: middle;
+  *zoom: 1;
+}
+
+.input-append,
+.input-prepend {
+  display: inline-block;
+  margin-bottom: 10px;
+  font-size: 0;
+  white-space: nowrap;
+  vertical-align: middle;
+}
+
+.input-append input,
+.input-prepend input,
+.input-append select,
+.input-prepend select,
+.input-append .uneditable-input,
+.input-prepend .uneditable-input,
+.input-append .dropdown-menu,
+.input-prepend .dropdown-menu,
+.input-append .popover,
+.input-prepend .popover {
+  font-size: 14px;
+}
+
+.input-append input,
+.input-prepend input,
+.input-append select,
+.input-prepend select,
+.input-append .uneditable-input,
+.input-prepend .uneditable-input {
+  position: relative;
+  margin-bottom: 0;
+  *margin-left: 0;
+  vertical-align: top;
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.input-append input:focus,
+.input-prepend input:focus,
+.input-append select:focus,
+.input-prepend select:focus,
+.input-append .uneditable-input:focus,
+.input-prepend .uneditable-input:focus {
+  z-index: 2;
+}
+
+.input-append .add-on,
+.input-prepend .add-on {
+  display: inline-block;
+  width: auto;
+  height: 20px;
+  min-width: 16px;
+  padding: 4px 5px;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 20px;
+  text-align: center;
+  text-shadow: 0 1px 0 #ffffff;
+  background-color: #eeeeee;
+  border: 1px solid #ccc;
+}
+
+.input-append .add-on,
+.input-prepend .add-on,
+.input-append .btn,
+.input-prepend .btn,
+.input-append .btn-group > .dropdown-toggle,
+.input-prepend .btn-group > .dropdown-toggle {
+  vertical-align: top;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.input-append .active,
+.input-prepend .active {
+  background-color: #a9dba9;
+  border-color: #46a546;
+}
+
+.input-prepend .add-on,
+.input-prepend .btn {
+  margin-right: -1px;
+}
+
+.input-prepend .add-on:first-child,
+.input-prepend .btn:first-child {
+  -webkit-border-radius: 4px 0 0 4px;
+     -moz-border-radius: 4px 0 0 4px;
+          border-radius: 4px 0 0 4px;
+}
+
+.input-append input,
+.input-append select,
+.input-append .uneditable-input {
+  -webkit-border-radius: 4px 0 0 4px;
+     -moz-border-radius: 4px 0 0 4px;
+          border-radius: 4px 0 0 4px;
+}
+
+.input-append input + .btn-group .btn:last-child,
+.input-append select + .btn-group .btn:last-child,
+.input-append .uneditable-input + .btn-group .btn:last-child {
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.input-append .add-on,
+.input-append .btn,
+.input-append .btn-group {
+  margin-left: -1px;
+}
+
+.input-append .add-on:last-child,
+.input-append .btn:last-child,
+.input-append .btn-group:last-child > .dropdown-toggle {
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append input,
+.input-prepend.input-append select,
+.input-prepend.input-append .uneditable-input {
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.input-prepend.input-append input + .btn-group .btn,
+.input-prepend.input-append select + .btn-group .btn,
+.input-prepend.input-append .uneditable-input + .btn-group .btn {
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append .add-on:first-child,
+.input-prepend.input-append .btn:first-child {
+  margin-right: -1px;
+  -webkit-border-radius: 4px 0 0 4px;
+     -moz-border-radius: 4px 0 0 4px;
+          border-radius: 4px 0 0 4px;
+}
+
+.input-prepend.input-append .add-on:last-child,
+.input-prepend.input-append .btn:last-child {
+  margin-left: -1px;
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append .btn-group:first-child {
+  margin-left: 0;
+}
+
+input.search-query {
+  padding-right: 14px;
+  padding-right: 4px \9;
+  padding-left: 14px;
+  padding-left: 4px \9;
+  /* IE7-8 doesn't have border-radius, so don't indent the padding */
+
+  margin-bottom: 0;
+  -webkit-border-radius: 15px;
+     -moz-border-radius: 15px;
+          border-radius: 15px;
+}
+
+/* Allow for input prepend/append in search forms */
+
+.form-search .input-append .search-query,
+.form-search .input-prepend .search-query {
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.form-search .input-append .search-query {
+  -webkit-border-radius: 14px 0 0 14px;
+     -moz-border-radius: 14px 0 0 14px;
+          border-radius: 14px 0 0 14px;
+}
+
+.form-search .input-append .btn {
+  -webkit-border-radius: 0 14px 14px 0;
+     -moz-border-radius: 0 14px 14px 0;
+          border-radius: 0 14px 14px 0;
+}
+
+.form-search .input-prepend .search-query {
+  -webkit-border-radius: 0 14px 14px 0;
+     -moz-border-radius: 0 14px 14px 0;
+          border-radius: 0 14px 14px 0;
+}
+
+.form-search .input-prepend .btn {
+  -webkit-border-radius: 14px 0 0 14px;
+     -moz-border-radius: 14px 0 0 14px;
+          border-radius: 14px 0 0 14px;
+}
+
+.form-search input,
+.form-inline input,
+.form-horizontal input,
+.form-search textarea,
+.form-inline textarea,
+.form-horizontal textarea,
+.form-search select,
+.form-inline select,
+.form-horizontal select,
+.form-search .help-inline,
+.form-inline .help-inline,
+.form-horizontal .help-inline,
+.form-search .uneditable-input,
+.form-inline .uneditable-input,
+.form-horizontal .uneditable-input,
+.form-search .input-prepend,
+.form-inline .input-prepend,
+.form-horizontal .input-prepend,
+.form-search .input-append,
+.form-inline .input-append,
+.form-horizontal .input-append {
+  display: inline-block;
+  *display: inline;
+  margin-bottom: 0;
+  vertical-align: middle;
+  *zoom: 1;
+}
+
+.form-search .hide,
+.form-inline .hide,
+.form-horizontal .hide {
+  display: none;
+}
+
+.form-search label,
+.form-inline label,
+.form-search .btn-group,
+.form-inline .btn-group {
+  display: inline-block;
+}
+
+.form-search .input-append,
+.form-inline .input-append,
+.form-search .input-prepend,
+.form-inline .input-prepend {
+  margin-bottom: 0;
+}
+
+.form-search .radio,
+.form-search .checkbox,
+.form-inline .radio,
+.form-inline .checkbox {
+  padding-left: 0;
+  margin-bottom: 0;
+  vertical-align: middle;
+}
+
+.form-search .radio input[type="radio"],
+.form-search .checkbox input[type="checkbox"],
+.form-inline .radio input[type="radio"],
+.form-inline .checkbox input[type="checkbox"] {
+  float: left;
+  margin-right: 3px;
+  margin-left: 0;
+}
+
+.control-group {
+  margin-bottom: 10px;
+}
+
+legend + .control-group {
+  margin-top: 20px;
+  -webkit-margin-top-collapse: separate;
+}
+
+.form-horizontal .control-group {
+  margin-bottom: 20px;
+  *zoom: 1;
+}
+
+.form-horizontal .control-group:before,
+.form-horizontal .control-group:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.form-horizontal .control-group:after {
+  clear: both;
+}
+
+.form-horizontal .control-label {
+  float: left;
+  width: 160px;
+  padding-top: 5px;
+  text-align: right;
+}
+
+.form-horizontal .controls {
+  *display: inline-block;
+  *padding-left: 20px;
+  margin-left: 180px;
+  *margin-left: 0;
+}
+
+.form-horizontal .controls:first-child {
+  *padding-left: 180px;
+}
+
+.form-horizontal .help-block {
+  margin-bottom: 0;
+}
+
+.form-horizontal input + .help-block,
+.form-horizontal select + .help-block,
+.form-horizontal textarea + .help-block,
+.form-horizontal .uneditable-input + .help-block,
+.form-horizontal .input-prepend + .help-block,
+.form-horizontal .input-append + .help-block {
+  margin-top: 10px;
+}
+
+.form-horizontal .form-actions {
+  padding-left: 180px;
+}
+
+table {
+  max-width: 100%;
+  background-color: transparent;
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
+.table {
+  width: 100%;
+  margin-bottom: 20px;
+}
+
+.table th,
+.table td {
+  padding: 8px;
+  line-height: 20px;
+  text-align: left;
+  vertical-align: top;
+  border-top: 1px solid #dddddd;
+}
+
+.table th {
+  font-weight: bold;
+}
+
+.table thead th {
+  vertical-align: bottom;
+}
+
+.table caption + thead tr:first-child th,
+.table caption + thead tr:first-child td,
+.table colgroup + thead tr:first-child th,
+.table colgroup + thead tr:first-child td,
+.table thead:first-child tr:first-child th,
+.table thead:first-child tr:first-child td {
+  border-top: 0;
+}
+
+.table tbody + tbody {
+  border-top: 2px solid #dddddd;
+}
+
+.table .table {
+  background-color: #ffffff;
+}
+
+.table-condensed th,
+.table-condensed td {
+  padding: 4px 5px;
+}
+
+.table-bordered {
+  border: 1px solid #dddddd;
+  border-collapse: separate;
+  *border-collapse: collapse;
+  border-left: 0;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.table-bordered th,
+.table-bordered td {
+  border-left: 1px solid #dddddd;
+}
+
+.table-bordered caption + thead tr:first-child th,
+.table-bordered caption + tbody tr:first-child th,
+.table-bordered caption + tbody tr:first-child td,
+.table-bordered colgroup + thead tr:first-child th,
+.table-bordered colgroup + tbody tr:first-child th,
+.table-bordered colgroup + tbody tr:first-child td,
+.table-bordered thead:first-child tr:first-child th,
+.table-bordered tbody:first-child tr:first-child th,
+.table-bordered tbody:first-child tr:first-child td {
+  border-top: 0;
+}
+
+.table-bordered thead:first-child tr:first-child > th:first-child,
+.table-bordered tbody:first-child tr:first-child > td:first-child,
+.table-bordered tbody:first-child tr:first-child > th:first-child {
+  -webkit-border-top-left-radius: 4px;
+          border-top-left-radius: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+.table-bordered thead:first-child tr:first-child > th:last-child,
+.table-bordered tbody:first-child tr:first-child > td:last-child,
+.table-bordered tbody:first-child tr:first-child > th:last-child {
+  -webkit-border-top-right-radius: 4px;
+          border-top-right-radius: 4px;
+  -moz-border-radius-topright: 4px;
+}
+
+.table-bordered thead:last-child tr:last-child > th:first-child,
+.table-bordered tbody:last-child tr:last-child > td:first-child,
+.table-bordered tbody:last-child tr:last-child > th:first-child,
+.table-bordered tfoot:last-child tr:last-child > td:first-child,
+.table-bordered tfoot:last-child tr:last-child > th:first-child {
+  -webkit-border-bottom-left-radius: 4px;
+          border-bottom-left-radius: 4px;
+  -moz-border-radius-bottomleft: 4px;
+}
+
+.table-bordered thead:last-child tr:last-child > th:last-child,
+.table-bordered tbody:last-child tr:last-child > td:last-child,
+.table-bordered tbody:last-child tr:last-child > th:last-child,
+.table-bordered tfoot:last-child tr:last-child > td:last-child,
+.table-bordered tfoot:last-child tr:last-child > th:last-child {
+  -webkit-border-bottom-right-radius: 4px;
+          border-bottom-right-radius: 4px;
+  -moz-border-radius-bottomright: 4px;
+}
+
+.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {
+  -webkit-border-bottom-left-radius: 0;
+          border-bottom-left-radius: 0;
+  -moz-border-radius-bottomleft: 0;
+}
+
+.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {
+  -webkit-border-bottom-right-radius: 0;
+          border-bottom-right-radius: 0;
+  -moz-border-radius-bottomright: 0;
+}
+
+.table-bordered caption + thead tr:first-child th:first-child,
+.table-bordered caption + tbody tr:first-child td:first-child,
+.table-bordered colgroup + thead tr:first-child th:first-child,
+.table-bordered colgroup + tbody tr:first-child td:first-child {
+  -webkit-border-top-left-radius: 4px;
+          border-top-left-radius: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+.table-bordered caption + thead tr:first-child th:last-child,
+.table-bordered caption + tbody tr:first-child td:last-child,
+.table-bordered colgroup + thead tr:first-child th:last-child,
+.table-bordered colgroup + tbody tr:first-child td:last-child {
+  -webkit-border-top-right-radius: 4px;
+          border-top-right-radius: 4px;
+  -moz-border-radius-topright: 4px;
+}
+
+.table-striped tbody > tr:nth-child(odd) > td,
+.table-striped tbody > tr:nth-child(odd) > th {
+  background-color: #f9f9f9;
+}
+
+.table-hover tbody tr:hover > td,
+.table-hover tbody tr:hover > th {
+  background-color: #f5f5f5;
+}
+
+table td[class*="span"],
+table th[class*="span"],
+.row-fluid table td[class*="span"],
+.row-fluid table th[class*="span"] {
+  display: table-cell;
+  float: none;
+  margin-left: 0;
+}
+
+.table td.span1,
+.table th.span1 {
+  float: none;
+  width: 44px;
+  margin-left: 0;
+}
+
+.table td.span2,
+.table th.span2 {
+  float: none;
+  width: 124px;
+  margin-left: 0;
+}
+
+.table td.span3,
+.table th.span3 {
+  float: none;
+  width: 204px;
+  margin-left: 0;
+}
+
+.table td.span4,
+.table th.span4 {
+  float: none;
+  width: 284px;
+  margin-left: 0;
+}
+
+.table td.span5,
+.table th.span5 {
+  float: none;
+  width: 364px;
+  margin-left: 0;
+}
+
+.table td.span6,
+.table th.span6 {
+  float: none;
+  width: 444px;
+  margin-left: 0;
+}
+
+.table td.span7,
+.table th.span7 {
+  float: none;
+  width: 524px;
+  margin-left: 0;
+}
+
+.table td.span8,
+.table th.span8 {
+  float: none;
+  width: 604px;
+  margin-left: 0;
+}
+
+.table td.span9,
+.table th.span9 {
+  float: none;
+  width: 684px;
+  margin-left: 0;
+}
+
+.table td.span10,
+.table th.span10 {
+  float: none;
+  width: 764px;
+  margin-left: 0;
+}
+
+.table td.span11,
+.table th.span11 {
+  float: none;
+  width: 844px;
+  margin-left: 0;
+}
+
+.table td.span12,
+.table th.span12 {
+  float: none;
+  width: 924px;
+  margin-left: 0;
+}
+
+.table tbody tr.success > td {
+  background-color: #dff0d8;
+}
+
+.table tbody tr.error > td {
+  background-color: #f2dede;
+}
+
+.table tbody tr.warning > td {
+  background-color: #fcf8e3;
+}
+
+.table tbody tr.info > td {
+  background-color: #d9edf7;
+}
+
+.table-hover tbody tr.success:hover > td {
+  background-color: #d0e9c6;
+}
+
+.table-hover tbody tr.error:hover > td {
+  background-color: #ebcccc;
+}
+
+.table-hover tbody tr.warning:hover > td {
+  background-color: #faf2cc;
+}
+
+.table-hover tbody tr.info:hover > td {
+  background-color: #c4e3f3;
+}
+
+[class^="icon-"],
+[class*=" icon-"] {
+  display: inline-block;
+  width: 14px;
+  height: 14px;
+  margin-top: 1px;
+  *margin-right: .3em;
+  line-height: 14px;
+  vertical-align: text-top;
+  background-image: url("../img/glyphicons-halflings.png");
+  background-position: 14px 14px;
+  background-repeat: no-repeat;
+}
+
+/* White icons with optional class, or on hover/focus/active states of certain elements */
+
+.icon-white,
+.nav-pills > .active > a > [class^="icon-"],
+.nav-pills > .active > a > [class*=" icon-"],
+.nav-list > .active > a > [class^="icon-"],
+.nav-list > .active > a > [class*=" icon-"],
+.navbar-inverse .nav > .active > a > [class^="icon-"],
+.navbar-inverse .nav > .active > a > [class*=" icon-"],
+.dropdown-menu > li > a:hover > [class^="icon-"],
+.dropdown-menu > li > a:focus > [class^="icon-"],
+.dropdown-menu > li > a:hover > [class*=" icon-"],
+.dropdown-menu > li > a:focus > [class*=" icon-"],
+.dropdown-menu > .active > a > [class^="icon-"],
+.dropdown-menu > .active > a > [class*=" icon-"],
+.dropdown-submenu:hover > a > [class^="icon-"],
+.dropdown-submenu:focus > a > [class^="icon-"],
+.dropdown-submenu:hover > a > [class*=" icon-"],
+.dropdown-submenu:focus > a > [class*=" icon-"] {
+  background-image: url("../img/glyphicons-halflings-white.png");
+}
+
+.icon-glass {
+  background-position: 0      0;
+}
+
+.icon-music {
+  background-position: -24px 0;
+}
+
+.icon-search {
+  background-position: -48px 0;
+}
+
+.icon-envelope {
+  background-position: -72px 0;
+}
+
+.icon-heart {
+  background-position: -96px 0;
+}
+
+.icon-star {
+  background-position: -120px 0;
+}
+
+.icon-star-empty {
+  background-position: -144px 0;
+}
+
+.icon-user {
+  background-position: -168px 0;
+}
+
+.icon-film {
+  background-position: -192px 0;
+}
+
+.icon-th-large {
+  background-position: -216px 0;
+}
+
+.icon-th {
+  background-position: -240px 0;
+}
+
+.icon-th-list {
+  background-position: -264px 0;
+}
+
+.icon-ok {
+  background-position: -288px 0;
+}
+
+.icon-remove {
+  background-position: -312px 0;
+}
+
+.icon-zoom-in {
+  background-position: -336px 0;
+}
+
+.icon-zoom-out {
+  background-position: -360px 0;
+}
+
+.icon-off {
+  background-position: -384px 0;
+}
+
+.icon-signal {
+  background-position: -408px 0;
+}
+
+.icon-cog {
+  background-position: -432px 0;
+}
+
+.icon-trash {
+  background-position: -456px 0;
+}
+
+.icon-home {
+  background-position: 0 -24px;
+}
+
+.icon-file {
+  background-position: -24px -24px;
+}
+
+.icon-time {
+  background-position: -48px -24px;
+}
+
+.icon-road {
+  background-position: -72px -24px;
+}
+
+.icon-download-alt {
+  background-position: -96px -24px;
+}
+
+.icon-download {
+  background-position: -120px -24px;
+}
+
+.icon-upload {
+  background-position: -144px -24px;
+}
+
+.icon-inbox {
+  background-position: -168px -24px;
+}
+
+.icon-play-circle {
+  background-position: -192px -24px;
+}
+
+.icon-repeat {
+  background-position: -216px -24px;
+}
+
+.icon-refresh {
+  background-position: -240px -24px;
+}
+
+.icon-list-alt {
+  background-position: -264px -24px;
+}
+
+.icon-lock {
+  background-position: -287px -24px;
+}
+
+.icon-flag {
+  background-position: -312px -24px;
+}
+
+.icon-headphones {
+  background-position: -336px -24px;
+}
+
+.icon-volume-off {
+  background-position: -360px -24px;
+}
+
+.icon-volume-down {
+  background-position: -384px -24px;
+}
+
+.icon-volume-up {
+  background-position: -408px -24px;
+}
+
+.icon-qrcode {
+  background-position: -432px -24px;
+}
+
+.icon-barcode {
+  background-position: -456px -24px;
+}
+
+.icon-tag {
+  background-position: 0 -48px;
+}
+
+.icon-tags {
+  background-position: -25px -48px;
+}
+
+.icon-book {
+  background-position: -48px -48px;
+}
+
+.icon-bookmark {
+  background-position: -72px -48px;
+}
+
+.icon-print {
+  background-position: -96px -48px;
+}
+
+.icon-camera {
+  background-position: -120px -48px;
+}
+
+.icon-font {
+  background-position: -144px -48px;
+}
+
+.icon-bold {
+  background-position: -167px -48px;
+}
+
+.icon-italic {
+  background-position: -192px -48px;
+}
+
+.icon-text-height {
+  background-position: -216px -48px;
+}
+
+.icon-text-width {
+  background-position: -240px -48px;
+}
+
+.icon-align-left {
+  background-position: -264px -48px;
+}
+
+.icon-align-center {
+  background-position: -288px -48px;
+}
+
+.icon-align-right {
+  background-position: -312px -48px;
+}
+
+.icon-align-justify {
+  background-position: -336px -48px;
+}
+
+.icon-list {
+  background-position: -360px -48px;
+}
+
+.icon-indent-left {
+  background-position: -384px -48px;
+}
+
+.icon-indent-right {
+  background-position: -408px -48px;
+}
+
+.icon-facetime-video {
+  background-position: -432px -48px;
+}
+
+.icon-picture {
+  background-position: -456px -48px;
+}
+
+.icon-pencil {
+  background-position: 0 -72px;
+}
+
+.icon-map-marker {
+  background-position: -24px -72px;
+}
+
+.icon-adjust {
+  background-position: -48px -72px;
+}
+
+.icon-tint {
+  background-position: -72px -72px;
+}
+
+.icon-edit {
+  background-position: -96px -72px;
+}
+
+.icon-share {
+  background-position: -120px -72px;
+}
+
+.icon-check {
+  background-position: -144px -72px;
+}
+
+.icon-move {
+  background-position: -168px -72px;
+}
+
+.icon-step-backward {
+  background-position: -192px -72px;
+}
+
+.icon-fast-backward {
+  background-position: -216px -72px;
+}
+
+.icon-backward {
+  background-position: -240px -72px;
+}
+
+.icon-play {
+  background-position: -264px -72px;
+}
+
+.icon-pause {
+  background-position: -288px -72px;
+}
+
+.icon-stop {
+  background-position: -312px -72px;
+}
+
+.icon-forward {
+  background-position: -336px -72px;
+}
+
+.icon-fast-forward {
+  background-position: -360px -72px;
+}
+
+.icon-step-forward {
+  background-position: -384px -72px;
+}
+
+.icon-eject {
+  background-position: -408px -72px;
+}
+
+.icon-chevron-left {
+  background-position: -432px -72px;
+}
+
+.icon-chevron-right {
+  background-position: -456px -72px;
+}
+
+.icon-plus-sign {
+  background-position: 0 -96px;
+}
+
+.icon-minus-sign {
+  background-position: -24px -96px;
+}
+
+.icon-remove-sign {
+  background-position: -48px -96px;
+}
+
+.icon-ok-sign {
+  background-position: -72px -96px;
+}
+
+.icon-question-sign {
+  background-position: -96px -96px;
+}
+
+.icon-info-sign {
+  background-position: -120px -96px;
+}
+
+.icon-screenshot {
+  background-position: -144px -96px;
+}
+
+.icon-remove-circle {
+  background-position: -168px -96px;
+}
+
+.icon-ok-circle {
+  background-position: -192px -96px;
+}
+
+.icon-ban-circle {
+  background-position: -216px -96px;
+}
+
+.icon-arrow-left {
+  background-position: -240px -96px;
+}
+
+.icon-arrow-right {
+  background-position: -264px -96px;
+}
+
+.icon-arrow-up {
+  background-position: -289px -96px;
+}
+
+.icon-arrow-down {
+  background-position: -312px -96px;
+}
+
+.icon-share-alt {
+  background-position: -336px -96px;
+}
+
+.icon-resize-full {
+  background-position: -360px -96px;
+}
+
+.icon-resize-small {
+  background-position: -384px -96px;
+}
+
+.icon-plus {
+  background-position: -408px -96px;
+}
+
+.icon-minus {
+  background-position: -433px -96px;
+}
+
+.icon-asterisk {
+  background-position: -456px -96px;
+}
+
+.icon-exclamation-sign {
+  background-position: 0 -120px;
+}
+
+.icon-gift {
+  background-position: -24px -120px;
+}
+
+.icon-leaf {
+  background-position: -48px -120px;
+}
+
+.icon-fire {
+  background-position: -72px -120px;
+}
+
+.icon-eye-open {
+  background-position: -96px -120px;
+}
+
+.icon-eye-close {
+  background-position: -120px -120px;
+}
+
+.icon-warning-sign {
+  background-position: -144px -120px;
+}
+
+.icon-plane {
+  background-position: -168px -120px;
+}
+
+.icon-calendar {
+  background-position: -192px -120px;
+}
+
+.icon-random {
+  width: 16px;
+  background-position: -216px -120px;
+}
+
+.icon-comment {
+  background-position: -240px -120px;
+}
+
+.icon-magnet {
+  background-position: -264px -120px;
+}
+
+.icon-chevron-up {
+  background-position: -288px -120px;
+}
+
+.icon-chevron-down {
+  background-position: -313px -119px;
+}
+
+.icon-retweet {
+  background-position: -336px -120px;
+}
+
+.icon-shopping-cart {
+  background-position: -360px -120px;
+}
+
+.icon-folder-close {
+  width: 16px;
+  background-position: -384px -120px;
+}
+
+.icon-folder-open {
+  width: 16px;
+  background-position: -408px -120px;
+}
+
+.icon-resize-vertical {
+  background-position: -432px -119px;
+}
+
+.icon-resize-horizontal {
+  background-position: -456px -118px;
+}
+
+.icon-hdd {
+  background-position: 0 -144px;
+}
+
+.icon-bullhorn {
+  background-position: -24px -144px;
+}
+
+.icon-bell {
+  background-position: -48px -144px;
+}
+
+.icon-certificate {
+  background-position: -72px -144px;
+}
+
+.icon-thumbs-up {
+  background-position: -96px -144px;
+}
+
+.icon-thumbs-down {
+  background-position: -120px -144px;
+}
+
+.icon-hand-right {
+  background-position: -144px -144px;
+}
+
+.icon-hand-left {
+  background-position: -168px -144px;
+}
+
+.icon-hand-up {
+  background-position: -192px -144px;
+}
+
+.icon-hand-down {
+  background-position: -216px -144px;
+}
+
+.icon-circle-arrow-right {
+  background-position: -240px -144px;
+}
+
+.icon-circle-arrow-left {
+  background-position: -264px -144px;
+}
+
+.icon-circle-arrow-up {
+  background-position: -288px -144px;
+}
+
+.icon-circle-arrow-down {
+  background-position: -312px -144px;
+}
+
+.icon-globe {
+  background-position: -336px -144px;
+}
+
+.icon-wrench {
+  background-position: -360px -144px;
+}
+
+.icon-tasks {
+  background-position: -384px -144px;
+}
+
+.icon-filter {
+  background-position: -408px -144px;
+}
+
+.icon-briefcase {
+  background-position: -432px -144px;
+}
+
+.icon-fullscreen {
+  background-position: -456px -144px;
+}
+
+.dropup,
+.dropdown {
+  position: relative;
+}
+
+.dropdown-toggle {
+  *margin-bottom: -3px;
+}
+
+.dropdown-toggle:active,
+.open .dropdown-toggle {
+  outline: 0;
+}
+
+.caret {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  vertical-align: top;
+  border-top: 4px solid #000000;
+  border-right: 4px solid transparent;
+  border-left: 4px solid transparent;
+  content: "";
+}
+
+.dropdown .caret {
+  margin-top: 8px;
+  margin-left: 2px;
+}
+
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 160px;
+  padding: 5px 0;
+  margin: 2px 0 0;
+  list-style: none;
+  background-color: #ffffff;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  *border-right-width: 2px;
+  *border-bottom-width: 2px;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  -webkit-background-clip: padding-box;
+     -moz-background-clip: padding;
+          background-clip: padding-box;
+}
+
+.dropdown-menu.pull-right {
+  right: 0;
+  left: auto;
+}
+
+.dropdown-menu .divider {
+  *width: 100%;
+  height: 1px;
+  margin: 9px 1px;
+  *margin: -5px 0 5px;
+  overflow: hidden;
+  background-color: #e5e5e5;
+  border-bottom: 1px solid #ffffff;
+}
+
+.dropdown-menu > li > a {
+  display: block;
+  padding: 3px 20px;
+  clear: both;
+  font-weight: normal;
+  line-height: 20px;
+  color: #333333;
+  white-space: nowrap;
+}
+
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus,
+.dropdown-submenu:hover > a,
+.dropdown-submenu:focus > a {
+  color: #ffffff;
+  text-decoration: none;
+  background-color: #0081c2;
+  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
+  background-image: -o-linear-gradient(top, #0088cc, #0077b3);
+  background-image: linear-gradient(to bottom, #0088cc, #0077b3);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
+}
+
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  color: #ffffff;
+  text-decoration: none;
+  background-color: #0081c2;
+  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
+  background-image: -o-linear-gradient(top, #0088cc, #0077b3);
+  background-image: linear-gradient(to bottom, #0088cc, #0077b3);
+  background-repeat: repeat-x;
+  outline: 0;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
+}
+
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  color: #999999;
+}
+
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  text-decoration: none;
+  cursor: default;
+  background-color: transparent;
+  background-image: none;
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.open {
+  *z-index: 1000;
+}
+
+.open > .dropdown-menu {
+  display: block;
+}
+
+.pull-right > .dropdown-menu {
+  right: 0;
+  left: auto;
+}
+
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+  border-top: 0;
+  border-bottom: 4px solid #000000;
+  content: "";
+}
+
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-bottom: 1px;
+}
+
+.dropdown-submenu {
+  position: relative;
+}
+
+.dropdown-submenu > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  -webkit-border-radius: 0 6px 6px 6px;
+     -moz-border-radius: 0 6px 6px 6px;
+          border-radius: 0 6px 6px 6px;
+}
+
+.dropdown-submenu:hover > .dropdown-menu {
+  display: block;
+}
+
+.dropup .dropdown-submenu > .dropdown-menu {
+  top: auto;
+  bottom: 0;
+  margin-top: 0;
+  margin-bottom: -2px;
+  -webkit-border-radius: 5px 5px 5px 0;
+     -moz-border-radius: 5px 5px 5px 0;
+          border-radius: 5px 5px 5px 0;
+}
+
+.dropdown-submenu > a:after {
+  display: block;
+  float: right;
+  width: 0;
+  height: 0;
+  margin-top: 5px;
+  margin-right: -10px;
+  border-color: transparent;
+  border-left-color: #cccccc;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  content: " ";
+}
+
+.dropdown-submenu:hover > a:after {
+  border-left-color: #ffffff;
+}
+
+.dropdown-submenu.pull-left {
+  float: none;
+}
+
+.dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  -webkit-border-radius: 6px 0 6px 6px;
+     -moz-border-radius: 6px 0 6px 6px;
+          border-radius: 6px 0 6px 6px;
+}
+
+.dropdown .dropdown-menu .nav-header {
+  padding-right: 20px;
+  padding-left: 20px;
+}
+
+.typeahead {
+  z-index: 1051;
+  margin-top: 2px;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.well {
+  min-height: 20px;
+  padding: 19px;
+  margin-bottom: 20px;
+  background-color: #f5f5f5;
+  border: 1px solid #e3e3e3;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+
+.well blockquote {
+  border-color: #ddd;
+  border-color: rgba(0, 0, 0, 0.15);
+}
+
+.well-large {
+  padding: 24px;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+}
+
+.well-small {
+  padding: 9px;
+  -webkit-border-radius: 3px;
+     -moz-border-radius: 3px;
+          border-radius: 3px;
+}
+
+.fade {
+  opacity: 0;
+  -webkit-transition: opacity 0.15s linear;
+     -moz-transition: opacity 0.15s linear;
+       -o-transition: opacity 0.15s linear;
+          transition: opacity 0.15s linear;
+}
+
+.fade.in {
+  opacity: 1;
+}
+
+.collapse {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  -webkit-transition: height 0.35s ease;
+     -moz-transition: height 0.35s ease;
+       -o-transition: height 0.35s ease;
+          transition: height 0.35s ease;
+}
+
+.collapse.in {
+  height: auto;
+}
+
+.close {
+  float: right;
+  font-size: 20px;
+  font-weight: bold;
+  line-height: 20px;
+  color: #000000;
+  text-shadow: 0 1px 0 #ffffff;
+  opacity: 0.2;
+  filter: alpha(opacity=20);
+}
+
+.close:hover,
+.close:focus {
+  color: #000000;
+  text-decoration: none;
+  cursor: pointer;
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+
+button.close {
+  padding: 0;
+  cursor: pointer;
+  background: transparent;
+  border: 0;
+  -webkit-appearance: none;
+}
+
+.btn {
+  display: inline-block;
+  *display: inline;
+  padding: 4px 12px;
+  margin-bottom: 0;
+  *margin-left: .3em;
+  font-size: 14px;
+  line-height: 20px;
+  color: #333333;
+  text-align: center;
+  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
+  vertical-align: middle;
+  cursor: pointer;
+  background-color: #f5f5f5;
+  *background-color: #e6e6e6;
+  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
+  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
+  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
+  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
+  background-repeat: repeat-x;
+  border: 1px solid #cccccc;
+  *border: 0;
+  border-color: #e6e6e6 #e6e6e6 #bfbfbf;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  border-bottom-color: #b3b3b3;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  *zoom: 1;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn:hover,
+.btn:focus,
+.btn:active,
+.btn.active,
+.btn.disabled,
+.btn[disabled] {
+  color: #333333;
+  background-color: #e6e6e6;
+  *background-color: #d9d9d9;
+}
+
+.btn:active,
+.btn.active {
+  background-color: #cccccc \9;
+}
+
+.btn:first-child {
+  *margin-left: 0;
+}
+
+.btn:hover,
+.btn:focus {
+  color: #333333;
+  text-decoration: none;
+  background-position: 0 -15px;
+  -webkit-transition: background-position 0.1s linear;
+     -moz-transition: background-position 0.1s linear;
+       -o-transition: background-position 0.1s linear;
+          transition: background-position 0.1s linear;
+}
+
+.btn:focus {
+  outline: thin dotted #333;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+.btn.active,
+.btn:active {
+  background-image: none;
+  outline: 0;
+  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn.disabled,
+.btn[disabled] {
+  cursor: default;
+  background-image: none;
+  opacity: 0.65;
+  filter: alpha(opacity=65);
+  -webkit-box-shadow: none;
+     -moz-box-shadow: none;
+          box-shadow: none;
+}
+
+.btn-large {
+  padding: 11px 19px;
+  font-size: 17.5px;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+}
+
+.btn-large [class^="icon-"],
+.btn-large [class*=" icon-"] {
+  margin-top: 4px;
+}
+
+.btn-small {
+  padding: 2px 10px;
+  font-size: 11.9px;
+  -webkit-border-radius: 3px;
+     -moz-border-radius: 3px;
+          border-radius: 3px;
+}
+
+.btn-small [class^="icon-"],
+.btn-small [class*=" icon-"] {
+  margin-top: 0;
+}
+
+.btn-mini [class^="icon-"],
+.btn-mini [class*=" icon-"] {
+  margin-top: -1px;
+}
+
+.btn-mini {
+  padding: 0 6px;
+  font-size: 10.5px;
+  -webkit-border-radius: 3px;
+     -moz-border-radius: 3px;
+          border-radius: 3px;
+}
+
+.btn-block {
+  display: block;
+  width: 100%;
+  padding-right: 0;
+  padding-left: 0;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.btn-block + .btn-block {
+  margin-top: 5px;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+
+.btn-primary.active,
+.btn-warning.active,
+.btn-danger.active,
+.btn-success.active,
+.btn-info.active,
+.btn-inverse.active {
+  color: rgba(255, 255, 255, 0.75);
+}
+
+.btn-primary {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #006dcc;
+  *background-color: #0044cc;
+  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+  background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+  background-image: linear-gradient(to bottom, #0088cc, #0044cc);
+  background-repeat: repeat-x;
+  border-color: #0044cc #0044cc #002a80;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary:active,
+.btn-primary.active,
+.btn-primary.disabled,
+.btn-primary[disabled] {
+  color: #ffffff;
+  background-color: #0044cc;
+  *background-color: #003bb3;
+}
+
+.btn-primary:active,
+.btn-primary.active {
+  background-color: #003399 \9;
+}
+
+.btn-warning {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #faa732;
+  *background-color: #f89406;
+  background-image: -moz-linear-gradient(top, #fbb450, #f89406);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
+  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
+  background-image: -o-linear-gradient(top, #fbb450, #f89406);
+  background-image: linear-gradient(to bottom, #fbb450, #f89406);
+  background-repeat: repeat-x;
+  border-color: #f89406 #f89406 #ad6704;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning:active,
+.btn-warning.active,
+.btn-warning.disabled,
+.btn-warning[disabled] {
+  color: #ffffff;
+  background-color: #f89406;
+  *background-color: #df8505;
+}
+
+.btn-warning:active,
+.btn-warning.active {
+  background-color: #c67605 \9;
+}
+
+.btn-danger {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #da4f49;
+  *background-color: #bd362f;
+  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
+  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
+  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
+  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
+  background-repeat: repeat-x;
+  border-color: #bd362f #bd362f #802420;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger:active,
+.btn-danger.active,
+.btn-danger.disabled,
+.btn-danger[disabled] {
+  color: #ffffff;
+  background-color: #bd362f;
+  *background-color: #a9302a;
+}
+
+.btn-danger:active,
+.btn-danger.active {
+  background-color: #942a25 \9;
+}
+
+.btn-success {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #5bb75b;
+  *background-color: #51a351;
+  background-image: -moz-linear-gradient(top, #62c462, #51a351);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
+  background-image: -webkit-linear-gradient(top, #62c462, #51a351);
+  background-image: -o-linear-gradient(top, #62c462, #51a351);
+  background-image: linear-gradient(to bottom, #62c462, #51a351);
+  background-repeat: repeat-x;
+  border-color: #51a351 #51a351 #387038;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-success:hover,
+.btn-success:focus,
+.btn-success:active,
+.btn-success.active,
+.btn-success.disabled,
+.btn-success[disabled] {
+  color: #ffffff;
+  background-color: #51a351;
+  *background-color: #499249;
+}
+
+.btn-success:active,
+.btn-success.active {
+  background-color: #408140 \9;
+}
+
+.btn-info {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #49afcd;
+  *background-color: #2f96b4;
+  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
+  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
+  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
+  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);
+  background-repeat: repeat-x;
+  border-color: #2f96b4 #2f96b4 #1f6377;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-info:hover,
+.btn-info:focus,
+.btn-info:active,
+.btn-info.active,
+.btn-info.disabled,
+.btn-info[disabled] {
+  color: #ffffff;
+  background-color: #2f96b4;
+  *background-color: #2a85a0;
+}
+
+.btn-info:active,
+.btn-info.active {
+  background-color: #24748c \9;
+}
+
+.btn-inverse {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #363636;
+  *background-color: #222222;
+  background-image: -moz-linear-gradient(top, #444444, #222222);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
+  background-image: -webkit-linear-gradient(top, #444444, #222222);
+  background-image: -o-linear-gradient(top, #444444, #222222);
+  background-image: linear-gradient(to bottom, #444444, #222222);
+  background-repeat: repeat-x;
+  border-color: #222222 #222222 #000000;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-inverse:hover,
+.btn-inverse:focus,
+.btn-inverse:active,
+.btn-inverse.active,
+.btn-inverse.disabled,
+.btn-inverse[disabled] {
+  color: #ffffff;
+  background-color: #222222;
+  *background-color: #151515;
+}
+
+.btn-inverse:active,
+.btn-inverse.active {
+  background-color: #080808 \9;
+}
+
+button.btn,
+input[type="submit"].btn {
+  *padding-top: 3px;
+  *padding-bottom: 3px;
+}
+
+button.btn::-moz-focus-inner,
+input[type="submit"].btn::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+
+button.btn.btn-large,
+input[type="submit"].btn.btn-large {
+  *padding-top: 7px;
+  *padding-bottom: 7px;
+}
+
+button.btn.btn-small,
+input[type="submit"].btn.btn-small {
+  *padding-top: 3px;
+  *padding-bottom: 3px;
+}
+
+button.btn.btn-mini,
+input[type="submit"].btn.btn-mini {
+  *padding-top: 1px;
+  *padding-bottom: 1px;
+}
+
+.btn-link,
+.btn-link:active,
+.btn-link[disabled] {
+  background-color: transparent;
+  background-image: none;
+  -webkit-box-shadow: none;
+     -moz-box-shadow: none;
+          box-shadow: none;
+}
+
+.btn-link {
+  color: #0088cc;
+  cursor: pointer;
+  border-color: transparent;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.btn-link:hover,
+.btn-link:focus {
+  color: #005580;
+  text-decoration: underline;
+  background-color: transparent;
+}
+
+.btn-link[disabled]:hover,
+.btn-link[disabled]:focus {
+  color: #333333;
+  text-decoration: none;
+}
+
+.btn-group {
+  position: relative;
+  display: inline-block;
+  *display: inline;
+  *margin-left: .3em;
+  font-size: 0;
+  white-space: nowrap;
+  vertical-align: middle;
+  *zoom: 1;
+}
+
+.btn-group:first-child {
+  *margin-left: 0;
+}
+
+.btn-group + .btn-group {
+  margin-left: 5px;
+}
+
+.btn-toolbar {
+  margin-top: 10px;
+  margin-bottom: 10px;
+  font-size: 0;
+}
+
+.btn-toolbar > .btn + .btn,
+.btn-toolbar > .btn-group + .btn,
+.btn-toolbar > .btn + .btn-group {
+  margin-left: 5px;
+}
+
+.btn-group > .btn {
+  position: relative;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.btn-group > .btn + .btn {
+  margin-left: -1px;
+}
+
+.btn-group > .btn,
+.btn-group > .dropdown-menu,
+.btn-group > .popover {
+  font-size: 14px;
+}
+
+.btn-group > .btn-mini {
+  font-size: 10.5px;
+}
+
+.btn-group > .btn-small {
+  font-size: 11.9px;
+}
+
+.btn-group > .btn-large {
+  font-size: 17.5px;
+}
+
+.btn-group > .btn:first-child {
+  margin-left: 0;
+  -webkit-border-bottom-left-radius: 4px;
+          border-bottom-left-radius: 4px;
+  -webkit-border-top-left-radius: 4px;
+          border-top-left-radius: 4px;
+  -moz-border-radius-bottomleft: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+.btn-group > .btn:last-child,
+.btn-group > .dropdown-toggle {
+  -webkit-border-top-right-radius: 4px;
+          border-top-right-radius: 4px;
+  -webkit-border-bottom-right-radius: 4px;
+          border-bottom-right-radius: 4px;
+  -moz-border-radius-topright: 4px;
+  -moz-border-radius-bottomright: 4px;
+}
+
+.btn-group > .btn.large:first-child {
+  margin-left: 0;
+  -webkit-border-bottom-left-radius: 6px;
+          border-bottom-left-radius: 6px;
+  -webkit-border-top-left-radius: 6px;
+          border-top-left-radius: 6px;
+  -moz-border-radius-bottomleft: 6px;
+  -moz-border-radius-topleft: 6px;
+}
+
+.btn-group > .btn.large:last-child,
+.btn-group > .large.dropdown-toggle {
+  -webkit-border-top-right-radius: 6px;
+          border-top-right-radius: 6px;
+  -webkit-border-bottom-right-radius: 6px;
+          border-bottom-right-radius: 6px;
+  -moz-border-radius-topright: 6px;
+  -moz-border-radius-bottomright: 6px;
+}
+
+.btn-group > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group > .btn:active,
+.btn-group > .btn.active {
+  z-index: 2;
+}
+
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+
+.btn-group > .btn + .dropdown-toggle {
+  *padding-top: 5px;
+  padding-right: 8px;
+  *padding-bottom: 5px;
+  padding-left: 8px;
+  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn-group > .btn-mini + .dropdown-toggle {
+  *padding-top: 2px;
+  padding-right: 5px;
+  *padding-bottom: 2px;
+  padding-left: 5px;
+}
+
+.btn-group > .btn-small + .dropdown-toggle {
+  *padding-top: 5px;
+  *padding-bottom: 4px;
+}
+
+.btn-group > .btn-large + .dropdown-toggle {
+  *padding-top: 7px;
+  padding-right: 12px;
+  *padding-bottom: 7px;
+  padding-left: 12px;
+}
+
+.btn-group.open .dropdown-toggle {
+  background-image: none;
+  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn-group.open .btn.dropdown-toggle {
+  background-color: #e6e6e6;
+}
+
+.btn-group.open .btn-primary.dropdown-toggle {
+  background-color: #0044cc;
+}
+
+.btn-group.open .btn-warning.dropdown-toggle {
+  background-color: #f89406;
+}
+
+.btn-group.open .btn-danger.dropdown-toggle {
+  background-color: #bd362f;
+}
+
+.btn-group.open .btn-success.dropdown-toggle {
+  background-color: #51a351;
+}
+
+.btn-group.open .btn-info.dropdown-toggle {
+  background-color: #2f96b4;
+}
+
+.btn-group.open .btn-inverse.dropdown-toggle {
+  background-color: #222222;
+}
+
+.btn .caret {
+  margin-top: 8px;
+  margin-left: 0;
+}
+
+.btn-large .caret {
+  margin-top: 6px;
+}
+
+.btn-large .caret {
+  border-top-width: 5px;
+  border-right-width: 5px;
+  border-left-width: 5px;
+}
+
+.btn-mini .caret,
+.btn-small .caret {
+  margin-top: 8px;
+}
+
+.dropup .btn-large .caret {
+  border-bottom-width: 5px;
+}
+
+.btn-primary .caret,
+.btn-warning .caret,
+.btn-danger .caret,
+.btn-info .caret,
+.btn-success .caret,
+.btn-inverse .caret {
+  border-top-color: #ffffff;
+  border-bottom-color: #ffffff;
+}
+
+.btn-group-vertical {
+  display: inline-block;
+  *display: inline;
+  /* IE7 inline-block hack */
+
+  *zoom: 1;
+}
+
+.btn-group-vertical > .btn {
+  display: block;
+  float: none;
+  max-width: 100%;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.btn-group-vertical > .btn + .btn {
+  margin-top: -1px;
+  margin-left: 0;
+}
+
+.btn-group-vertical > .btn:first-child {
+  -webkit-border-radius: 4px 4px 0 0;
+     -moz-border-radius: 4px 4px 0 0;
+          border-radius: 4px 4px 0 0;
+}
+
+.btn-group-vertical > .btn:last-child {
+  -webkit-border-radius: 0 0 4px 4px;
+     -moz-border-radius: 0 0 4px 4px;
+          border-radius: 0 0 4px 4px;
+}
+
+.btn-group-vertical > .btn-large:first-child {
+  -webkit-border-radius: 6px 6px 0 0;
+     -moz-border-radius: 6px 6px 0 0;
+          border-radius: 6px 6px 0 0;
+}
+
+.btn-group-vertical > .btn-large:last-child {
+  -webkit-border-radius: 0 0 6px 6px;
+     -moz-border-radius: 0 0 6px 6px;
+          border-radius: 0 0 6px 6px;
+}
+
+.alert {
+  padding: 8px 35px 8px 14px;
+  margin-bottom: 20px;
+  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+  background-color: #fcf8e3;
+  border: 1px solid #fbeed5;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.alert,
+.alert h4 {
+  color: #c09853;
+}
+
+.alert h4 {
+  margin: 0;
+}
+
+.alert .close {
+  position: relative;
+  top: -2px;
+  right: -21px;
+  line-height: 20px;
+}
+
+.alert-success {
+  color: #468847;
+  background-color: #dff0d8;
+  border-color: #d6e9c6;
+}
+
+.alert-success h4 {
+  color: #468847;
+}
+
+.alert-danger,
+.alert-error {
+  color: #b94a48;
+  background-color: #f2dede;
+  border-color: #eed3d7;
+}
+
+.alert-danger h4,
+.alert-error h4 {
+  color: #b94a48;
+}
+
+.alert-info {
+  color: #3a87ad;
+  background-color: #d9edf7;
+  border-color: #bce8f1;
+}
+
+.alert-info h4 {
+  color: #3a87ad;
+}
+
+.alert-block {
+  padding-top: 14px;
+  padding-bottom: 14px;
+}
+
+.alert-block > p,
+.alert-block > ul {
+  margin-bottom: 0;
+}
+
+.alert-block p + p {
+  margin-top: 5px;
+}
+
+.nav {
+  margin-bottom: 20px;
+  margin-left: 0;
+  list-style: none;
+}
+
+.nav > li > a {
+  display: block;
+}
+
+.nav > li > a:hover,
+.nav > li > a:focus {
+  text-decoration: none;
+  background-color: #eeeeee;
+}
+
+.nav > li > a > img {
+  max-width: none;
+}
+
+.nav > .pull-right {
+  float: right;
+}
+
+.nav-header {
+  display: block;
+  padding: 3px 15px;
+  font-size: 11px;
+  font-weight: bold;
+  line-height: 20px;
+  color: #999999;
+  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+  text-transform: uppercase;
+}
+
+.nav li + .nav-header {
+  margin-top: 9px;
+}
+
+.nav-list {
+  padding-right: 15px;
+  padding-left: 15px;
+  margin-bottom: 0;
+}
+
+.nav-list > li > a,
+.nav-list .nav-header {
+  margin-right: -15px;
+  margin-left: -15px;
+  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+}
+
+.nav-list > li > a {
+  padding: 3px 15px;
+}
+
+.nav-list > .active > a,
+.nav-list > .active > a:hover,
+.nav-list > .active > a:focus {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
+  background-color: #0088cc;
+}
+
+.nav-list [class^="icon-"],
+.nav-list [class*=" icon-"] {
+  margin-right: 2px;
+}
+
+.nav-list .divider {
+  *width: 100%;
+  height: 1px;
+  margin: 9px 1px;
+  *margin: -5px 0 5px;
+  overflow: hidden;
+  background-color: #e5e5e5;
+  border-bottom: 1px solid #ffffff;
+}
+
+.nav-tabs,
+.nav-pills {
+  *zoom: 1;
+}
+
+.nav-tabs:before,
+.nav-pills:before,
+.nav-tabs:after,
+.nav-pills:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.nav-tabs:after,
+.nav-pills:after {
+  clear: both;
+}
+
+.nav-tabs > li,
+.nav-pills > li {
+  float: left;
+}
+
+.nav-tabs > li > a,
+.nav-pills > li > a {
+  padding-right: 12px;
+  padding-left: 12px;
+  margin-right: 2px;
+  line-height: 14px;
+}
+
+.nav-tabs {
+  border-bottom: 1px solid #ddd;
+}
+
+.nav-tabs > li {
+  margin-bottom: -1px;
+}
+
+.nav-tabs > li > a {
+  padding-top: 8px;
+  padding-bottom: 8px;
+  line-height: 20px;
+  border: 1px solid transparent;
+  -webkit-border-radius: 4px 4px 0 0;
+     -moz-border-radius: 4px 4px 0 0;
+          border-radius: 4px 4px 0 0;
+}
+
+.nav-tabs > li > a:hover,
+.nav-tabs > li > a:focus {
+  border-color: #eeeeee #eeeeee #dddddd;
+}
+
+.nav-tabs > .active > a,
+.nav-tabs > .active > a:hover,
+.nav-tabs > .active > a:focus {
+  color: #555555;
+  cursor: default;
+  background-color: #ffffff;
+  border: 1px solid #ddd;
+  border-bottom-color: transparent;
+}
+
+.nav-pills > li > a {
+  padding-top: 8px;
+  padding-bottom: 8px;
+  margin-top: 2px;
+  margin-bottom: 2px;
+  -webkit-border-radius: 5px;
+     -moz-border-radius: 5px;
+          border-radius: 5px;
+}
+
+.nav-pills > .active > a,
+.nav-pills > .active > a:hover,
+.nav-pills > .active > a:focus {
+  color: #ffffff;
+  background-color: #0088cc;
+}
+
+.nav-stacked > li {
+  float: none;
+}
+
+.nav-stacked > li > a {
+  margin-right: 0;
+}
+
+.nav-tabs.nav-stacked {
+  border-bottom: 0;
+}
+
+.nav-tabs.nav-stacked > li > a {
+  border: 1px solid #ddd;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.nav-tabs.nav-stacked > li:first-child > a {
+  -webkit-border-top-right-radius: 4px;
+          border-top-right-radius: 4px;
+  -webkit-border-top-left-radius: 4px;
+          border-top-left-radius: 4px;
+  -moz-border-radius-topright: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+.nav-tabs.nav-stacked > li:last-child > a {
+  -webkit-border-bottom-right-radius: 4px;
+          border-bottom-right-radius: 4px;
+  -webkit-border-bottom-left-radius: 4px;
+          border-bottom-left-radius: 4px;
+  -moz-border-radius-bottomright: 4px;
+  -moz-border-radius-bottomleft: 4px;
+}
+
+.nav-tabs.nav-stacked > li > a:hover,
+.nav-tabs.nav-stacked > li > a:focus {
+  z-index: 2;
+  border-color: #ddd;
+}
+
+.nav-pills.nav-stacked > li > a {
+  margin-bottom: 3px;
+}
+
+.nav-pills.nav-stacked > li:last-child > a {
+  margin-bottom: 1px;
+}
+
+.nav-tabs .dropdown-menu {
+  -webkit-border-radius: 0 0 6px 6px;
+     -moz-border-radius: 0 0 6px 6px;
+          border-radius: 0 0 6px 6px;
+}
+
+.nav-pills .dropdown-menu {
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+}
+
+.nav .dropdown-toggle .caret {
+  margin-top: 6px;
+  border-top-color: #0088cc;
+  border-bottom-color: #0088cc;
+}
+
+.nav .dropdown-toggle:hover .caret,
+.nav .dropdown-toggle:focus .caret {
+  border-top-color: #005580;
+  border-bottom-color: #005580;
+}
+
+/* move down carets for tabs */
+
+.nav-tabs .dropdown-toggle .caret {
+  margin-top: 8px;
+}
+
+.nav .active .dropdown-toggle .caret {
+  border-top-color: #fff;
+  border-bottom-color: #fff;
+}
+
+.nav-tabs .active .dropdown-toggle .caret {
+  border-top-color: #555555;
+  border-bottom-color: #555555;
+}
+
+.nav > .dropdown.active > a:hover,
+.nav > .dropdown.active > a:focus {
+  cursor: pointer;
+}
+
+.nav-tabs .open .dropdown-toggle,
+.nav-pills .open .dropdown-toggle,
+.nav > li.dropdown.open.active > a:hover,
+.nav > li.dropdown.open.active > a:focus {
+  color: #ffffff;
+  background-color: #999999;
+  border-color: #999999;
+}
+
+.nav li.dropdown.open .caret,
+.nav li.dropdown.open.active .caret,
+.nav li.dropdown.open a:hover .caret,
+.nav li.dropdown.open a:focus .caret {
+  border-top-color: #ffffff;
+  border-bottom-color: #ffffff;
+  opacity: 1;
+  filter: alpha(opacity=100);
+}
+
+.tabs-stacked .open > a:hover,
+.tabs-stacked .open > a:focus {
+  border-color: #999999;
+}
+
+.tabbable {
+  *zoom: 1;
+}
+
+.tabbable:before,
+.tabbable:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.tabbable:after {
+  clear: both;
+}
+
+.tab-content {
+  overflow: auto;
+}
+
+.tabs-below > .nav-tabs,
+.tabs-right > .nav-tabs,
+.tabs-left > .nav-tabs {
+  border-bottom: 0;
+}
+
+.tab-content > .tab-pane,
+.pill-content > .pill-pane {
+  display: none;
+}
+
+.tab-content > .active,
+.pill-content > .active {
+  display: block;
+}
+
+.tabs-below > .nav-tabs {
+  border-top: 1px solid #ddd;
+}
+
+.tabs-below > .nav-tabs > li {
+  margin-top: -1px;
+  margin-bottom: 0;
+}
+
+.tabs-below > .nav-tabs > li > a {
+  -webkit-border-radius: 0 0 4px 4px;
+     -moz-border-radius: 0 0 4px 4px;
+          border-radius: 0 0 4px 4px;
+}
+
+.tabs-below > .nav-tabs > li > a:hover,
+.tabs-below > .nav-tabs > li > a:focus {
+  border-top-color: #ddd;
+  border-bottom-color: transparent;
+}
+
+.tabs-below > .nav-tabs > .active > a,
+.tabs-below > .nav-tabs > .active > a:hover,
+.tabs-below > .nav-tabs > .active > a:focus {
+  border-color: transparent #ddd #ddd #ddd;
+}
+
+.tabs-left > .nav-tabs > li,
+.tabs-right > .nav-tabs > li {
+  float: none;
+}
+
+.tabs-left > .nav-tabs > li > a,
+.tabs-right > .nav-tabs > li > a {
+  min-width: 74px;
+  margin-right: 0;
+  margin-bottom: 3px;
+}
+
+.tabs-left > .nav-tabs {
+  float: left;
+  margin-right: 19px;
+  border-right: 1px solid #ddd;
+}
+
+.tabs-left > .nav-tabs > li > a {
+  margin-right: -1px;
+  -webkit-border-radius: 4px 0 0 4px;
+     -moz-border-radius: 4px 0 0 4px;
+          border-radius: 4px 0 0 4px;
+}
+
+.tabs-left > .nav-tabs > li > a:hover,
+.tabs-left > .nav-tabs > li > a:focus {
+  border-color: #eeeeee #dddddd #eeeeee #eeeeee;
+}
+
+.tabs-left > .nav-tabs .active > a,
+.tabs-left > .nav-tabs .active > a:hover,
+.tabs-left > .nav-tabs .active > a:focus {
+  border-color: #ddd transparent #ddd #ddd;
+  *border-right-color: #ffffff;
+}
+
+.tabs-right > .nav-tabs {
+  float: right;
+  margin-left: 19px;
+  border-left: 1px solid #ddd;
+}
+
+.tabs-right > .nav-tabs > li > a {
+  margin-left: -1px;
+  -webkit-border-radius: 0 4px 4px 0;
+     -moz-border-radius: 0 4px 4px 0;
+          border-radius: 0 4px 4px 0;
+}
+
+.tabs-right > .nav-tabs > li > a:hover,
+.tabs-right > .nav-tabs > li > a:focus {
+  border-color: #eeeeee #eeeeee #eeeeee #dddddd;
+}
+
+.tabs-right > .nav-tabs .active > a,
+.tabs-right > .nav-tabs .active > a:hover,
+.tabs-right > .nav-tabs .active > a:focus {
+  border-color: #ddd #ddd #ddd transparent;
+  *border-left-color: #ffffff;
+}
+
+.nav > .disabled > a {
+  color: #999999;
+}
+
+.nav > .disabled > a:hover,
+.nav > .disabled > a:focus {
+  text-decoration: none;
+  cursor: default;
+  background-color: transparent;
+}
+
+.navbar {
+  *position: relative;
+  *z-index: 2;
+  margin-bottom: 20px;
+  overflow: visible;
+}
+
+.navbar-inner {
+  min-height: 40px;
+  padding-right: 20px;
+  padding-left: 20px;
+  background-color: #fafafa;
+  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));
+  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);
+  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);
+  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);
+  background-repeat: repeat-x;
+  border: 1px solid #d4d4d4;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);
+  *zoom: 1;
+  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+          box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+}
+
+.navbar-inner:before,
+.navbar-inner:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.navbar-inner:after {
+  clear: both;
+}
+
+.navbar .container {
+  width: auto;
+}
+
+.nav-collapse.collapse {
+  height: auto;
+  overflow: visible;
+}
+
+.navbar .brand {
+  display: block;
+  float: left;
+  padding: 10px 20px 10px;
+  margin-left: -20px;
+  font-size: 20px;
+  font-weight: 200;
+  color: #777777;
+  text-shadow: 0 1px 0 #ffffff;
+}
+
+.navbar .brand:hover,
+.navbar .brand:focus {
+  text-decoration: none;
+}
+
+.navbar-text {
+  margin-bottom: 0;
+  line-height: 40px;
+  color: #777777;
+}
+
+.navbar-link {
+  color: #777777;
+}
+
+.navbar-link:hover,
+.navbar-link:focus {
+  color: #333333;
+}
+
+.navbar .divider-vertical {
+  height: 40px;
+  margin: 0 9px;
+  border-right: 1px solid #ffffff;
+  border-left: 1px solid #f2f2f2;
+}
+
+.navbar .btn,
+.navbar .btn-group {
+  margin-top: 5px;
+}
+
+.navbar .btn-group .btn,
+.navbar .input-prepend .btn,
+.navbar .input-append .btn,
+.navbar .input-prepend .btn-group,
+.navbar .input-append .btn-group {
+  margin-top: 0;
+}
+
+.navbar-form {
+  margin-bottom: 0;
+  *zoom: 1;
+}
+
+.navbar-form:before,
+.navbar-form:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.navbar-form:after {
+  clear: both;
+}
+
+.navbar-form input,
+.navbar-form select,
+.navbar-form .radio,
+.navbar-form .checkbox {
+  margin-top: 5px;
+}
+
+.navbar-form input,
+.navbar-form select,
+.navbar-form .btn {
+  display: inline-block;
+  margin-bottom: 0;
+}
+
+.navbar-form input[type="image"],
+.navbar-form input[type="checkbox"],
+.navbar-form input[type="radio"] {
+  margin-top: 3px;
+}
+
+.navbar-form .input-append,
+.navbar-form .input-prepend {
+  margin-top: 5px;
+  white-space: nowrap;
+}
+
+.navbar-form .input-append input,
+.navbar-form .input-prepend input {
+  margin-top: 0;
+}
+
+.navbar-search {
+  position: relative;
+  float: left;
+  margin-top: 5px;
+  margin-bottom: 0;
+}
+
+.navbar-search .search-query {
+  padding: 4px 14px;
+  margin-bottom: 0;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 13px;
+  font-weight: normal;
+  line-height: 1;
+  -webkit-border-radius: 15px;
+     -moz-border-radius: 15px;
+          border-radius: 15px;
+}
+
+.navbar-static-top {
+  position: static;
+  margin-bottom: 0;
+}
+
+.navbar-static-top .navbar-inner {
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  position: fixed;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+  margin-bottom: 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-static-top .navbar-inner {
+  border-width: 0 0 1px;
+}
+
+.navbar-fixed-bottom .navbar-inner {
+  border-width: 1px 0 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-fixed-bottom .navbar-inner {
+  padding-right: 0;
+  padding-left: 0;
+  -webkit-border-radius: 0;
+     -moz-border-radius: 0;
+          border-radius: 0;
+}
+
+.navbar-static-top .container,
+.navbar-fixed-top .container,
+.navbar-fixed-bottom .container {
+  width: 940px;
+}
+
+.navbar-fixed-top {
+  top: 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-static-top .navbar-inner {
+  -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+     -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+          box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+}
+
+.navbar-fixed-bottom {
+  bottom: 0;
+}
+
+.navbar-fixed-bottom .navbar-inner {
+  -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+     -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+          box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+}
+
+.navbar .nav {
+  position: relative;
+  left: 0;
+  display: block;
+  float: left;
+  margin: 0 10px 0 0;
+}
+
+.navbar .nav.pull-right {
+  float: right;
+  margin-right: 0;
+}
+
+.navbar .nav > li {
+  float: left;
+}
+
+.navbar .nav > li > a {
+  float: none;
+  padding: 10px 15px 10px;
+  color: #777777;
+  text-decoration: none;
+  text-shadow: 0 1px 0 #ffffff;
+}
+
+.navbar .nav .dropdown-toggle .caret {
+  margin-top: 8px;
+}
+
+.navbar .nav > li > a:focus,
+.navbar .nav > li > a:hover {
+  color: #333333;
+  text-decoration: none;
+  background-color: transparent;
+}
+
+.navbar .nav > .active > a,
+.navbar .nav > .active > a:hover,
+.navbar .nav > .active > a:focus {
+  color: #555555;
+  text-decoration: none;
+  background-color: #e5e5e5;
+  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+     -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+          box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+}
+
+.navbar .btn-navbar {
+  display: none;
+  float: right;
+  padding: 7px 10px;
+  margin-right: 5px;
+  margin-left: 5px;
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #ededed;
+  *background-color: #e5e5e5;
+  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));
+  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);
+  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);
+  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);
+  background-repeat: repeat-x;
+  border-color: #e5e5e5 #e5e5e5 #bfbfbf;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+     -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+}
+
+.navbar .btn-navbar:hover,
+.navbar .btn-navbar:focus,
+.navbar .btn-navbar:active,
+.navbar .btn-navbar.active,
+.navbar .btn-navbar.disabled,
+.navbar .btn-navbar[disabled] {
+  color: #ffffff;
+  background-color: #e5e5e5;
+  *background-color: #d9d9d9;
+}
+
+.navbar .btn-navbar:active,
+.navbar .btn-navbar.active {
+  background-color: #cccccc \9;
+}
+
+.navbar .btn-navbar .icon-bar {
+  display: block;
+  width: 18px;
+  height: 2px;
+  background-color: #f5f5f5;
+  -webkit-border-radius: 1px;
+     -moz-border-radius: 1px;
+          border-radius: 1px;
+  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+     -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+          box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+}
+
+.btn-navbar .icon-bar + .icon-bar {
+  margin-top: 3px;
+}
+
+.navbar .nav > li > .dropdown-menu:before {
+  position: absolute;
+  top: -7px;
+  left: 9px;
+  display: inline-block;
+  border-right: 7px solid transparent;
+  border-bottom: 7px solid #ccc;
+  border-left: 7px solid transparent;
+  border-bottom-color: rgba(0, 0, 0, 0.2);
+  content: '';
+}
+
+.navbar .nav > li > .dropdown-menu:after {
+  position: absolute;
+  top: -6px;
+  left: 10px;
+  display: inline-block;
+  border-right: 6px solid transparent;
+  border-bottom: 6px solid #ffffff;
+  border-left: 6px solid transparent;
+  content: '';
+}
+
+.navbar-fixed-bottom .nav > li > .dropdown-menu:before {
+  top: auto;
+  bottom: -7px;
+  border-top: 7px solid #ccc;
+  border-bottom: 0;
+  border-top-color: rgba(0, 0, 0, 0.2);
+}
+
+.navbar-fixed-bottom .nav > li > .dropdown-menu:after {
+  top: auto;
+  bottom: -6px;
+  border-top: 6px solid #ffffff;
+  border-bottom: 0;
+}
+
+.navbar .nav li.dropdown > a:hover .caret,
+.navbar .nav li.dropdown > a:focus .caret {
+  border-top-color: #333333;
+  border-bottom-color: #333333;
+}
+
+.navbar .nav li.dropdown.open > .dropdown-toggle,
+.navbar .nav li.dropdown.active > .dropdown-toggle,
+.navbar .nav li.dropdown.open.active > .dropdown-toggle {
+  color: #555555;
+  background-color: #e5e5e5;
+}
+
+.navbar .nav li.dropdown > .dropdown-toggle .caret {
+  border-top-color: #777777;
+  border-bottom-color: #777777;
+}
+
+.navbar .nav li.dropdown.open > .dropdown-toggle .caret,
+.navbar .nav li.dropdown.active > .dropdown-toggle .caret,
+.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {
+  border-top-color: #555555;
+  border-bottom-color: #555555;
+}
+
+.navbar .pull-right > li > .dropdown-menu,
+.navbar .nav > li > .dropdown-menu.pull-right {
+  right: 0;
+  left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu:before,
+.navbar .nav > li > .dropdown-menu.pull-right:before {
+  right: 12px;
+  left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu:after,
+.navbar .nav > li > .dropdown-menu.pull-right:after {
+  right: 13px;
+  left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu .dropdown-menu,
+.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {
+  right: 100%;
+  left: auto;
+  margin-right: -1px;
+  margin-left: 0;
+  -webkit-border-radius: 6px 0 6px 6px;
+     -moz-border-radius: 6px 0 6px 6px;
+          border-radius: 6px 0 6px 6px;
+}
+
+.navbar-inverse .navbar-inner {
+  background-color: #1b1b1b;
+  background-image: -moz-linear-gradient(top, #222222, #111111);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));
+  background-image: -webkit-linear-gradient(top, #222222, #111111);
+  background-image: -o-linear-gradient(top, #222222, #111111);
+  background-image: linear-gradient(to bottom, #222222, #111111);
+  background-repeat: repeat-x;
+  border-color: #252525;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);
+}
+
+.navbar-inverse .brand,
+.navbar-inverse .nav > li > a {
+  color: #999999;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+
+.navbar-inverse .brand:hover,
+.navbar-inverse .nav > li > a:hover,
+.navbar-inverse .brand:focus,
+.navbar-inverse .nav > li > a:focus {
+  color: #ffffff;
+}
+
+.navbar-inverse .brand {
+  color: #999999;
+}
+
+.navbar-inverse .navbar-text {
+  color: #999999;
+}
+
+.navbar-inverse .nav > li > a:focus,
+.navbar-inverse .nav > li > a:hover {
+  color: #ffffff;
+  background-color: transparent;
+}
+
+.navbar-inverse .nav .active > a,
+.navbar-inverse .nav .active > a:hover,
+.navbar-inverse .nav .active > a:focus {
+  color: #ffffff;
+  background-color: #111111;
+}
+
+.navbar-inverse .navbar-link {
+  color: #999999;
+}
+
+.navbar-inverse .navbar-link:hover,
+.navbar-inverse .navbar-link:focus {
+  color: #ffffff;
+}
+
+.navbar-inverse .divider-vertical {
+  border-right-color: #222222;
+  border-left-color: #111111;
+}
+
+.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,
+.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,
+.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {
+  color: #ffffff;
+  background-color: #111111;
+}
+
+.navbar-inverse .nav li.dropdown > a:hover .caret,
+.navbar-inverse .nav li.dropdown > a:focus .caret {
+  border-top-color: #ffffff;
+  border-bottom-color: #ffffff;
+}
+
+.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {
+  border-top-color: #999999;
+  border-bottom-color: #999999;
+}
+
+.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,
+.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,
+.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {
+  border-top-color: #ffffff;
+  border-bottom-color: #ffffff;
+}
+
+.navbar-inverse .navbar-search .search-query {
+  color: #ffffff;
+  background-color: #515151;
+  border-color: #111111;
+  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+  -webkit-transition: none;
+     -moz-transition: none;
+       -o-transition: none;
+          transition: none;
+}
+
+.navbar-inverse .navbar-search .search-query:-moz-placeholder {
+  color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {
+  color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {
+  color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query:focus,
+.navbar-inverse .navbar-search .search-query.focused {
+  padding: 5px 15px;
+  color: #333333;
+  text-shadow: 0 1px 0 #ffffff;
+  background-color: #ffffff;
+  border: 0;
+  outline: 0;
+  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+     -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+          box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+}
+
+.navbar-inverse .btn-navbar {
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #0e0e0e;
+  *background-color: #040404;
+  background-image: -moz-linear-gradient(top, #151515, #040404);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));
+  background-image: -webkit-linear-gradient(top, #151515, #040404);
+  background-image: -o-linear-gradient(top, #151515, #040404);
+  background-image: linear-gradient(to bottom, #151515, #040404);
+  background-repeat: repeat-x;
+  border-color: #040404 #040404 #000000;
+  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.navbar-inverse .btn-navbar:hover,
+.navbar-inverse .btn-navbar:focus,
+.navbar-inverse .btn-navbar:active,
+.navbar-inverse .btn-navbar.active,
+.navbar-inverse .btn-navbar.disabled,
+.navbar-inverse .btn-navbar[disabled] {
+  color: #ffffff;
+  background-color: #040404;
+  *background-color: #000000;
+}
+
+.navbar-inverse .btn-navbar:active,
+.navbar-inverse .btn-navbar.active {
+  background-color: #000000 \9;
+}
+
+.breadcrumb {
+  padding: 8px 15px;
+  margin: 0 0 20px;
+  list-style: none;
+  background-color: #f5f5f5;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.breadcrumb > li {
+  display: inline-block;
+  *display: inline;
+  text-shadow: 0 1px 0 #ffffff;
+  *zoom: 1;
+}
+
+.breadcrumb > li > .divider {
+  padding: 0 5px;
+  color: #ccc;
+}
+
+.breadcrumb > .active {
+  color: #999999;
+}
+
+.pagination {
+  margin: 20px 0;
+}
+
+.pagination ul {
+  display: inline-block;
+  *display: inline;
+  margin-bottom: 0;
+  margin-left: 0;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  *zoom: 1;
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.pagination ul > li {
+  display: inline;
+}
+
+.pagination ul > li > a,
+.pagination ul > li > span {
+  float: left;
+  padding: 4px 12px;
+  line-height: 20px;
+  text-decoration: none;
+  background-color: #ffffff;
+  border: 1px solid #dddddd;
+  border-left-width: 0;
+}
+
+.pagination ul > li > a:hover,
+.pagination ul > li > a:focus,
+.pagination ul > .active > a,
+.pagination ul > .active > span {
+  background-color: #f5f5f5;
+}
+
+.pagination ul > .active > a,
+.pagination ul > .active > span {
+  color: #999999;
+  cursor: default;
+}
+
+.pagination ul > .disabled > span,
+.pagination ul > .disabled > a,
+.pagination ul > .disabled > a:hover,
+.pagination ul > .disabled > a:focus {
+  color: #999999;
+  cursor: default;
+  background-color: transparent;
+}
+
+.pagination ul > li:first-child > a,
+.pagination ul > li:first-child > span {
+  border-left-width: 1px;
+  -webkit-border-bottom-left-radius: 4px;
+          border-bottom-left-radius: 4px;
+  -webkit-border-top-left-radius: 4px;
+          border-top-left-radius: 4px;
+  -moz-border-radius-bottomleft: 4px;
+  -moz-border-radius-topleft: 4px;
+}
+
+.pagination ul > li:last-child > a,
+.pagination ul > li:last-child > span {
+  -webkit-border-top-right-radius: 4px;
+          border-top-right-radius: 4px;
+  -webkit-border-bottom-right-radius: 4px;
+          border-bottom-right-radius: 4px;
+  -moz-border-radius-topright: 4px;
+  -moz-border-radius-bottomright: 4px;
+}
+
+.pagination-centered {
+  text-align: center;
+}
+
+.pagination-right {
+  text-align: right;
+}
+
+.pagination-large ul > li > a,
+.pagination-large ul > li > span {
+  padding: 11px 19px;
+  font-size: 17.5px;
+}
+
+.pagination-large ul > li:first-child > a,
+.pagination-large ul > li:first-child > span {
+  -webkit-border-bottom-left-radius: 6px;
+          border-bottom-left-radius: 6px;
+  -webkit-border-top-left-radius: 6px;
+          border-top-left-radius: 6px;
+  -moz-border-radius-bottomleft: 6px;
+  -moz-border-radius-topleft: 6px;
+}
+
+.pagination-large ul > li:last-child > a,
+.pagination-large ul > li:last-child > span {
+  -webkit-border-top-right-radius: 6px;
+          border-top-right-radius: 6px;
+  -webkit-border-bottom-right-radius: 6px;
+          border-bottom-right-radius: 6px;
+  -moz-border-radius-topright: 6px;
+  -moz-border-radius-bottomright: 6px;
+}
+
+.pagination-mini ul > li:first-child > a,
+.pagination-small ul > li:first-child > a,
+.pagination-mini ul > li:first-child > span,
+.pagination-small ul > li:first-child > span {
+  -webkit-border-bottom-left-radius: 3px;
+          border-bottom-left-radius: 3px;
+  -webkit-border-top-left-radius: 3px;
+          border-top-left-radius: 3px;
+  -moz-border-radius-bottomleft: 3px;
+  -moz-border-radius-topleft: 3px;
+}
+
+.pagination-mini ul > li:last-child > a,
+.pagination-small ul > li:last-child > a,
+.pagination-mini ul > li:last-child > span,
+.pagination-small ul > li:last-child > span {
+  -webkit-border-top-right-radius: 3px;
+          border-top-right-radius: 3px;
+  -webkit-border-bottom-right-radius: 3px;
+          border-bottom-right-radius: 3px;
+  -moz-border-radius-topright: 3px;
+  -moz-border-radius-bottomright: 3px;
+}
+
+.pagination-small ul > li > a,
+.pagination-small ul > li > span {
+  padding: 2px 10px;
+  font-size: 11.9px;
+}
+
+.pagination-mini ul > li > a,
+.pagination-mini ul > li > span {
+  padding: 0 6px;
+  font-size: 10.5px;
+}
+
+.pager {
+  margin: 20px 0;
+  text-align: center;
+  list-style: none;
+  *zoom: 1;
+}
+
+.pager:before,
+.pager:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.pager:after {
+  clear: both;
+}
+
+.pager li {
+  display: inline;
+}
+
+.pager li > a,
+.pager li > span {
+  display: inline-block;
+  padding: 5px 14px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  -webkit-border-radius: 15px;
+     -moz-border-radius: 15px;
+          border-radius: 15px;
+}
+
+.pager li > a:hover,
+.pager li > a:focus {
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.pager .next > a,
+.pager .next > span {
+  float: right;
+}
+
+.pager .previous > a,
+.pager .previous > span {
+  float: left;
+}
+
+.pager .disabled > a,
+.pager .disabled > a:hover,
+.pager .disabled > a:focus,
+.pager .disabled > span {
+  color: #999999;
+  cursor: default;
+  background-color: #fff;
+}
+
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1040;
+  background-color: #000000;
+}
+
+.modal-backdrop.fade {
+  opacity: 0;
+}
+
+.modal-backdrop,
+.modal-backdrop.fade.in {
+  opacity: 0.8;
+  filter: alpha(opacity=80);
+}
+
+.modal {
+  position: fixed;
+  top: 10%;
+  left: 50%;
+  z-index: 1050;
+  width: 560px;
+  margin-left: -280px;
+  background-color: #ffffff;
+  border: 1px solid #999;
+  border: 1px solid rgba(0, 0, 0, 0.3);
+  *border: 1px solid #999;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+  outline: none;
+  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+     -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+          box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+  -webkit-background-clip: padding-box;
+     -moz-background-clip: padding-box;
+          background-clip: padding-box;
+}
+
+.modal.fade {
+  top: -25%;
+  -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;
+     -moz-transition: opacity 0.3s linear, top 0.3s ease-out;
+       -o-transition: opacity 0.3s linear, top 0.3s ease-out;
+          transition: opacity 0.3s linear, top 0.3s ease-out;
+}
+
+.modal.fade.in {
+  top: 10%;
+}
+
+.modal-header {
+  padding: 9px 15px;
+  border-bottom: 1px solid #eee;
+}
+
+.modal-header .close {
+  margin-top: 2px;
+}
+
+.modal-header h3 {
+  margin: 0;
+  line-height: 30px;
+}
+
+.modal-body {
+  position: relative;
+  max-height: 400px;
+  padding: 15px;
+  overflow-y: auto;
+}
+
+.modal-form {
+  margin-bottom: 0;
+}
+
+.modal-footer {
+  padding: 14px 15px 15px;
+  margin-bottom: 0;
+  text-align: right;
+  background-color: #f5f5f5;
+  border-top: 1px solid #ddd;
+  -webkit-border-radius: 0 0 6px 6px;
+     -moz-border-radius: 0 0 6px 6px;
+          border-radius: 0 0 6px 6px;
+  *zoom: 1;
+  -webkit-box-shadow: inset 0 1px 0 #ffffff;
+     -moz-box-shadow: inset 0 1px 0 #ffffff;
+          box-shadow: inset 0 1px 0 #ffffff;
+}
+
+.modal-footer:before,
+.modal-footer:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.modal-footer:after {
+  clear: both;
+}
+
+.modal-footer .btn + .btn {
+  margin-bottom: 0;
+  margin-left: 5px;
+}
+
+.modal-footer .btn-group .btn + .btn {
+  margin-left: -1px;
+}
+
+.modal-footer .btn-block + .btn-block {
+  margin-left: 0;
+}
+
+.tooltip {
+  position: absolute;
+  z-index: 1030;
+  display: block;
+  font-size: 11px;
+  line-height: 1.4;
+  opacity: 0;
+  filter: alpha(opacity=0);
+  visibility: visible;
+}
+
+.tooltip.in {
+  opacity: 0.8;
+  filter: alpha(opacity=80);
+}
+
+.tooltip.top {
+  padding: 5px 0;
+  margin-top: -3px;
+}
+
+.tooltip.right {
+  padding: 0 5px;
+  margin-left: 3px;
+}
+
+.tooltip.bottom {
+  padding: 5px 0;
+  margin-top: 3px;
+}
+
+.tooltip.left {
+  padding: 0 5px;
+  margin-left: -3px;
+}
+
+.tooltip-inner {
+  max-width: 200px;
+  padding: 8px;
+  color: #ffffff;
+  text-align: center;
+  text-decoration: none;
+  background-color: #000000;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.tooltip-arrow {
+  position: absolute;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.tooltip.top .tooltip-arrow {
+  bottom: 0;
+  left: 50%;
+  margin-left: -5px;
+  border-top-color: #000000;
+  border-width: 5px 5px 0;
+}
+
+.tooltip.right .tooltip-arrow {
+  top: 50%;
+  left: 0;
+  margin-top: -5px;
+  border-right-color: #000000;
+  border-width: 5px 5px 5px 0;
+}
+
+.tooltip.left .tooltip-arrow {
+  top: 50%;
+  right: 0;
+  margin-top: -5px;
+  border-left-color: #000000;
+  border-width: 5px 0 5px 5px;
+}
+
+.tooltip.bottom .tooltip-arrow {
+  top: 0;
+  left: 50%;
+  margin-left: -5px;
+  border-bottom-color: #000000;
+  border-width: 0 5px 5px;
+}
+
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1010;
+  display: none;
+  max-width: 276px;
+  padding: 1px;
+  text-align: left;
+  white-space: normal;
+  background-color: #ffffff;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  -webkit-background-clip: padding-box;
+     -moz-background-clip: padding;
+          background-clip: padding-box;
+}
+
+.popover.top {
+  margin-top: -10px;
+}
+
+.popover.right {
+  margin-left: 10px;
+}
+
+.popover.bottom {
+  margin-top: 10px;
+}
+
+.popover.left {
+  margin-left: -10px;
+}
+
+.popover-title {
+  padding: 8px 14px;
+  margin: 0;
+  font-size: 14px;
+  font-weight: normal;
+  line-height: 18px;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  -webkit-border-radius: 5px 5px 0 0;
+     -moz-border-radius: 5px 5px 0 0;
+          border-radius: 5px 5px 0 0;
+}
+
+.popover-title:empty {
+  display: none;
+}
+
+.popover-content {
+  padding: 9px 14px;
+}
+
+.popover .arrow,
+.popover .arrow:after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover .arrow {
+  border-width: 11px;
+}
+
+.popover .arrow:after {
+  border-width: 10px;
+  content: "";
+}
+
+.popover.top .arrow {
+  bottom: -11px;
+  left: 50%;
+  margin-left: -11px;
+  border-top-color: #999;
+  border-top-color: rgba(0, 0, 0, 0.25);
+  border-bottom-width: 0;
+}
+
+.popover.top .arrow:after {
+  bottom: 1px;
+  margin-left: -10px;
+  border-top-color: #ffffff;
+  border-bottom-width: 0;
+}
+
+.popover.right .arrow {
+  top: 50%;
+  left: -11px;
+  margin-top: -11px;
+  border-right-color: #999;
+  border-right-color: rgba(0, 0, 0, 0.25);
+  border-left-width: 0;
+}
+
+.popover.right .arrow:after {
+  bottom: -10px;
+  left: 1px;
+  border-right-color: #ffffff;
+  border-left-width: 0;
+}
+
+.popover.bottom .arrow {
+  top: -11px;
+  left: 50%;
+  margin-left: -11px;
+  border-bottom-color: #999;
+  border-bottom-color: rgba(0, 0, 0, 0.25);
+  border-top-width: 0;
+}
+
+.popover.bottom .arrow:after {
+  top: 1px;
+  margin-left: -10px;
+  border-bottom-color: #ffffff;
+  border-top-width: 0;
+}
+
+.popover.left .arrow {
+  top: 50%;
+  right: -11px;
+  margin-top: -11px;
+  border-left-color: #999;
+  border-left-color: rgba(0, 0, 0, 0.25);
+  border-right-width: 0;
+}
+
+.popover.left .arrow:after {
+  right: 1px;
+  bottom: -10px;
+  border-left-color: #ffffff;
+  border-right-width: 0;
+}
+
+.thumbnails {
+  margin-left: -20px;
+  list-style: none;
+  *zoom: 1;
+}
+
+.thumbnails:before,
+.thumbnails:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.thumbnails:after {
+  clear: both;
+}
+
+.row-fluid .thumbnails {
+  margin-left: 0;
+}
+
+.thumbnails > li {
+  float: left;
+  margin-bottom: 20px;
+  margin-left: 20px;
+}
+
+.thumbnail {
+  display: block;
+  padding: 4px;
+  line-height: 20px;
+  border: 1px solid #ddd;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+     -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+          box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+  -webkit-transition: all 0.2s ease-in-out;
+     -moz-transition: all 0.2s ease-in-out;
+       -o-transition: all 0.2s ease-in-out;
+          transition: all 0.2s ease-in-out;
+}
+
+a.thumbnail:hover,
+a.thumbnail:focus {
+  border-color: #0088cc;
+  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+     -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+          box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+}
+
+.thumbnail > img {
+  display: block;
+  max-width: 100%;
+  margin-right: auto;
+  margin-left: auto;
+}
+
+.thumbnail .caption {
+  padding: 9px;
+  color: #555555;
+}
+
+.media,
+.media-body {
+  overflow: hidden;
+  *overflow: visible;
+  zoom: 1;
+}
+
+.media,
+.media .media {
+  margin-top: 15px;
+}
+
+.media:first-child {
+  margin-top: 0;
+}
+
+.media-object {
+  display: block;
+}
+
+.media-heading {
+  margin: 0 0 5px;
+}
+
+.media > .pull-left {
+  margin-right: 10px;
+}
+
+.media > .pull-right {
+  margin-left: 10px;
+}
+
+.media-list {
+  margin-left: 0;
+  list-style: none;
+}
+
+.label,
+.badge {
+  display: inline-block;
+  padding: 2px 4px;
+  font-size: 11.844px;
+  font-weight: bold;
+  line-height: 14px;
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  white-space: nowrap;
+  vertical-align: baseline;
+  background-color: #999999;
+}
+
+.label {
+  -webkit-border-radius: 3px;
+     -moz-border-radius: 3px;
+          border-radius: 3px;
+}
+
+.badge {
+  padding-right: 9px;
+  padding-left: 9px;
+  -webkit-border-radius: 9px;
+     -moz-border-radius: 9px;
+          border-radius: 9px;
+}
+
+.label:empty,
+.badge:empty {
+  display: none;
+}
+
+a.label:hover,
+a.label:focus,
+a.badge:hover,
+a.badge:focus {
+  color: #ffffff;
+  text-decoration: none;
+  cursor: pointer;
+}
+
+.label-important,
+.badge-important {
+  background-color: #b94a48;
+}
+
+.label-important[href],
+.badge-important[href] {
+  background-color: #953b39;
+}
+
+.label-warning,
+.badge-warning {
+  background-color: #f89406;
+}
+
+.label-warning[href],
+.badge-warning[href] {
+  background-color: #c67605;
+}
+
+.label-success,
+.badge-success {
+  background-color: #468847;
+}
+
+.label-success[href],
+.badge-success[href] {
+  background-color: #356635;
+}
+
+.label-info,
+.badge-info {
+  background-color: #3a87ad;
+}
+
+.label-info[href],
+.badge-info[href] {
+  background-color: #2d6987;
+}
+
+.label-inverse,
+.badge-inverse {
+  background-color: #333333;
+}
+
+.label-inverse[href],
+.badge-inverse[href] {
+  background-color: #1a1a1a;
+}
+
+.btn .label,
+.btn .badge {
+  position: relative;
+  top: -1px;
+}
+
+.btn-mini .label,
+.btn-mini .badge {
+  top: 0;
+}
+
+@-webkit-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@-moz-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@-ms-keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@-o-keyframes progress-bar-stripes {
+  from {
+    background-position: 0 0;
+  }
+  to {
+    background-position: 40px 0;
+  }
+}
+
+@keyframes progress-bar-stripes {
+  from {
+    background-position: 40px 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+.progress {
+  height: 20px;
+  margin-bottom: 20px;
+  overflow: hidden;
+  background-color: #f7f7f7;
+  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));
+  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);
+  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);
+  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);
+  background-repeat: repeat-x;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);
+  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+     -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+
+.progress .bar {
+  float: left;
+  width: 0;
+  height: 100%;
+  font-size: 12px;
+  color: #ffffff;
+  text-align: center;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+  background-color: #0e90d2;
+  background-image: -moz-linear-gradient(top, #149bdf, #0480be);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));
+  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);
+  background-image: -o-linear-gradient(top, #149bdf, #0480be);
+  background-image: linear-gradient(to bottom, #149bdf, #0480be);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);
+  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+     -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+  -webkit-transition: width 0.6s ease;
+     -moz-transition: width 0.6s ease;
+       -o-transition: width 0.6s ease;
+          transition: width 0.6s ease;
+}
+
+.progress .bar + .bar {
+  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+     -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+          box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+}
+
+.progress-striped .bar {
+  background-color: #149bdf;
+  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  -webkit-background-size: 40px 40px;
+     -moz-background-size: 40px 40px;
+       -o-background-size: 40px 40px;
+          background-size: 40px 40px;
+}
+
+.progress.active .bar {
+  -webkit-animation: progress-bar-stripes 2s linear infinite;
+     -moz-animation: progress-bar-stripes 2s linear infinite;
+      -ms-animation: progress-bar-stripes 2s linear infinite;
+       -o-animation: progress-bar-stripes 2s linear infinite;
+          animation: progress-bar-stripes 2s linear infinite;
+}
+
+.progress-danger .bar,
+.progress .bar-danger {
+  background-color: #dd514c;
+  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));
+  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
+  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
+  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);
+}
+
+.progress-danger.progress-striped .bar,
+.progress-striped .bar-danger {
+  background-color: #ee5f5b;
+  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-success .bar,
+.progress .bar-success {
+  background-color: #5eb95e;
+  background-image: -moz-linear-gradient(top, #62c462, #57a957);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));
+  background-image: -webkit-linear-gradient(top, #62c462, #57a957);
+  background-image: -o-linear-gradient(top, #62c462, #57a957);
+  background-image: linear-gradient(to bottom, #62c462, #57a957);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);
+}
+
+.progress-success.progress-striped .bar,
+.progress-striped .bar-success {
+  background-color: #62c462;
+  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-info .bar,
+.progress .bar-info {
+  background-color: #4bb1cf;
+  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));
+  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
+  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
+  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);
+}
+
+.progress-info.progress-striped .bar,
+.progress-striped .bar-info {
+  background-color: #5bc0de;
+  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-warning .bar,
+.progress .bar-warning {
+  background-color: #faa732;
+  background-image: -moz-linear-gradient(top, #fbb450, #f89406);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
+  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
+  background-image: -o-linear-gradient(top, #fbb450, #f89406);
+  background-image: linear-gradient(to bottom, #fbb450, #f89406);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
+}
+
+.progress-warning.progress-striped .bar,
+.progress-striped .bar-warning {
+  background-color: #fbb450;
+  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.accordion {
+  margin-bottom: 20px;
+}
+
+.accordion-group {
+  margin-bottom: 2px;
+  border: 1px solid #e5e5e5;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+}
+
+.accordion-heading {
+  border-bottom: 0;
+}
+
+.accordion-heading .accordion-toggle {
+  display: block;
+  padding: 8px 15px;
+}
+
+.accordion-toggle {
+  cursor: pointer;
+}
+
+.accordion-inner {
+  padding: 9px 15px;
+  border-top: 1px solid #e5e5e5;
+}
+
+.carousel {
+  position: relative;
+  margin-bottom: 20px;
+  line-height: 1;
+}
+
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+
+.carousel-inner > .item {
+  position: relative;
+  display: none;
+  -webkit-transition: 0.6s ease-in-out left;
+     -moz-transition: 0.6s ease-in-out left;
+       -o-transition: 0.6s ease-in-out left;
+          transition: 0.6s ease-in-out left;
+}
+
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+  display: block;
+  line-height: 1;
+}
+
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  display: block;
+}
+
+.carousel-inner > .active {
+  left: 0;
+}
+
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+.carousel-inner > .next {
+  left: 100%;
+}
+
+.carousel-inner > .prev {
+  left: -100%;
+}
+
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+  left: 0;
+}
+
+.carousel-inner > .active.left {
+  left: -100%;
+}
+
+.carousel-inner > .active.right {
+  left: 100%;
+}
+
+.carousel-control {
+  position: absolute;
+  top: 40%;
+  left: 15px;
+  width: 40px;
+  height: 40px;
+  margin-top: -20px;
+  font-size: 60px;
+  font-weight: 100;
+  line-height: 30px;
+  color: #ffffff;
+  text-align: center;
+  background: #222222;
+  border: 3px solid #ffffff;
+  -webkit-border-radius: 23px;
+     -moz-border-radius: 23px;
+          border-radius: 23px;
+  opacity: 0.5;
+  filter: alpha(opacity=50);
+}
+
+.carousel-control.right {
+  right: 15px;
+  left: auto;
+}
+
+.carousel-control:hover,
+.carousel-control:focus {
+  color: #ffffff;
+  text-decoration: none;
+  opacity: 0.9;
+  filter: alpha(opacity=90);
+}
+
+.carousel-indicators {
+  position: absolute;
+  top: 15px;
+  right: 15px;
+  z-index: 5;
+  margin: 0;
+  list-style: none;
+}
+
+.carousel-indicators li {
+  display: block;
+  float: left;
+  width: 10px;
+  height: 10px;
+  margin-left: 5px;
+  text-indent: -999px;
+  background-color: #ccc;
+  background-color: rgba(255, 255, 255, 0.25);
+  border-radius: 5px;
+}
+
+.carousel-indicators .active {
+  background-color: #fff;
+}
+
+.carousel-caption {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 15px;
+  background: #333333;
+  background: rgba(0, 0, 0, 0.75);
+}
+
+.carousel-caption h4,
+.carousel-caption p {
+  line-height: 20px;
+  color: #ffffff;
+}
+
+.carousel-caption h4 {
+  margin: 0 0 5px;
+}
+
+.carousel-caption p {
+  margin-bottom: 0;
+}
+
+.hero-unit {
+  padding: 60px;
+  margin-bottom: 30px;
+  font-size: 18px;
+  font-weight: 200;
+  line-height: 30px;
+  color: inherit;
+  background-color: #eeeeee;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+}
+
+.hero-unit h1 {
+  margin-bottom: 0;
+  font-size: 60px;
+  line-height: 1;
+  letter-spacing: -1px;
+  color: inherit;
+}
+
+.hero-unit li {
+  line-height: 30px;
+}
+
+.pull-right {
+  float: right;
+}
+
+.pull-left {
+  float: left;
+}
+
+.hide {
+  display: none;
+}
+
+.show {
+  display: block;
+}
+
+.invisible {
+  visibility: hidden;
+}
+
+.affix {
+  position: fixed;
+}
diff --git a/doc/asset/css/codemirror.css b/doc/asset/css/codemirror.css
new file mode 100644
index 0000000..9e14234
--- /dev/null
+++ b/doc/asset/css/codemirror.css
@@ -0,0 +1,245 @@
+/* BASICS */
+
+.CodeMirror {
+  /* Set height, width, borders, and global font properties here */
+  font-family: monospace;
+  height: 420px;
+}
+.CodeMirror-scroll {
+  /* Set scrolling behaviour here */
+  overflow: auto;
+}
+
+/* PADDING */
+
+.CodeMirror-lines {
+  padding: 4px 0; /* Vertical padding around content */
+}
+.CodeMirror pre {
+  padding: 0 4px; /* Horizontal padding of content */
+}
+
+.CodeMirror-scrollbar-filler {
+  background-color: white; /* The little square between H and V scrollbars */
+}
+
+/* GUTTER */
+
+.CodeMirror-gutters {
+  border-right: 1px solid #ddd;
+  background-color: #f7f7f7;
+}
+.CodeMirror-linenumbers {}
+.CodeMirror-linenumber {
+  padding: 0 3px 0 5px;
+  min-width: 20px;
+  text-align: right;
+  color: #999;
+}
+
+/* CURSOR */
+
+.CodeMirror div.CodeMirror-cursor {
+  border-left: 1px solid black;
+}
+/* Shown when moving in bi-directional text */
+.CodeMirror div.CodeMirror-secondarycursor {
+  border-left: 1px solid silver;
+}
+.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
+  width: auto;
+  border: 0;
+  background: transparent;
+  background: rgba(0, 200, 0, .4);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
+}
+/* Kludge to turn off filter in ie9+, which also accepts rgba */
+.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor:not(#nonsense_id) {
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+/* Can style cursor different in overwrite (non-insert) mode */
+.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
+
+/* DEFAULT THEME */
+
+.cm-s-default .cm-keyword {color: #708;}
+.cm-s-default .cm-atom {color: #219;}
+.cm-s-default .cm-number {color: #164;}
+.cm-s-default .cm-def {color: #00f;}
+.cm-s-default .cm-variable {color: black;}
+.cm-s-default .cm-variable-2 {color: #05a;}
+.cm-s-default .cm-variable-3 {color: #085;}
+.cm-s-default .cm-property {color: black;}
+.cm-s-default .cm-operator {color: black;}
+.cm-s-default .cm-comment {color: #a50;}
+.cm-s-default .cm-string {color: #a11;}
+.cm-s-default .cm-string-2 {color: #f50;}
+.cm-s-default .cm-meta {color: #555;}
+.cm-s-default .cm-error {color: #f00;}
+.cm-s-default .cm-qualifier {color: #555;}
+.cm-s-default .cm-builtin {color: #30a;}
+.cm-s-default .cm-bracket {color: #997;}
+.cm-s-default .cm-tag {color: #170;}
+.cm-s-default .cm-attribute {color: #00c;}
+.cm-s-default .cm-header {color: blue;}
+.cm-s-default .cm-quote {color: #090;}
+.cm-s-default .cm-hr {color: #999;}
+.cm-s-default .cm-link {color: #00c;}
+
+.cm-negative {color: #d44;}
+.cm-positive {color: #292;}
+.cm-header, .cm-strong {font-weight: bold;}
+.cm-em {font-style: italic;}
+.cm-emstrong {font-style: italic; font-weight: bold;}
+.cm-link {text-decoration: underline;}
+
+.cm-invalidchar {color: #f00;}
+
+div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
+div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
+
+/* STOP */
+
+/* The rest of this file contains styles related to the mechanics of
+   the editor. You probably shouldn't touch them. */
+
+.CodeMirror {
+  line-height: 1;
+  position: relative;
+  overflow: hidden;
+}
+
+.CodeMirror-scroll {
+  /* 30px is the magic margin used to hide the element's real scrollbars */
+  /* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */
+  margin-bottom: -30px; margin-right: -30px;
+  padding-bottom: 30px; padding-right: 30px;
+  height: 100%;
+  outline: none; /* Prevent dragging from highlighting the element */
+  position: relative;
+}
+.CodeMirror-sizer {
+  position: relative;
+}
+
+/* The fake, visible scrollbars. Used to force redraw during scrolling
+   before actuall scrolling happens, thus preventing shaking and
+   flickering artifacts. */
+.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
+  position: absolute;
+  z-index: 6;
+  display: none;
+}
+.CodeMirror-vscrollbar {
+  right: 0; top: 0;
+  overflow-x: hidden;
+  overflow-y: scroll;
+}
+.CodeMirror-hscrollbar {
+  bottom: 0; left: 0;
+  overflow-y: hidden;
+  overflow-x: scroll;
+}
+.CodeMirror-scrollbar-filler {
+  right: 0; bottom: 0;
+  z-index: 6;
+}
+
+.CodeMirror-gutters {
+  position: absolute; left: 0; top: 0;
+  height: 100%;
+  padding-bottom: 30px;
+  z-index: 3;
+}
+.CodeMirror-gutter {
+  height: 100%;
+  display: inline-block;
+  /* Hack to make IE7 behave */
+  *zoom:1;
+  *display:inline;
+}
+.CodeMirror-gutter-elt {
+  position: absolute;
+  cursor: default;
+  z-index: 4;
+}
+
+.CodeMirror-lines {
+  cursor: text;
+}
+.CodeMirror pre {
+  /* Reset some styles that the rest of the page might have set */
+  -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0;
+  border-width: 0;
+  background: transparent;
+  font-family: inherit;
+  font-size: inherit;
+  margin: 0;
+  white-space: pre;
+  word-wrap: normal;
+  line-height: inherit;
+  color: inherit;
+  z-index: 2;
+  position: relative;
+  overflow: visible;
+}
+.CodeMirror-wrap pre {
+  word-wrap: break-word;
+  white-space: pre-wrap;
+  word-break: normal;
+}
+.CodeMirror-linebackground {
+  position: absolute;
+  left: 0; right: 0; top: 0; bottom: 0;
+  z-index: 0;
+}
+
+.CodeMirror-linewidget {
+  position: relative;
+  z-index: 2;
+  overflow: auto;
+}
+
+.CodeMirror-widget {
+  display: inline-block;
+}
+
+.CodeMirror-wrap .CodeMirror-scroll {
+  overflow-x: hidden;
+}
+
+.CodeMirror-measure {
+  position: absolute;
+  width: 100%; height: 0px;
+  overflow: hidden;
+  visibility: hidden;
+}
+.CodeMirror-measure pre { position: static; }
+
+.CodeMirror div.CodeMirror-cursor {
+  position: absolute;
+  visibility: hidden;
+  border-right: none;
+  width: 0;
+}
+.CodeMirror-focused div.CodeMirror-cursor {
+  visibility: visible;
+}
+
+.CodeMirror-selected { background: #d9d9d9; }
+.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
+
+.cm-searching {
+  background: #ffa;
+  background: rgba(255, 255, 0, .4);
+}
+
+/* IE7 hack to prevent it from returning funny offsetTops on the spans */
+.CodeMirror span { *vertical-align: text-bottom; }
+
+@media print {
+  /* Hide the cursor when printing */
+  .CodeMirror div.CodeMirror-cursor {
+    visibility: hidden;
+  }
+}
diff --git a/doc/asset/css/echartsHome.css b/doc/asset/css/echartsHome.css
new file mode 100644
index 0000000..f287e01
--- /dev/null
+++ b/doc/asset/css/echartsHome.css
@@ -0,0 +1,273 @@
+body {
+    padding-top: 60px;
+    padding-bottom: 40px;
+    color: #5a5a5a;
+    font-family: "微软雅黑";
+}
+
+.face {
+    background-color:#181818;
+}
+
+
+#forkme_banner {
+    display: block;
+    position: absolute;
+    top: 0;
+    right: 0;
+    z-index: 10;
+    padding: 10px 50px 10px 10px;
+    color: #fff;
+    background: url('../img/blacktocat.png') #0090ff no-repeat 95% 50%;
+    font-weight: 700;
+    box-shadow: 0 0 10px rgba(0,0,0,.5);
+    border-bottom-left-radius: 2px;
+    border-bottom-right-radius: 2px;
+}
+
+/* Carousel base class */
+.carousel {
+  margin: -20px 0 30px 0;
+}
+
+.carousel .container {
+  position: relative;
+  z-index: 9;
+}
+
+.carousel-control {
+  height: 80px;
+  margin-top: 0;
+  font-size: 120px;
+  text-shadow: 0 1px 1px rgba(0,0,0,.4);
+  background-color: transparent;
+  border: 0;
+  z-index: 10;
+}
+
+.carousel .item {
+  height: 300px;
+}
+.carousel img {
+  position: absolute;
+  top: 0;
+  left: 0;
+  min-width: 100%;
+  height: 300px;
+}
+
+.carousel-caption {
+  background-color: transparent;
+  position: static;
+  max-width: 540px;
+  padding: 0;
+  margin-top: 40px;
+}
+.carousel-caption h1,
+.carousel-caption .lead {
+  margin: 0;
+  line-height: 1.25;
+  color: #fff;
+  text-shadow: 0 1px 1px rgba(0,0,0,.4);
+}
+.carousel-caption .btn {
+  margin-top: 10px;
+}
+
+/* Featurettes
+------------------------- */
+.featurette-divider {
+  margin: 30px 0; /* Space out the Bootstrap <hr> more */
+}
+.featurette {
+  overflow: hidden; /* Vertically center images part 2: clear their floats. */
+}
+
+.navbar a.brand {
+    background:url('../ico/favicon.png') no-repeat 0 10px;
+    margin-left:0
+}
+.sidebar-nav {
+    padding: 9px 0;
+    margin-bottom: 0;
+}
+
+/* Give some space on the sides of the floated elements so text doesn't run right into it. */
+.featurette .pull-left {
+  margin:10px 40px 0 0;
+}
+.featurette .pull-right {
+  margin:10px 0 0 40px;
+}
+
+/* Thin out the marketing headings */
+.featurette-heading {
+  font-size: 50px;
+  font-weight: 300;
+  line-height: 1;
+  margin-bottom:30px;
+}
+
+.CodeMirror pre{color: #f8f8f2;}
+
+.span4.ani {
+    transition: width 1s;
+    -moz-transition: width 1s; /* Firefox 4 */
+    -webkit-transition: width 1s; /* Safari and Chrome */
+    -o-transition: width 1s; /* Opera */
+}
+.span8.ani {
+    transition: width 1s;
+    -moz-transition: width 1s; /* Firefox 4 */
+    -webkit-transition: width 1s; /* Safari and Chrome */
+    -o-transition: width 1s; /* Opera */
+}
+.main {
+    height: 400px;
+    overflow: hidden;
+    padding : 10px;
+    margin-bottom: 10px;
+    border: 1px solid #e3e3e3;
+    -webkit-border-radius: 4px;
+       -moz-border-radius: 4px;
+            border-radius: 4px;
+    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+       -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+            box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+
+a.accordion-toggle:hover {
+    text-decoration:none;
+    font-weight:bolder;
+}
+ul.nav-list {
+    overflow-y: auto;
+}
+.nav-list i.icon-plus, .nav-list i.icon-minus {
+    margin: 6px 0 0 -15px;
+    float: left;
+    cursor : pointer;
+    opacity: .3;
+}
+i.icon-chevron-right{
+    float: right;
+    margin-top: 2px;
+    margin-right: -6px;
+    opacity: .25;
+}
+.page-header {
+    padding-top:35px;
+    margin:0;
+    border-width:0;
+}
+.page-header h1 {
+    background-color:#eee;
+    padding:15px;
+    text-align:right;
+}
+div.section {
+    padding-top:30px;
+}
+tr.head {
+    background-color:#f5f5f5
+}
+
+/*doc*/
+.accordion-inner {
+    padding: 0 0 0 10px;
+}
+#toc,
+#config {
+    padding: 9px 0;
+    overflow-y : auto;
+}
+.tree ul,
+.tree li {
+    list-style: none;
+    font-size : 14px;
+    line-height : 20px;
+}
+.tree ul {
+    margin: 0;
+    padding: 0 0 0 2em;
+}
+
+.tree {
+    white-space: nowrap;
+}
+.tree strong {
+    color: purple;
+    font-weight: normal;
+}
+.tree li {
+    position: relative;
+}
+.tree strong:hover, #content .value:hover, #content .summary:hover {
+    background-color: silver;
+    -webkit-transition: all .5s ease-in;
+}
+.tree .operator {
+    position: absolute;
+    left: -1em;
+    top: 0;
+    display: none;
+    cursor: pointer;
+}
+.tree ul .operator {
+    display: block;
+}
+.tree ul .value,
+.tree ul .group,
+.tree ul .summary {
+    margin-left: .5em;
+}
+.tree .group {
+    display: inline;
+}
+.tree .summary {
+    display: none;
+    color: black;
+    font-weight: bold;
+}
+.tree .tree-close .group {
+    display: none;
+}
+.tree .tree-close .summary {
+    display: inline;
+}
+.tree .string {
+    color: maroon;
+}
+.tree .number {
+    color: blue;
+}
+.tree .boolean {
+    color: black;
+}
+#doc h3 a,#doc h4 a,#doc h5 a{
+    display:inline-block;
+    padding-top:80px;
+}
+table.full {width:100%;}
+.ADoc_table { border-collapse: collapse; margin-bottom:15px; }
+
+.ADoc_table th, .ADoc_table td {
+    border:1px solid rgb(23,53,81);
+    padding: 3px;
+    background:#fff;
+    color:#222;
+}
+
+.ADoc_table th {
+    border-bottom:2px solid rgb(23,53,81);
+    background:rgb(37,78,117);
+    color:#fff;
+}
+
+#icon-resize {
+    float:right;
+    opacity:.3;
+}
+a#icon-resize:hover {
+    opacity:.6;
+}
diff --git a/doc/asset/css/monokai.css b/doc/asset/css/monokai.css
new file mode 100644
index 0000000..11f926b
--- /dev/null
+++ b/doc/asset/css/monokai.css
@@ -0,0 +1,28 @@
+/* Based on Sublime Text's Monokai theme */
+
+.cm-s-monokai.CodeMirror {background: #272822; color: #f8f8f2;}
+.cm-s-monokai div.CodeMirror-selected {background: #49483E !important;}
+.cm-s-monokai .CodeMirror-gutters {/*background: #272822; */border-right: 0px;}
+.cm-s-monokai .CodeMirror-linenumber {/*color: #d0d0d0;*/color: green}
+.cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}
+
+.cm-s-monokai span.cm-comment {color: #75715e;}
+.cm-s-monokai span.cm-atom {color: #ae81ff;}
+.cm-s-monokai span.cm-number {color: #ae81ff;}
+
+.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;}
+.cm-s-monokai span.cm-keyword {color: #f92672;}
+.cm-s-monokai span.cm-string {color: #e6db74;}
+
+.cm-s-monokai span.cm-variable {color: #a6e22e;}
+.cm-s-monokai span.cm-variable-2 {color: #9effff;}
+.cm-s-monokai span.cm-def {color: #fd971f;}
+.cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;}
+.cm-s-monokai span.cm-bracket {color: #f8f8f2;}
+.cm-s-monokai span.cm-tag {color: #f92672;}
+.cm-s-monokai span.cm-link {color: #ae81ff;}
+
+.cm-s-monokai .CodeMirror-matchingbracket {
+  text-decoration: underline;
+  color: white !important;
+}
diff --git a/doc/asset/ico/favicon.png b/doc/asset/ico/favicon.png
new file mode 100644
index 0000000..2ec057f
--- /dev/null
+++ b/doc/asset/ico/favicon.png
Binary files differ
diff --git a/doc/asset/img/architecture.png b/doc/asset/img/architecture.png
new file mode 100644
index 0000000..d65e1f1
--- /dev/null
+++ b/doc/asset/img/architecture.png
Binary files differ
diff --git a/doc/asset/img/blacktocat.png b/doc/asset/img/blacktocat.png
new file mode 100644
index 0000000..6e264fe
--- /dev/null
+++ b/doc/asset/img/blacktocat.png
Binary files differ
diff --git a/doc/asset/img/custom.png b/doc/asset/img/custom.png
new file mode 100644
index 0000000..f217cec
--- /dev/null
+++ b/doc/asset/img/custom.png
Binary files differ
diff --git a/doc/asset/img/dataView.gif b/doc/asset/img/dataView.gif
new file mode 100644
index 0000000..a7fcc39
--- /dev/null
+++ b/doc/asset/img/dataView.gif
Binary files differ
diff --git a/doc/asset/img/datazoom.gif b/doc/asset/img/datazoom.gif
new file mode 100644
index 0000000..895a7fb
--- /dev/null
+++ b/doc/asset/img/datazoom.gif
Binary files differ
diff --git a/doc/asset/img/device.png b/doc/asset/img/device.png
new file mode 100644
index 0000000..0628534
--- /dev/null
+++ b/doc/asset/img/device.png
Binary files differ
diff --git a/doc/asset/img/doc/axisBoundaryGap.png b/doc/asset/img/doc/axisBoundaryGap.png
new file mode 100644
index 0000000..1034e5e
--- /dev/null
+++ b/doc/asset/img/doc/axisBoundaryGap.png
Binary files differ
diff --git a/doc/asset/img/doc/axisBoundaryGap1.jpg b/doc/asset/img/doc/axisBoundaryGap1.jpg
new file mode 100644
index 0000000..00eda49
--- /dev/null
+++ b/doc/asset/img/doc/axisBoundaryGap1.jpg
Binary files differ
diff --git a/doc/asset/img/doc/axisDetail.jpg b/doc/asset/img/doc/axisDetail.jpg
new file mode 100644
index 0000000..540b6ce
--- /dev/null
+++ b/doc/asset/img/doc/axisDetail.jpg
Binary files differ
diff --git a/doc/asset/img/doc/axisDetail.png b/doc/asset/img/doc/axisDetail.png
new file mode 100644
index 0000000..436cf09
--- /dev/null
+++ b/doc/asset/img/doc/axisDetail.png
Binary files differ
diff --git a/doc/asset/img/doc/charts.jpg b/doc/asset/img/doc/charts.jpg
new file mode 100644
index 0000000..71d7514
--- /dev/null
+++ b/doc/asset/img/doc/charts.jpg
Binary files differ
diff --git a/doc/asset/img/doc/grid.jpg b/doc/asset/img/doc/grid.jpg
new file mode 100644
index 0000000..49f0b60
--- /dev/null
+++ b/doc/asset/img/doc/grid.jpg
Binary files differ
diff --git a/doc/asset/img/doc/legend.png b/doc/asset/img/doc/legend.png
new file mode 100644
index 0000000..0efde33
--- /dev/null
+++ b/doc/asset/img/doc/legend.png
Binary files differ
diff --git a/doc/asset/img/doc/multiControl.jpg b/doc/asset/img/doc/multiControl.jpg
new file mode 100644
index 0000000..b2ad874
--- /dev/null
+++ b/doc/asset/img/doc/multiControl.jpg
Binary files differ
diff --git a/doc/asset/img/doc/toolbox.png b/doc/asset/img/doc/toolbox.png
new file mode 100644
index 0000000..d01588d
--- /dev/null
+++ b/doc/asset/img/doc/toolbox.png
Binary files differ
diff --git a/doc/asset/img/doc/tooltip1.jpg b/doc/asset/img/doc/tooltip1.jpg
new file mode 100644
index 0000000..ca13238
--- /dev/null
+++ b/doc/asset/img/doc/tooltip1.jpg
Binary files differ
diff --git a/doc/asset/img/doc/tooltip2.jpg b/doc/asset/img/doc/tooltip2.jpg
new file mode 100644
index 0000000..41aad9a
--- /dev/null
+++ b/doc/asset/img/doc/tooltip2.jpg
Binary files differ
diff --git a/doc/asset/img/draggable.gif b/doc/asset/img/draggable.gif
new file mode 100644
index 0000000..db43f15
--- /dev/null
+++ b/doc/asset/img/draggable.gif
Binary files differ
diff --git a/doc/asset/img/example/axis.png b/doc/asset/img/example/axis.png
new file mode 100644
index 0000000..b4c0ca0
--- /dev/null
+++ b/doc/asset/img/example/axis.png
Binary files differ
diff --git a/doc/asset/img/example/bar.png b/doc/asset/img/example/bar.png
new file mode 100644
index 0000000..2ade7ee
--- /dev/null
+++ b/doc/asset/img/example/bar.png
Binary files differ
diff --git a/doc/asset/img/example/bar1.png b/doc/asset/img/example/bar1.png
new file mode 100644
index 0000000..910ed05
--- /dev/null
+++ b/doc/asset/img/example/bar1.png
Binary files differ
diff --git a/doc/asset/img/example/bar2.png b/doc/asset/img/example/bar2.png
new file mode 100644
index 0000000..e50cbb3
--- /dev/null
+++ b/doc/asset/img/example/bar2.png
Binary files differ
diff --git a/doc/asset/img/example/bar3.png b/doc/asset/img/example/bar3.png
new file mode 100644
index 0000000..0bbe574
--- /dev/null
+++ b/doc/asset/img/example/bar3.png
Binary files differ
diff --git a/doc/asset/img/example/bar4.png b/doc/asset/img/example/bar4.png
new file mode 100644
index 0000000..d4f52e9
--- /dev/null
+++ b/doc/asset/img/example/bar4.png
Binary files differ
diff --git a/doc/asset/img/example/bar5.png b/doc/asset/img/example/bar5.png
new file mode 100644
index 0000000..a7a8a81
--- /dev/null
+++ b/doc/asset/img/example/bar5.png
Binary files differ
diff --git a/doc/asset/img/example/datazoom.png b/doc/asset/img/example/datazoom.png
new file mode 100644
index 0000000..5ed1fc7
--- /dev/null
+++ b/doc/asset/img/example/datazoom.png
Binary files differ
diff --git a/doc/asset/img/example/datazoom1.png b/doc/asset/img/example/datazoom1.png
new file mode 100644
index 0000000..dac451c
--- /dev/null
+++ b/doc/asset/img/example/datazoom1.png
Binary files differ
diff --git a/doc/asset/img/example/lasagna.png b/doc/asset/img/example/lasagna.png
new file mode 100644
index 0000000..b71c327
--- /dev/null
+++ b/doc/asset/img/example/lasagna.png
Binary files differ
diff --git a/doc/asset/img/example/line.png b/doc/asset/img/example/line.png
new file mode 100644
index 0000000..4570ed0
--- /dev/null
+++ b/doc/asset/img/example/line.png
Binary files differ
diff --git a/doc/asset/img/example/line1.png b/doc/asset/img/example/line1.png
new file mode 100644
index 0000000..110a7aa
--- /dev/null
+++ b/doc/asset/img/example/line1.png
Binary files differ
diff --git a/doc/asset/img/example/line2.png b/doc/asset/img/example/line2.png
new file mode 100644
index 0000000..263b10d
--- /dev/null
+++ b/doc/asset/img/example/line2.png
Binary files differ
diff --git a/doc/asset/img/example/line3.png b/doc/asset/img/example/line3.png
new file mode 100644
index 0000000..6a67346
--- /dev/null
+++ b/doc/asset/img/example/line3.png
Binary files differ
diff --git a/doc/asset/img/example/line4.png b/doc/asset/img/example/line4.png
new file mode 100644
index 0000000..c9e3919
--- /dev/null
+++ b/doc/asset/img/example/line4.png
Binary files differ
diff --git a/doc/asset/img/example/line5.png b/doc/asset/img/example/line5.png
new file mode 100644
index 0000000..09f1350
--- /dev/null
+++ b/doc/asset/img/example/line5.png
Binary files differ
diff --git a/doc/asset/img/example/loading.png b/doc/asset/img/example/loading.png
new file mode 100644
index 0000000..1e8311c
--- /dev/null
+++ b/doc/asset/img/example/loading.png
Binary files differ
diff --git a/doc/asset/img/example/mix1.png b/doc/asset/img/example/mix1.png
new file mode 100644
index 0000000..84d642e
--- /dev/null
+++ b/doc/asset/img/example/mix1.png
Binary files differ
diff --git a/doc/asset/img/example/mix2.png b/doc/asset/img/example/mix2.png
new file mode 100644
index 0000000..cd4d123
--- /dev/null
+++ b/doc/asset/img/example/mix2.png
Binary files differ
diff --git a/doc/asset/img/example/pie.png b/doc/asset/img/example/pie.png
new file mode 100644
index 0000000..d945e73
--- /dev/null
+++ b/doc/asset/img/example/pie.png
Binary files differ
diff --git a/doc/asset/img/example/pie1.png b/doc/asset/img/example/pie1.png
new file mode 100644
index 0000000..c285b08
--- /dev/null
+++ b/doc/asset/img/example/pie1.png
Binary files differ
diff --git a/doc/asset/img/example/pie2.png b/doc/asset/img/example/pie2.png
new file mode 100644
index 0000000..8e1698f
--- /dev/null
+++ b/doc/asset/img/example/pie2.png
Binary files differ
diff --git a/doc/asset/img/example/pie3.png b/doc/asset/img/example/pie3.png
new file mode 100644
index 0000000..e4b84a3
--- /dev/null
+++ b/doc/asset/img/example/pie3.png
Binary files differ
diff --git a/doc/asset/img/example/radar1.jpg b/doc/asset/img/example/radar1.jpg
new file mode 100644
index 0000000..2a5c828
--- /dev/null
+++ b/doc/asset/img/example/radar1.jpg
Binary files differ
diff --git a/doc/asset/img/example/radar2.jpg b/doc/asset/img/example/radar2.jpg
new file mode 100644
index 0000000..7697f04
--- /dev/null
+++ b/doc/asset/img/example/radar2.jpg
Binary files differ
diff --git a/doc/asset/img/example/scatter1.jpg b/doc/asset/img/example/scatter1.jpg
new file mode 100644
index 0000000..1e9c8ac
--- /dev/null
+++ b/doc/asset/img/example/scatter1.jpg
Binary files differ
diff --git a/doc/asset/img/example/scatter2.jpg b/doc/asset/img/example/scatter2.jpg
new file mode 100644
index 0000000..b17538a
--- /dev/null
+++ b/doc/asset/img/example/scatter2.jpg
Binary files differ
diff --git a/doc/asset/img/example/tooltip.png b/doc/asset/img/example/tooltip.png
new file mode 100644
index 0000000..fff8e6d
--- /dev/null
+++ b/doc/asset/img/example/tooltip.png
Binary files differ
diff --git a/doc/asset/img/explorer.png b/doc/asset/img/explorer.png
new file mode 100644
index 0000000..93d6f47
--- /dev/null
+++ b/doc/asset/img/explorer.png
Binary files differ
diff --git a/doc/asset/img/glyphicons-halflings-white.png b/doc/asset/img/glyphicons-halflings-white.png
new file mode 100644
index 0000000..3bf6484
--- /dev/null
+++ b/doc/asset/img/glyphicons-halflings-white.png
Binary files differ
diff --git a/doc/asset/img/glyphicons-halflings.png b/doc/asset/img/glyphicons-halflings.png
new file mode 100644
index 0000000..a996999
--- /dev/null
+++ b/doc/asset/img/glyphicons-halflings.png
Binary files differ
diff --git a/doc/asset/img/legendSelected.gif b/doc/asset/img/legendSelected.gif
new file mode 100644
index 0000000..5840d7d
--- /dev/null
+++ b/doc/asset/img/legendSelected.gif
Binary files differ
diff --git a/doc/asset/img/magicType.gif b/doc/asset/img/magicType.gif
new file mode 100644
index 0000000..100c224
--- /dev/null
+++ b/doc/asset/img/magicType.gif
Binary files differ
diff --git a/doc/asset/img/mark.gif b/doc/asset/img/mark.gif
new file mode 100644
index 0000000..daa9243
--- /dev/null
+++ b/doc/asset/img/mark.gif
Binary files differ
diff --git a/doc/asset/img/mix.jpg b/doc/asset/img/mix.jpg
new file mode 100644
index 0000000..28f7790
--- /dev/null
+++ b/doc/asset/img/mix.jpg
Binary files differ
diff --git a/doc/asset/img/multiStack.png b/doc/asset/img/multiStack.png
new file mode 100644
index 0000000..dd30927
--- /dev/null
+++ b/doc/asset/img/multiStack.png
Binary files differ
diff --git a/doc/asset/img/slide-01.png b/doc/asset/img/slide-01.png
new file mode 100644
index 0000000..abfb3b3
--- /dev/null
+++ b/doc/asset/img/slide-01.png
Binary files differ
diff --git a/doc/asset/img/slide-02.png b/doc/asset/img/slide-02.png
new file mode 100644
index 0000000..5335470
--- /dev/null
+++ b/doc/asset/img/slide-02.png
Binary files differ
diff --git a/doc/asset/img/slide-03.png b/doc/asset/img/slide-03.png
new file mode 100644
index 0000000..475bce0
--- /dev/null
+++ b/doc/asset/img/slide-03.png
Binary files differ
diff --git a/doc/asset/img/zrender.png b/doc/asset/img/zrender.png
new file mode 100644
index 0000000..0c30151
--- /dev/null
+++ b/doc/asset/img/zrender.png
Binary files differ
diff --git a/doc/asset/js/application.js b/doc/asset/js/application.js
new file mode 100644
index 0000000..f880bc0
--- /dev/null
+++ b/doc/asset/js/application.js
@@ -0,0 +1,156 @@
+// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT
+// IT'S ALL JUST JUNK FOR OUR DOCS!
+// ++++++++++++++++++++++++++++++++++++++++++
+
+!function ($) {
+
+  $(function(){
+
+    var $window = $(window)
+
+    // Disable certain links in docs
+    $('section [href^=#]').click(function (e) {
+      e.preventDefault()
+    })
+
+    // side bar
+    setTimeout(function () {
+      $('.bs-docs-sidenav').affix({
+        offset: {
+          top: function () { return $window.width() <= 980 ? 290 : 210 }
+        , bottom: 270
+        }
+      })
+    }, 100)
+
+    // make code pretty
+    window.prettyPrint && prettyPrint()
+
+    // add-ons
+    $('.add-on :checkbox').on('click', function () {
+      var $this = $(this)
+        , method = $this.attr('checked') ? 'addClass' : 'removeClass'
+      $(this).parents('.add-on')[method]('active')
+    })
+
+    // add tipsies to grid for scaffolding
+    if ($('#gridSystem').length) {
+      $('#gridSystem').tooltip({
+          selector: '.show-grid > [class*="span"]'
+        , title: function () { return $(this).width() + 'px' }
+      })
+    }
+
+    // tooltip demo
+    $('.tooltip-demo').tooltip({
+      selector: "a[data-toggle=tooltip]"
+    })
+
+    $('.tooltip-test').tooltip()
+    $('.popover-test').popover()
+
+    // popover demo
+    $("a[data-toggle=popover]")
+      .popover()
+      .click(function(e) {
+        e.preventDefault()
+      })
+
+    // button state demo
+    $('#fat-btn')
+      .click(function () {
+        var btn = $(this)
+        btn.button('loading')
+        setTimeout(function () {
+          btn.button('reset')
+        }, 3000)
+      })
+
+    // carousel demo
+    $('#myCarousel').carousel()
+
+    // javascript build logic
+    var inputsComponent = $("#components.download input")
+      , inputsPlugin = $("#plugins.download input")
+      , inputsVariables = $("#variables.download input")
+
+    // toggle all plugin checkboxes
+    $('#components.download .toggle-all').on('click', function (e) {
+      e.preventDefault()
+      inputsComponent.attr('checked', !inputsComponent.is(':checked'))
+    })
+
+    $('#plugins.download .toggle-all').on('click', function (e) {
+      e.preventDefault()
+      inputsPlugin.attr('checked', !inputsPlugin.is(':checked'))
+    })
+
+    $('#variables.download .toggle-all').on('click', function (e) {
+      e.preventDefault()
+      inputsVariables.val('')
+    })
+
+    // request built javascript
+    $('.download-btn .btn').on('click', function () {
+
+      var css = $("#components.download input:checked")
+            .map(function () { return this.value })
+            .toArray()
+        , js = $("#plugins.download input:checked")
+            .map(function () { return this.value })
+            .toArray()
+        , vars = {}
+        , img = ['glyphicons-halflings.png', 'glyphicons-halflings-white.png']
+
+    $("#variables.download input")
+      .each(function () {
+        $(this).val() && (vars[ $(this).prev().text() ] = $(this).val())
+      })
+
+      $.ajax({
+        type: 'POST'
+      , url: /\?dev/.test(window.location) ? 'http://localhost:3000' : 'http://bootstrap.herokuapp.com'
+      , dataType: 'jsonpi'
+      , params: {
+          js: js
+        , css: css
+        , vars: vars
+        , img: img
+      }
+      })
+    })
+  })
+
+// Modified from the original jsonpi https://github.com/benvinegar/jquery-jsonpi
+$.ajaxTransport('jsonpi', function(opts, originalOptions, jqXHR) {
+  var url = opts.url;
+
+  return {
+    send: function(_, completeCallback) {
+      var name = 'jQuery_iframe_' + jQuery.now()
+        , iframe, form
+
+      iframe = $('<iframe>')
+        .attr('name', name)
+        .appendTo('head')
+
+      form = $('<form>')
+        .attr('method', opts.type) // GET or POST
+        .attr('action', url)
+        .attr('target', name)
+
+      $.each(opts.params, function(k, v) {
+
+        $('<input>')
+          .attr('type', 'hidden')
+          .attr('name', k)
+          .attr('value', typeof v == 'string' ? v : JSON.stringify(v))
+          .appendTo(form)
+      })
+
+      form.appendTo('body').submit()
+    }
+  }
+})
+
+}(window.jQuery)
diff --git a/doc/asset/js/bootstrap-affix.js b/doc/asset/js/bootstrap-affix.js
new file mode 100644
index 0000000..827ff45
--- /dev/null
+++ b/doc/asset/js/bootstrap-affix.js
@@ -0,0 +1,117 @@
+/* ==========================================================
+ * bootstrap-affix.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#affix
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* AFFIX CLASS DEFINITION
+  * ====================== */
+
+  var Affix = function (element, options) {
+    this.options = $.extend({}, $.fn.affix.defaults, options)
+    this.$window = $(window)
+      .on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
+      .on('click.affix.data-api',  $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this))
+    this.$element = $(element)
+    this.checkPosition()
+  }
+
+  Affix.prototype.checkPosition = function () {
+    if (!this.$element.is(':visible')) return
+
+    var scrollHeight = $(document).height()
+      , scrollTop = this.$window.scrollTop()
+      , position = this.$element.offset()
+      , offset = this.options.offset
+      , offsetBottom = offset.bottom
+      , offsetTop = offset.top
+      , reset = 'affix affix-top affix-bottom'
+      , affix
+
+    if (typeof offset != 'object') offsetBottom = offsetTop = offset
+    if (typeof offsetTop == 'function') offsetTop = offset.top()
+    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
+
+    affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
+      false    : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
+      'bottom' : offsetTop != null && scrollTop <= offsetTop ?
+      'top'    : false
+
+    if (this.affixed === affix) return
+
+    this.affixed = affix
+    this.unpin = affix == 'bottom' ? position.top - scrollTop : null
+
+    this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
+  }
+
+
+ /* AFFIX PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.affix
+
+  $.fn.affix = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('affix')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('affix', (data = new Affix(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.affix.Constructor = Affix
+
+  $.fn.affix.defaults = {
+    offset: 0
+  }
+
+
+ /* AFFIX NO CONFLICT
+  * ================= */
+
+  $.fn.affix.noConflict = function () {
+    $.fn.affix = old
+    return this
+  }
+
+
+ /* AFFIX DATA-API
+  * ============== */
+
+  $(window).on('load', function () {
+    $('[data-spy="affix"]').each(function () {
+      var $spy = $(this)
+        , data = $spy.data()
+
+      data.offset = data.offset || {}
+
+      data.offsetBottom && (data.offset.bottom = data.offsetBottom)
+      data.offsetTop && (data.offset.top = data.offsetTop)
+
+      $spy.affix(data)
+    })
+  })
+
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/doc/asset/js/bootstrap-alert.js b/doc/asset/js/bootstrap-alert.js
new file mode 100644
index 0000000..8917f94
--- /dev/null
+++ b/doc/asset/js/bootstrap-alert.js
@@ -0,0 +1,99 @@
+/* ==========================================================
+ * bootstrap-alert.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* ALERT CLASS DEFINITION
+  * ====================== */
+
+  var dismiss = '[data-dismiss="alert"]'
+    , Alert = function (el) {
+        $(el).on('click', dismiss, this.close)
+      }
+
+  Alert.prototype.close = function (e) {
+    var $this = $(this)
+      , selector = $this.attr('data-target')
+      , $parent
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+    }
+
+    $parent = $(selector)
+
+    e && e.preventDefault()
+
+    $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
+
+    $parent.trigger(e = $.Event('close'))
+
+    if (e.isDefaultPrevented()) return
+
+    $parent.removeClass('in')
+
+    function removeElement() {
+      $parent
+        .trigger('closed')
+        .remove()
+    }
+
+    $.support.transition && $parent.hasClass('fade') ?
+      $parent.on($.support.transition.end, removeElement) :
+      removeElement()
+  }
+
+
+ /* ALERT PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.alert
+
+  $.fn.alert = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('alert')
+      if (!data) $this.data('alert', (data = new Alert(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  $.fn.alert.Constructor = Alert
+
+
+ /* ALERT NO CONFLICT
+  * ================= */
+
+  $.fn.alert.noConflict = function () {
+    $.fn.alert = old
+    return this
+  }
+
+
+ /* ALERT DATA-API
+  * ============== */
+
+  $(document).on('click.alert.data-api', dismiss, Alert.prototype.close)
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/doc/asset/js/bootstrap-button.js b/doc/asset/js/bootstrap-button.js
new file mode 100644
index 0000000..66df0a2
--- /dev/null
+++ b/doc/asset/js/bootstrap-button.js
@@ -0,0 +1,105 @@
+/* ============================================================
+ * bootstrap-button.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+  * ============================== */
+
+  var Button = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.button.defaults, options)
+  }
+
+  Button.prototype.setState = function (state) {
+    var d = 'disabled'
+      , $el = this.$element
+      , data = $el.data()
+      , val = $el.is('input') ? 'val' : 'html'
+
+    state = state + 'Text'
+    data.resetText || $el.data('resetText', $el[val]())
+
+    $el[val](data[state] || this.options[state])
+
+    // push to event loop to allow forms to submit
+    setTimeout(function () {
+      state == 'loadingText' ?
+        $el.addClass(d).attr(d, d) :
+        $el.removeClass(d).removeAttr(d)
+    }, 0)
+  }
+
+  Button.prototype.toggle = function () {
+    var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
+
+    $parent && $parent
+      .find('.active')
+      .removeClass('active')
+
+    this.$element.toggleClass('active')
+  }
+
+
+ /* BUTTON PLUGIN DEFINITION
+  * ======================== */
+
+  var old = $.fn.button
+
+  $.fn.button = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('button')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('button', (data = new Button(this, options)))
+      if (option == 'toggle') data.toggle()
+      else if (option) data.setState(option)
+    })
+  }
+
+  $.fn.button.defaults = {
+    loadingText: 'loading...'
+  }
+
+  $.fn.button.Constructor = Button
+
+
+ /* BUTTON NO CONFLICT
+  * ================== */
+
+  $.fn.button.noConflict = function () {
+    $.fn.button = old
+    return this
+  }
+
+
+ /* BUTTON DATA-API
+  * =============== */
+
+  $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
+    var $btn = $(e.target)
+    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+    $btn.button('toggle')
+  })
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/doc/asset/js/bootstrap-carousel.js b/doc/asset/js/bootstrap-carousel.js
new file mode 100644
index 0000000..b40edd7
--- /dev/null
+++ b/doc/asset/js/bootstrap-carousel.js
@@ -0,0 +1,207 @@
+/* ==========================================================
+ * bootstrap-carousel.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* CAROUSEL CLASS DEFINITION
+  * ========================= */
+
+  var Carousel = function (element, options) {
+    this.$element = $(element)
+    this.$indicators = this.$element.find('.carousel-indicators')
+    this.options = options
+    this.options.pause == 'hover' && this.$element
+      .on('mouseenter', $.proxy(this.pause, this))
+      .on('mouseleave', $.proxy(this.cycle, this))
+  }
+
+  Carousel.prototype = {
+
+    cycle: function (e) {
+      if (!e) this.paused = false
+      if (this.interval) clearInterval(this.interval);
+      this.options.interval
+        && !this.paused
+        && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+      return this
+    }
+
+  , getActiveIndex: function () {
+      this.$active = this.$element.find('.item.active')
+      this.$items = this.$active.parent().children()
+      return this.$items.index(this.$active)
+    }
+
+  , to: function (pos) {
+      var activeIndex = this.getActiveIndex()
+        , that = this
+
+      if (pos > (this.$items.length - 1) || pos < 0) return
+
+      if (this.sliding) {
+        return this.$element.one('slid', function () {
+          that.to(pos)
+        })
+      }
+
+      if (activeIndex == pos) {
+        return this.pause().cycle()
+      }
+
+      return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
+    }
+
+  , pause: function (e) {
+      if (!e) this.paused = true
+      if (this.$element.find('.next, .prev').length && $.support.transition.end) {
+        this.$element.trigger($.support.transition.end)
+        this.cycle(true)
+      }
+      clearInterval(this.interval)
+      this.interval = null
+      return this
+    }
+
+  , next: function () {
+      if (this.sliding) return
+      return this.slide('next')
+    }
+
+  , prev: function () {
+      if (this.sliding) return
+      return this.slide('prev')
+    }
+
+  , slide: function (type, next) {
+      var $active = this.$element.find('.item.active')
+        , $next = next || $active[type]()
+        , isCycling = this.interval
+        , direction = type == 'next' ? 'left' : 'right'
+        , fallback  = type == 'next' ? 'first' : 'last'
+        , that = this
+        , e
+
+      this.sliding = true
+
+      isCycling && this.pause()
+
+      $next = $next.length ? $next : this.$element.find('.item')[fallback]()
+
+      e = $.Event('slide', {
+        relatedTarget: $next[0]
+      , direction: direction
+      })
+
+      if ($next.hasClass('active')) return
+
+      if (this.$indicators.length) {
+        this.$indicators.find('.active').removeClass('active')
+        this.$element.one('slid', function () {
+          var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
+          $nextIndicator && $nextIndicator.addClass('active')
+        })
+      }
+
+      if ($.support.transition && this.$element.hasClass('slide')) {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $next.addClass(type)
+        $next[0].offsetWidth // force reflow
+        $active.addClass(direction)
+        $next.addClass(direction)
+        this.$element.one($.support.transition.end, function () {
+          $next.removeClass([type, direction].join(' ')).addClass('active')
+          $active.removeClass(['active', direction].join(' '))
+          that.sliding = false
+          setTimeout(function () { that.$element.trigger('slid') }, 0)
+        })
+      } else {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $active.removeClass('active')
+        $next.addClass('active')
+        this.sliding = false
+        this.$element.trigger('slid')
+      }
+
+      isCycling && this.cycle()
+
+      return this
+    }
+
+  }
+
+
+ /* CAROUSEL PLUGIN DEFINITION
+  * ========================== */
+
+  var old = $.fn.carousel
+
+  $.fn.carousel = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('carousel')
+        , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
+        , action = typeof option == 'string' ? option : options.slide
+      if (!data) $this.data('carousel', (data = new Carousel(this, options)))
+      if (typeof option == 'number') data.to(option)
+      else if (action) data[action]()
+      else if (options.interval) data.pause().cycle()
+    })
+  }
+
+  $.fn.carousel.defaults = {
+    interval: 5000
+  , pause: 'hover'
+  }
+
+  $.fn.carousel.Constructor = Carousel
+
+
+ /* CAROUSEL NO CONFLICT
+  * ==================== */
+
+  $.fn.carousel.noConflict = function () {
+    $.fn.carousel = old
+    return this
+  }
+
+ /* CAROUSEL DATA-API
+  * ================= */
+
+  $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
+    var $this = $(this), href
+      , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+      , options = $.extend({}, $target.data(), $this.data())
+      , slideIndex
+
+    $target.carousel(options)
+
+    if (slideIndex = $this.attr('data-slide-to')) {
+      $target.data('carousel').pause().to(slideIndex).cycle()
+    }
+
+    e.preventDefault()
+  })
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/doc/asset/js/bootstrap-collapse.js b/doc/asset/js/bootstrap-collapse.js
new file mode 100644
index 0000000..2bede4a
--- /dev/null
+++ b/doc/asset/js/bootstrap-collapse.js
@@ -0,0 +1,167 @@
+/* =============================================================
+ * bootstrap-collapse.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* COLLAPSE PUBLIC CLASS DEFINITION
+  * ================================ */
+
+  var Collapse = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.collapse.defaults, options)
+
+    if (this.options.parent) {
+      this.$parent = $(this.options.parent)
+    }
+
+    this.options.toggle && this.toggle()
+  }
+
+  Collapse.prototype = {
+
+    constructor: Collapse
+
+  , dimension: function () {
+      var hasWidth = this.$element.hasClass('width')
+      return hasWidth ? 'width' : 'height'
+    }
+
+  , show: function () {
+      var dimension
+        , scroll
+        , actives
+        , hasData
+
+      if (this.transitioning || this.$element.hasClass('in')) return
+
+      dimension = this.dimension()
+      scroll = $.camelCase(['scroll', dimension].join('-'))
+      actives = this.$parent && this.$parent.find('> .accordion-group > .in')
+
+      if (actives && actives.length) {
+        hasData = actives.data('collapse')
+        if (hasData && hasData.transitioning) return
+        actives.collapse('hide')
+        hasData || actives.data('collapse', null)
+      }
+
+      this.$element[dimension](0)
+      this.transition('addClass', $.Event('show'), 'shown')
+      $.support.transition && this.$element[dimension](this.$element[0][scroll])
+    }
+
+  , hide: function () {
+      var dimension
+      if (this.transitioning || !this.$element.hasClass('in')) return
+      dimension = this.dimension()
+      this.reset(this.$element[dimension]())
+      this.transition('removeClass', $.Event('hide'), 'hidden')
+      this.$element[dimension](0)
+    }
+
+  , reset: function (size) {
+      var dimension = this.dimension()
+
+      this.$element
+        .removeClass('collapse')
+        [dimension](size || 'auto')
+        [0].offsetWidth
+
+      this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
+
+      return this
+    }
+
+  , transition: function (method, startEvent, completeEvent) {
+      var that = this
+        , complete = function () {
+            if (startEvent.type == 'show') that.reset()
+            that.transitioning = 0
+            that.$element.trigger(completeEvent)
+          }
+
+      this.$element.trigger(startEvent)
+
+      if (startEvent.isDefaultPrevented()) return
+
+      this.transitioning = 1
+
+      this.$element[method]('in')
+
+      $.support.transition && this.$element.hasClass('collapse') ?
+        this.$element.one($.support.transition.end, complete) :
+        complete()
+    }
+
+  , toggle: function () {
+      this[this.$element.hasClass('in') ? 'hide' : 'show']()
+    }
+
+  }
+
+
+ /* COLLAPSE PLUGIN DEFINITION
+  * ========================== */
+
+  var old = $.fn.collapse
+
+  $.fn.collapse = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('collapse')
+        , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option)
+      if (!data) $this.data('collapse', (data = new Collapse(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.collapse.defaults = {
+    toggle: true
+  }
+
+  $.fn.collapse.Constructor = Collapse
+
+
+ /* COLLAPSE NO CONFLICT
+  * ==================== */
+
+  $.fn.collapse.noConflict = function () {
+    $.fn.collapse = old
+    return this
+  }
+
+
+ /* COLLAPSE DATA-API
+  * ================= */
+
+  $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
+    var $this = $(this), href
+      , target = $this.attr('data-target')
+        || e.preventDefault()
+        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
+      , option = $(target).data('collapse') ? 'toggle' : $this.data()
+    $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
+    $(target).collapse(option)
+  })
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/doc/asset/js/bootstrap-dropdown.js b/doc/asset/js/bootstrap-dropdown.js
new file mode 100644
index 0000000..a1d5151
--- /dev/null
+++ b/doc/asset/js/bootstrap-dropdown.js
@@ -0,0 +1,165 @@
+/* ============================================================
+ * bootstrap-dropdown.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* DROPDOWN CLASS DEFINITION
+  * ========================= */
+
+  var toggle = '[data-toggle=dropdown]'
+    , Dropdown = function (element) {
+        var $el = $(element).on('click.dropdown.data-api', this.toggle)
+        $('html').on('click.dropdown.data-api', function () {
+          $el.parent().removeClass('open')
+        })
+      }
+
+  Dropdown.prototype = {
+
+    constructor: Dropdown
+
+  , toggle: function (e) {
+      var $this = $(this)
+        , $parent
+        , isActive
+
+      if ($this.is('.disabled, :disabled')) return
+
+      $parent = getParent($this)
+
+      isActive = $parent.hasClass('open')
+
+      clearMenus()
+
+      if (!isActive) {
+        $parent.toggleClass('open')
+      }
+
+      $this.focus()
+
+      return false
+    }
+
+  , keydown: function (e) {
+      var $this
+        , $items
+        , $active
+        , $parent
+        , isActive
+        , index
+
+      if (!/(38|40|27)/.test(e.keyCode)) return
+
+      $this = $(this)
+
+      e.preventDefault()
+      e.stopPropagation()
+
+      if ($this.is('.disabled, :disabled')) return
+
+      $parent = getParent($this)
+
+      isActive = $parent.hasClass('open')
+
+      if (!isActive || (isActive && e.keyCode == 27)) {
+        if (e.which == 27) $parent.find(toggle).focus()
+        return $this.click()
+      }
+
+      $items = $('[role=menu] li:not(.divider):visible a', $parent)
+
+      if (!$items.length) return
+
+      index = $items.index($items.filter(':focus'))
+
+      if (e.keyCode == 38 && index > 0) index--                                        // up
+      if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
+      if (!~index) index = 0
+
+      $items
+        .eq(index)
+        .focus()
+    }
+
+  }
+
+  function clearMenus() {
+    $(toggle).each(function () {
+      getParent($(this)).removeClass('open')
+    })
+  }
+
+  function getParent($this) {
+    var selector = $this.attr('data-target')
+      , $parent
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+    }
+
+    $parent = selector && $(selector)
+
+    if (!$parent || !$parent.length) $parent = $this.parent()
+
+    return $parent
+  }
+
+
+  /* DROPDOWN PLUGIN DEFINITION
+   * ========================== */
+
+  var old = $.fn.dropdown
+
+  $.fn.dropdown = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('dropdown')
+      if (!data) $this.data('dropdown', (data = new Dropdown(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  $.fn.dropdown.Constructor = Dropdown
+
+
+ /* DROPDOWN NO CONFLICT
+  * ==================== */
+
+  $.fn.dropdown.noConflict = function () {
+    $.fn.dropdown = old
+    return this
+  }
+
+
+  /* APPLY TO STANDARD DROPDOWN ELEMENTS
+   * =================================== */
+
+  $(document)
+    .on('click.dropdown.data-api', clearMenus)
+    .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+    .on('click.dropdown-menu', function (e) { e.stopPropagation() })
+    .on('click.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)
+    .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
+
+}(window.jQuery);
diff --git a/doc/asset/js/bootstrap-modal.js b/doc/asset/js/bootstrap-modal.js
new file mode 100644
index 0000000..12abe06
--- /dev/null
+++ b/doc/asset/js/bootstrap-modal.js
@@ -0,0 +1,247 @@
+/* =========================================================
+ * bootstrap-modal.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#modals
+ * =========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* MODAL CLASS DEFINITION
+  * ====================== */
+
+  var Modal = function (element, options) {
+    this.options = options
+    this.$element = $(element)
+      .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+    this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
+  }
+
+  Modal.prototype = {
+
+      constructor: Modal
+
+    , toggle: function () {
+        return this[!this.isShown ? 'show' : 'hide']()
+      }
+
+    , show: function () {
+        var that = this
+          , e = $.Event('show')
+
+        this.$element.trigger(e)
+
+        if (this.isShown || e.isDefaultPrevented()) return
+
+        this.isShown = true
+
+        this.escape()
+
+        this.backdrop(function () {
+          var transition = $.support.transition && that.$element.hasClass('fade')
+
+          if (!that.$element.parent().length) {
+            that.$element.appendTo(document.body) //don't move modals dom position
+          }
+
+          that.$element.show()
+
+          if (transition) {
+            that.$element[0].offsetWidth // force reflow
+          }
+
+          that.$element
+            .addClass('in')
+            .attr('aria-hidden', false)
+
+          that.enforceFocus()
+
+          transition ?
+            that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
+            that.$element.focus().trigger('shown')
+
+        })
+      }
+
+    , hide: function (e) {
+        e && e.preventDefault()
+
+        var that = this
+
+        e = $.Event('hide')
+
+        this.$element.trigger(e)
+
+        if (!this.isShown || e.isDefaultPrevented()) return
+
+        this.isShown = false
+
+        this.escape()
+
+        $(document).off('focusin.modal')
+
+        this.$element
+          .removeClass('in')
+          .attr('aria-hidden', true)
+
+        $.support.transition && this.$element.hasClass('fade') ?
+          this.hideWithTransition() :
+          this.hideModal()
+      }
+
+    , enforceFocus: function () {
+        var that = this
+        $(document).on('focusin.modal', function (e) {
+          if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
+            that.$element.focus()
+          }
+        })
+      }
+
+    , escape: function () {
+        var that = this
+        if (this.isShown && this.options.keyboard) {
+          this.$element.on('keyup.dismiss.modal', function ( e ) {
+            e.which == 27 && that.hide()
+          })
+        } else if (!this.isShown) {
+          this.$element.off('keyup.dismiss.modal')
+        }
+      }
+
+    , hideWithTransition: function () {
+        var that = this
+          , timeout = setTimeout(function () {
+              that.$element.off($.support.transition.end)
+              that.hideModal()
+            }, 500)
+
+        this.$element.one($.support.transition.end, function () {
+          clearTimeout(timeout)
+          that.hideModal()
+        })
+      }
+
+    , hideModal: function () {
+        var that = this
+        this.$element.hide()
+        this.backdrop(function () {
+          that.removeBackdrop()
+          that.$element.trigger('hidden')
+        })
+      }
+
+    , removeBackdrop: function () {
+        this.$backdrop && this.$backdrop.remove()
+        this.$backdrop = null
+      }
+
+    , backdrop: function (callback) {
+        var that = this
+          , animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+        if (this.isShown && this.options.backdrop) {
+          var doAnimate = $.support.transition && animate
+
+          this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+            .appendTo(document.body)
+
+          this.$backdrop.click(
+            this.options.backdrop == 'static' ?
+              $.proxy(this.$element[0].focus, this.$element[0])
+            : $.proxy(this.hide, this)
+          )
+
+          if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+          this.$backdrop.addClass('in')
+
+          if (!callback) return
+
+          doAnimate ?
+            this.$backdrop.one($.support.transition.end, callback) :
+            callback()
+
+        } else if (!this.isShown && this.$backdrop) {
+          this.$backdrop.removeClass('in')
+
+          $.support.transition && this.$element.hasClass('fade')?
+            this.$backdrop.one($.support.transition.end, callback) :
+            callback()
+
+        } else if (callback) {
+          callback()
+        }
+      }
+  }
+
+
+ /* MODAL PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.modal
+
+  $.fn.modal = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('modal')
+        , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
+      if (!data) $this.data('modal', (data = new Modal(this, options)))
+      if (typeof option == 'string') data[option]()
+      else if (options.show) data.show()
+    })
+  }
+
+  $.fn.modal.defaults = {
+      backdrop: true
+    , keyboard: true
+    , show: true
+  }
+
+  $.fn.modal.Constructor = Modal
+
+
+ /* MODAL NO CONFLICT
+  * ================= */
+
+  $.fn.modal.noConflict = function () {
+    $.fn.modal = old
+    return this
+  }
+
+
+ /* MODAL DATA-API
+  * ============== */
+
+  $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
+    var $this = $(this)
+      , href = $this.attr('href')
+      , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
+      , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
+
+    e.preventDefault()
+
+    $target
+      .modal(option)
+      .one('hide', function () {
+        $this.focus()
+      })
+  })
+
+}(window.jQuery);
diff --git a/doc/asset/js/bootstrap-popover.js b/doc/asset/js/bootstrap-popover.js
new file mode 100644
index 0000000..e6d897c
--- /dev/null
+++ b/doc/asset/js/bootstrap-popover.js
@@ -0,0 +1,114 @@
+/* ===========================================================
+ * bootstrap-popover.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* POPOVER PUBLIC CLASS DEFINITION
+  * =============================== */
+
+  var Popover = function (element, options) {
+    this.init('popover', element, options)
+  }
+
+
+  /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+     ========================================== */
+
+  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+    constructor: Popover
+
+  , setContent: function () {
+      var $tip = this.tip()
+        , title = this.getTitle()
+        , content = this.getContent()
+
+      $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+      $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
+
+      $tip.removeClass('fade top bottom left right in')
+    }
+
+  , hasContent: function () {
+      return this.getTitle() || this.getContent()
+    }
+
+  , getContent: function () {
+      var content
+        , $e = this.$element
+        , o = this.options
+
+      content = (typeof o.content == 'function' ? o.content.call($e[0]) :  o.content)
+        || $e.attr('data-content')
+
+      return content
+    }
+
+  , tip: function () {
+      if (!this.$tip) {
+        this.$tip = $(this.options.template)
+      }
+      return this.$tip
+    }
+
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
+  })
+
+
+ /* POPOVER PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.popover
+
+  $.fn.popover = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('popover')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('popover', (data = new Popover(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.popover.Constructor = Popover
+
+  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
+    placement: 'right'
+  , trigger: 'click'
+  , content: ''
+  , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+  })
+
+
+ /* POPOVER NO CONFLICT
+  * =================== */
+
+  $.fn.popover.noConflict = function () {
+    $.fn.popover = old
+    return this
+  }
+
+}(window.jQuery);
diff --git a/doc/asset/js/bootstrap-scrollspy.js b/doc/asset/js/bootstrap-scrollspy.js
new file mode 100644
index 0000000..ac1402b
--- /dev/null
+++ b/doc/asset/js/bootstrap-scrollspy.js
@@ -0,0 +1,162 @@
+/* =============================================================
+ * bootstrap-scrollspy.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#scrollspy
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* SCROLLSPY CLASS DEFINITION
+  * ========================== */
+
+  function ScrollSpy(element, options) {
+    var process = $.proxy(this.process, this)
+      , $element = $(element).is('body') ? $(window) : $(element)
+      , href
+    this.options = $.extend({}, $.fn.scrollspy.defaults, options)
+    this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
+    this.selector = (this.options.target
+      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+      || '') + ' .nav li > a'
+    this.$body = $('body')
+    this.refresh()
+    this.process()
+  }
+
+  ScrollSpy.prototype = {
+
+      constructor: ScrollSpy
+
+    , refresh: function () {
+        var self = this
+          , $targets
+
+        this.offsets = $([])
+        this.targets = $([])
+
+        $targets = this.$body
+          .find(this.selector)
+          .map(function () {
+            var $el = $(this)
+              , href = $el.data('target') || $el.attr('href')
+              , $href = /^#\w/.test(href) && $(href)
+            return ( $href
+              && $href.length
+              && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null
+          })
+          .sort(function (a, b) { return a[0] - b[0] })
+          .each(function () {
+            self.offsets.push(this[0])
+            self.targets.push(this[1])
+          })
+      }
+
+    , process: function () {
+        var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+          , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
+          , maxScroll = scrollHeight - this.$scrollElement.height()
+          , offsets = this.offsets
+          , targets = this.targets
+          , activeTarget = this.activeTarget
+          , i
+
+        if (scrollTop >= maxScroll) {
+          return activeTarget != (i = targets.last()[0])
+            && this.activate ( i )
+        }
+
+        for (i = offsets.length; i--;) {
+          activeTarget != targets[i]
+            && scrollTop >= offsets[i]
+            && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+            && this.activate( targets[i] )
+        }
+      }
+
+    , activate: function (target) {
+        var active
+          , selector
+
+        this.activeTarget = target
+
+        $(this.selector)
+          .parent('.active')
+          .removeClass('active')
+
+        selector = this.selector
+          + '[data-target="' + target + '"],'
+          + this.selector + '[href="' + target + '"]'
+
+        active = $(selector)
+          .parent('li')
+          .addClass('active')
+
+        if (active.parent('.dropdown-menu').length)  {
+          active = active.closest('li.dropdown').addClass('active')
+        }
+
+        active.trigger('activate')
+      }
+
+  }
+
+
+ /* SCROLLSPY PLUGIN DEFINITION
+  * =========================== */
+
+  var old = $.fn.scrollspy
+
+  $.fn.scrollspy = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('scrollspy')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.scrollspy.Constructor = ScrollSpy
+
+  $.fn.scrollspy.defaults = {
+    offset: 10
+  }
+
+
+ /* SCROLLSPY NO CONFLICT
+  * ===================== */
+
+  $.fn.scrollspy.noConflict = function () {
+    $.fn.scrollspy = old
+    return this
+  }
+
+
+ /* SCROLLSPY DATA-API
+  * ================== */
+
+  $(window).on('load', function () {
+    $('[data-spy="scroll"]').each(function () {
+      var $spy = $(this)
+      $spy.scrollspy($spy.data())
+    })
+  })
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/doc/asset/js/bootstrap-tab.js b/doc/asset/js/bootstrap-tab.js
new file mode 100644
index 0000000..1d23df6
--- /dev/null
+++ b/doc/asset/js/bootstrap-tab.js
@@ -0,0 +1,144 @@
+/* ========================================================
+ * bootstrap-tab.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
+ * ========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* TAB CLASS DEFINITION
+  * ==================== */
+
+  var Tab = function (element) {
+    this.element = $(element)
+  }
+
+  Tab.prototype = {
+
+    constructor: Tab
+
+  , show: function () {
+      var $this = this.element
+        , $ul = $this.closest('ul:not(.dropdown-menu)')
+        , selector = $this.attr('data-target')
+        , previous
+        , $target
+        , e
+
+      if (!selector) {
+        selector = $this.attr('href')
+        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+      }
+
+      if ( $this.parent('li').hasClass('active') ) return
+
+      previous = $ul.find('.active:last a')[0]
+
+      e = $.Event('show', {
+        relatedTarget: previous
+      })
+
+      $this.trigger(e)
+
+      if (e.isDefaultPrevented()) return
+
+      $target = $(selector)
+
+      this.activate($this.parent('li'), $ul)
+      this.activate($target, $target.parent(), function () {
+        $this.trigger({
+          type: 'shown'
+        , relatedTarget: previous
+        })
+      })
+    }
+
+  , activate: function ( element, container, callback) {
+      var $active = container.find('> .active')
+        , transition = callback
+            && $.support.transition
+            && $active.hasClass('fade')
+
+      function next() {
+        $active
+          .removeClass('active')
+          .find('> .dropdown-menu > .active')
+          .removeClass('active')
+
+        element.addClass('active')
+
+        if (transition) {
+          element[0].offsetWidth // reflow for transition
+          element.addClass('in')
+        } else {
+          element.removeClass('fade')
+        }
+
+        if ( element.parent('.dropdown-menu') ) {
+          element.closest('li.dropdown').addClass('active')
+        }
+
+        callback && callback()
+      }
+
+      transition ?
+        $active.one($.support.transition.end, next) :
+        next()
+
+      $active.removeClass('in')
+    }
+  }
+
+
+ /* TAB PLUGIN DEFINITION
+  * ===================== */
+
+  var old = $.fn.tab
+
+  $.fn.tab = function ( option ) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('tab')
+      if (!data) $this.data('tab', (data = new Tab(this)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.tab.Constructor = Tab
+
+
+ /* TAB NO CONFLICT
+  * =============== */
+
+  $.fn.tab.noConflict = function () {
+    $.fn.tab = old
+    return this
+  }
+
+
+ /* TAB DATA-API
+  * ============ */
+
+  $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+    e.preventDefault()
+    $(this).tab('show')
+  })
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/doc/asset/js/bootstrap-tooltip.js b/doc/asset/js/bootstrap-tooltip.js
new file mode 100644
index 0000000..835abbe
--- /dev/null
+++ b/doc/asset/js/bootstrap-tooltip.js
@@ -0,0 +1,361 @@
+/* ===========================================================
+ * bootstrap-tooltip.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* TOOLTIP PUBLIC CLASS DEFINITION
+  * =============================== */
+
+  var Tooltip = function (element, options) {
+    this.init('tooltip', element, options)
+  }
+
+  Tooltip.prototype = {
+
+    constructor: Tooltip
+
+  , init: function (type, element, options) {
+      var eventIn
+        , eventOut
+        , triggers
+        , trigger
+        , i
+
+      this.type = type
+      this.$element = $(element)
+      this.options = this.getOptions(options)
+      this.enabled = true
+
+      triggers = this.options.trigger.split(' ')
+
+      for (i = triggers.length; i--;) {
+        trigger = triggers[i]
+        if (trigger == 'click') {
+          this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+        } else if (trigger != 'manual') {
+          eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
+          eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
+          this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+          this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+        }
+      }
+
+      this.options.selector ?
+        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+        this.fixTitle()
+    }
+
+  , getOptions: function (options) {
+      options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)
+
+      if (options.delay && typeof options.delay == 'number') {
+        options.delay = {
+          show: options.delay
+        , hide: options.delay
+        }
+      }
+
+      return options
+    }
+
+  , enter: function (e) {
+      var defaults = $.fn[this.type].defaults
+        , options = {}
+        , self
+
+      this._options && $.each(this._options, function (key, value) {
+        if (defaults[key] != value) options[key] = value
+      }, this)
+
+      self = $(e.currentTarget)[this.type](options).data(this.type)
+
+      if (!self.options.delay || !self.options.delay.show) return self.show()
+
+      clearTimeout(this.timeout)
+      self.hoverState = 'in'
+      this.timeout = setTimeout(function() {
+        if (self.hoverState == 'in') self.show()
+      }, self.options.delay.show)
+    }
+
+  , leave: function (e) {
+      var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+      if (this.timeout) clearTimeout(this.timeout)
+      if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+      self.hoverState = 'out'
+      this.timeout = setTimeout(function() {
+        if (self.hoverState == 'out') self.hide()
+      }, self.options.delay.hide)
+    }
+
+  , show: function () {
+      var $tip
+        , pos
+        , actualWidth
+        , actualHeight
+        , placement
+        , tp
+        , e = $.Event('show')
+
+      if (this.hasContent() && this.enabled) {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $tip = this.tip()
+        this.setContent()
+
+        if (this.options.animation) {
+          $tip.addClass('fade')
+        }
+
+        placement = typeof this.options.placement == 'function' ?
+          this.options.placement.call(this, $tip[0], this.$element[0]) :
+          this.options.placement
+
+        $tip
+          .detach()
+          .css({ top: 0, left: 0, display: 'block' })
+
+        this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+
+        pos = this.getPosition()
+
+        actualWidth = $tip[0].offsetWidth
+        actualHeight = $tip[0].offsetHeight
+
+        switch (placement) {
+          case 'bottom':
+            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
+            break
+          case 'top':
+            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
+            break
+          case 'left':
+            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
+            break
+          case 'right':
+            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
+            break
+        }
+
+        this.applyPlacement(tp, placement)
+        this.$element.trigger('shown')
+      }
+    }
+
+  , applyPlacement: function(offset, placement){
+      var $tip = this.tip()
+        , width = $tip[0].offsetWidth
+        , height = $tip[0].offsetHeight
+        , actualWidth
+        , actualHeight
+        , delta
+        , replace
+
+      $tip
+        .offset(offset)
+        .addClass(placement)
+        .addClass('in')
+
+      actualWidth = $tip[0].offsetWidth
+      actualHeight = $tip[0].offsetHeight
+
+      if (placement == 'top' && actualHeight != height) {
+        offset.top = offset.top + height - actualHeight
+        replace = true
+      }
+
+      if (placement == 'bottom' || placement == 'top') {
+        delta = 0
+
+        if (offset.left < 0){
+          delta = offset.left * -2
+          offset.left = 0
+          $tip.offset(offset)
+          actualWidth = $tip[0].offsetWidth
+          actualHeight = $tip[0].offsetHeight
+        }
+
+        this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
+      } else {
+        this.replaceArrow(actualHeight - height, actualHeight, 'top')
+      }
+
+      if (replace) $tip.offset(offset)
+    }
+
+  , replaceArrow: function(delta, dimension, position){
+      this
+        .arrow()
+        .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
+    }
+
+  , setContent: function () {
+      var $tip = this.tip()
+        , title = this.getTitle()
+
+      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+      $tip.removeClass('fade in top bottom left right')
+    }
+
+  , hide: function () {
+      var that = this
+        , $tip = this.tip()
+        , e = $.Event('hide')
+
+      this.$element.trigger(e)
+      if (e.isDefaultPrevented()) return
+
+      $tip.removeClass('in')
+
+      function removeWithAnimation() {
+        var timeout = setTimeout(function () {
+          $tip.off($.support.transition.end).detach()
+        }, 500)
+
+        $tip.one($.support.transition.end, function () {
+          clearTimeout(timeout)
+          $tip.detach()
+        })
+      }
+
+      $.support.transition && this.$tip.hasClass('fade') ?
+        removeWithAnimation() :
+        $tip.detach()
+
+      this.$element.trigger('hidden')
+
+      return this
+    }
+
+  , fixTitle: function () {
+      var $e = this.$element
+      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
+        $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+      }
+    }
+
+  , hasContent: function () {
+      return this.getTitle()
+    }
+
+  , getPosition: function () {
+      var el = this.$element[0]
+      return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
+        width: el.offsetWidth
+      , height: el.offsetHeight
+      }, this.$element.offset())
+    }
+
+  , getTitle: function () {
+      var title
+        , $e = this.$element
+        , o = this.options
+
+      title = $e.attr('data-original-title')
+        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
+
+      return title
+    }
+
+  , tip: function () {
+      return this.$tip = this.$tip || $(this.options.template)
+    }
+
+  , arrow: function(){
+      return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
+    }
+
+  , validate: function () {
+      if (!this.$element[0].parentNode) {
+        this.hide()
+        this.$element = null
+        this.options = null
+      }
+    }
+
+  , enable: function () {
+      this.enabled = true
+    }
+
+  , disable: function () {
+      this.enabled = false
+    }
+
+  , toggleEnabled: function () {
+      this.enabled = !this.enabled
+    }
+
+  , toggle: function (e) {
+      var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
+      self.tip().hasClass('in') ? self.hide() : self.show()
+    }
+
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
+  }
+
+
+ /* TOOLTIP PLUGIN DEFINITION
+  * ========================= */
+
+  var old = $.fn.tooltip
+
+  $.fn.tooltip = function ( option ) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('tooltip')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.tooltip.Constructor = Tooltip
+
+  $.fn.tooltip.defaults = {
+    animation: true
+  , placement: 'top'
+  , selector: false
+  , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
+  , trigger: 'hover focus'
+  , title: ''
+  , delay: 0
+  , html: false
+  , container: false
+  }
+
+
+ /* TOOLTIP NO CONFLICT
+  * =================== */
+
+  $.fn.tooltip.noConflict = function () {
+    $.fn.tooltip = old
+    return this
+  }
+
+}(window.jQuery);
diff --git a/doc/asset/js/bootstrap-transition.js b/doc/asset/js/bootstrap-transition.js
new file mode 100644
index 0000000..92719d3
--- /dev/null
+++ b/doc/asset/js/bootstrap-transition.js
@@ -0,0 +1,60 @@
+/* ===================================================
+ * bootstrap-transition.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+  /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
+   * ======================================================= */
+
+  $(function () {
+
+    $.support.transition = (function () {
+
+      var transitionEnd = (function () {
+
+        var el = document.createElement('bootstrap')
+          , transEndEventNames = {
+               'WebkitTransition' : 'webkitTransitionEnd'
+            ,  'MozTransition'    : 'transitionend'
+            ,  'OTransition'      : 'oTransitionEnd otransitionend'
+            ,  'transition'       : 'transitionend'
+            }
+          , name
+
+        for (name in transEndEventNames){
+          if (el.style[name] !== undefined) {
+            return transEndEventNames[name]
+          }
+        }
+
+      }())
+
+      return transitionEnd && {
+        end: transitionEnd
+      }
+
+    })()
+
+  })
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/doc/asset/js/bootstrap-typeahead.js b/doc/asset/js/bootstrap-typeahead.js
new file mode 100644
index 0000000..280cde8
--- /dev/null
+++ b/doc/asset/js/bootstrap-typeahead.js
@@ -0,0 +1,335 @@
+/* =============================================================
+ * bootstrap-typeahead.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#typeahead
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function($){
+
+  "use strict"; // jshint ;_;
+
+
+ /* TYPEAHEAD PUBLIC CLASS DEFINITION
+  * ================================= */
+
+  var Typeahead = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.typeahead.defaults, options)
+    this.matcher = this.options.matcher || this.matcher
+    this.sorter = this.options.sorter || this.sorter
+    this.highlighter = this.options.highlighter || this.highlighter
+    this.updater = this.options.updater || this.updater
+    this.source = this.options.source
+    this.$menu = $(this.options.menu)
+    this.shown = false
+    this.listen()
+  }
+
+  Typeahead.prototype = {
+
+    constructor: Typeahead
+
+  , select: function () {
+      var val = this.$menu.find('.active').attr('data-value')
+      this.$element
+        .val(this.updater(val))
+        .change()
+      return this.hide()
+    }
+
+  , updater: function (item) {
+      return item
+    }
+
+  , show: function () {
+      var pos = $.extend({}, this.$element.position(), {
+        height: this.$element[0].offsetHeight
+      })
+
+      this.$menu
+        .insertAfter(this.$element)
+        .css({
+          top: pos.top + pos.height
+        , left: pos.left
+        })
+        .show()
+
+      this.shown = true
+      return this
+    }
+
+  , hide: function () {
+      this.$menu.hide()
+      this.shown = false
+      return this
+    }
+
+  , lookup: function (event) {
+      var items
+
+      this.query = this.$element.val()
+
+      if (!this.query || this.query.length < this.options.minLength) {
+        return this.shown ? this.hide() : this
+      }
+
+      items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
+
+      return items ? this.process(items) : this
+    }
+
+  , process: function (items) {
+      var that = this
+
+      items = $.grep(items, function (item) {
+        return that.matcher(item)
+      })
+
+      items = this.sorter(items)
+
+      if (!items.length) {
+        return this.shown ? this.hide() : this
+      }
+
+      return this.render(items.slice(0, this.options.items)).show()
+    }
+
+  , matcher: function (item) {
+      return ~item.toLowerCase().indexOf(this.query.toLowerCase())
+    }
+
+  , sorter: function (items) {
+      var beginswith = []
+        , caseSensitive = []
+        , caseInsensitive = []
+        , item
+
+      while (item = items.shift()) {
+        if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
+        else if (~item.indexOf(this.query)) caseSensitive.push(item)
+        else caseInsensitive.push(item)
+      }
+
+      return beginswith.concat(caseSensitive, caseInsensitive)
+    }
+
+  , highlighter: function (item) {
+      var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
+      return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
+        return '<strong>' + match + '</strong>'
+      })
+    }
+
+  , render: function (items) {
+      var that = this
+
+      items = $(items).map(function (i, item) {
+        i = $(that.options.item).attr('data-value', item)
+        i.find('a').html(that.highlighter(item))
+        return i[0]
+      })
+
+      items.first().addClass('active')
+      this.$menu.html(items)
+      return this
+    }
+
+  , next: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , next = active.next()
+
+      if (!next.length) {
+        next = $(this.$menu.find('li')[0])
+      }
+
+      next.addClass('active')
+    }
+
+  , prev: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , prev = active.prev()
+
+      if (!prev.length) {
+        prev = this.$menu.find('li').last()
+      }
+
+      prev.addClass('active')
+    }
+
+  , listen: function () {
+      this.$element
+        .on('focus',    $.proxy(this.focus, this))
+        .on('blur',     $.proxy(this.blur, this))
+        .on('keypress', $.proxy(this.keypress, this))
+        .on('keyup',    $.proxy(this.keyup, this))
+
+      if (this.eventSupported('keydown')) {
+        this.$element.on('keydown', $.proxy(this.keydown, this))
+      }
+
+      this.$menu
+        .on('click', $.proxy(this.click, this))
+        .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
+        .on('mouseleave', 'li', $.proxy(this.mouseleave, this))
+    }
+
+  , eventSupported: function(eventName) {
+      var isSupported = eventName in this.$element
+      if (!isSupported) {
+        this.$element.setAttribute(eventName, 'return;')
+        isSupported = typeof this.$element[eventName] === 'function'
+      }
+      return isSupported
+    }
+
+  , move: function (e) {
+      if (!this.shown) return
+
+      switch(e.keyCode) {
+        case 9: // tab
+        case 13: // enter
+        case 27: // escape
+          e.preventDefault()
+          break
+
+        case 38: // up arrow
+          e.preventDefault()
+          this.prev()
+          break
+
+        case 40: // down arrow
+          e.preventDefault()
+          this.next()
+          break
+      }
+
+      e.stopPropagation()
+    }
+
+  , keydown: function (e) {
+      this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])
+      this.move(e)
+    }
+
+  , keypress: function (e) {
+      if (this.suppressKeyPressRepeat) return
+      this.move(e)
+    }
+
+  , keyup: function (e) {
+      switch(e.keyCode) {
+        case 40: // down arrow
+        case 38: // up arrow
+        case 16: // shift
+        case 17: // ctrl
+        case 18: // alt
+          break
+
+        case 9: // tab
+        case 13: // enter
+          if (!this.shown) return
+          this.select()
+          break
+
+        case 27: // escape
+          if (!this.shown) return
+          this.hide()
+          break
+
+        default:
+          this.lookup()
+      }
+
+      e.stopPropagation()
+      e.preventDefault()
+  }
+
+  , focus: function (e) {
+      this.focused = true
+    }
+
+  , blur: function (e) {
+      this.focused = false
+      if (!this.mousedover && this.shown) this.hide()
+    }
+
+  , click: function (e) {
+      e.stopPropagation()
+      e.preventDefault()
+      this.select()
+      this.$element.focus()
+    }
+
+  , mouseenter: function (e) {
+      this.mousedover = true
+      this.$menu.find('.active').removeClass('active')
+      $(e.currentTarget).addClass('active')
+    }
+
+  , mouseleave: function (e) {
+      this.mousedover = false
+      if (!this.focused && this.shown) this.hide()
+    }
+
+  }
+
+
+  /* TYPEAHEAD PLUGIN DEFINITION
+   * =========================== */
+
+  var old = $.fn.typeahead
+
+  $.fn.typeahead = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('typeahead')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.typeahead.defaults = {
+    source: []
+  , items: 8
+  , menu: '<ul class="typeahead dropdown-menu"></ul>'
+  , item: '<li><a href="#"></a></li>'
+  , minLength: 1
+  }
+
+  $.fn.typeahead.Constructor = Typeahead
+
+
+ /* TYPEAHEAD NO CONFLICT
+  * =================== */
+
+  $.fn.typeahead.noConflict = function () {
+    $.fn.typeahead = old
+    return this
+  }
+
+
+ /* TYPEAHEAD DATA-API
+  * ================== */
+
+  $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
+    var $this = $(this)
+    if ($this.data('typeahead')) return
+    $this.typeahead($this.data())
+  })
+
+}(window.jQuery);
diff --git a/doc/asset/js/bootstrap.js b/doc/asset/js/bootstrap.js
new file mode 100644
index 0000000..c298ee4
--- /dev/null
+++ b/doc/asset/js/bootstrap.js
@@ -0,0 +1,2276 @@
+/* ===================================================
+ * bootstrap-transition.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+  /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
+   * ======================================================= */
+
+  $(function () {
+
+    $.support.transition = (function () {
+
+      var transitionEnd = (function () {
+
+        var el = document.createElement('bootstrap')
+          , transEndEventNames = {
+               'WebkitTransition' : 'webkitTransitionEnd'
+            ,  'MozTransition'    : 'transitionend'
+            ,  'OTransition'      : 'oTransitionEnd otransitionend'
+            ,  'transition'       : 'transitionend'
+            }
+          , name
+
+        for (name in transEndEventNames){
+          if (el.style[name] !== undefined) {
+            return transEndEventNames[name]
+          }
+        }
+
+      }())
+
+      return transitionEnd && {
+        end: transitionEnd
+      }
+
+    })()
+
+  })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-alert.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* ALERT CLASS DEFINITION
+  * ====================== */
+
+  var dismiss = '[data-dismiss="alert"]'
+    , Alert = function (el) {
+        $(el).on('click', dismiss, this.close)
+      }
+
+  Alert.prototype.close = function (e) {
+    var $this = $(this)
+      , selector = $this.attr('data-target')
+      , $parent
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+    }
+
+    $parent = $(selector)
+
+    e && e.preventDefault()
+
+    $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
+
+    $parent.trigger(e = $.Event('close'))
+
+    if (e.isDefaultPrevented()) return
+
+    $parent.removeClass('in')
+
+    function removeElement() {
+      $parent
+        .trigger('closed')
+        .remove()
+    }
+
+    $.support.transition && $parent.hasClass('fade') ?
+      $parent.on($.support.transition.end, removeElement) :
+      removeElement()
+  }
+
+
+ /* ALERT PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.alert
+
+  $.fn.alert = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('alert')
+      if (!data) $this.data('alert', (data = new Alert(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  $.fn.alert.Constructor = Alert
+
+
+ /* ALERT NO CONFLICT
+  * ================= */
+
+  $.fn.alert.noConflict = function () {
+    $.fn.alert = old
+    return this
+  }
+
+
+ /* ALERT DATA-API
+  * ============== */
+
+  $(document).on('click.alert.data-api', dismiss, Alert.prototype.close)
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-button.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+  * ============================== */
+
+  var Button = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.button.defaults, options)
+  }
+
+  Button.prototype.setState = function (state) {
+    var d = 'disabled'
+      , $el = this.$element
+      , data = $el.data()
+      , val = $el.is('input') ? 'val' : 'html'
+
+    state = state + 'Text'
+    data.resetText || $el.data('resetText', $el[val]())
+
+    $el[val](data[state] || this.options[state])
+
+    // push to event loop to allow forms to submit
+    setTimeout(function () {
+      state == 'loadingText' ?
+        $el.addClass(d).attr(d, d) :
+        $el.removeClass(d).removeAttr(d)
+    }, 0)
+  }
+
+  Button.prototype.toggle = function () {
+    var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
+
+    $parent && $parent
+      .find('.active')
+      .removeClass('active')
+
+    this.$element.toggleClass('active')
+  }
+
+
+ /* BUTTON PLUGIN DEFINITION
+  * ======================== */
+
+  var old = $.fn.button
+
+  $.fn.button = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('button')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('button', (data = new Button(this, options)))
+      if (option == 'toggle') data.toggle()
+      else if (option) data.setState(option)
+    })
+  }
+
+  $.fn.button.defaults = {
+    loadingText: 'loading...'
+  }
+
+  $.fn.button.Constructor = Button
+
+
+ /* BUTTON NO CONFLICT
+  * ================== */
+
+  $.fn.button.noConflict = function () {
+    $.fn.button = old
+    return this
+  }
+
+
+ /* BUTTON DATA-API
+  * =============== */
+
+  $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
+    var $btn = $(e.target)
+    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+    $btn.button('toggle')
+  })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-carousel.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* CAROUSEL CLASS DEFINITION
+  * ========================= */
+
+  var Carousel = function (element, options) {
+    this.$element = $(element)
+    this.$indicators = this.$element.find('.carousel-indicators')
+    this.options = options
+    this.options.pause == 'hover' && this.$element
+      .on('mouseenter', $.proxy(this.pause, this))
+      .on('mouseleave', $.proxy(this.cycle, this))
+  }
+
+  Carousel.prototype = {
+
+    cycle: function (e) {
+      if (!e) this.paused = false
+      if (this.interval) clearInterval(this.interval);
+      this.options.interval
+        && !this.paused
+        && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+      return this
+    }
+
+  , getActiveIndex: function () {
+      this.$active = this.$element.find('.item.active')
+      this.$items = this.$active.parent().children()
+      return this.$items.index(this.$active)
+    }
+
+  , to: function (pos) {
+      var activeIndex = this.getActiveIndex()
+        , that = this
+
+      if (pos > (this.$items.length - 1) || pos < 0) return
+
+      if (this.sliding) {
+        return this.$element.one('slid', function () {
+          that.to(pos)
+        })
+      }
+
+      if (activeIndex == pos) {
+        return this.pause().cycle()
+      }
+
+      return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
+    }
+
+  , pause: function (e) {
+      if (!e) this.paused = true
+      if (this.$element.find('.next, .prev').length && $.support.transition.end) {
+        this.$element.trigger($.support.transition.end)
+        this.cycle(true)
+      }
+      clearInterval(this.interval)
+      this.interval = null
+      return this
+    }
+
+  , next: function () {
+      if (this.sliding) return
+      return this.slide('next')
+    }
+
+  , prev: function () {
+      if (this.sliding) return
+      return this.slide('prev')
+    }
+
+  , slide: function (type, next) {
+      var $active = this.$element.find('.item.active')
+        , $next = next || $active[type]()
+        , isCycling = this.interval
+        , direction = type == 'next' ? 'left' : 'right'
+        , fallback  = type == 'next' ? 'first' : 'last'
+        , that = this
+        , e
+
+      this.sliding = true
+
+      isCycling && this.pause()
+
+      $next = $next.length ? $next : this.$element.find('.item')[fallback]()
+
+      e = $.Event('slide', {
+        relatedTarget: $next[0]
+      , direction: direction
+      })
+
+      if ($next.hasClass('active')) return
+
+      if (this.$indicators.length) {
+        this.$indicators.find('.active').removeClass('active')
+        this.$element.one('slid', function () {
+          var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
+          $nextIndicator && $nextIndicator.addClass('active')
+        })
+      }
+
+      if ($.support.transition && this.$element.hasClass('slide')) {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $next.addClass(type)
+        $next[0].offsetWidth // force reflow
+        $active.addClass(direction)
+        $next.addClass(direction)
+        this.$element.one($.support.transition.end, function () {
+          $next.removeClass([type, direction].join(' ')).addClass('active')
+          $active.removeClass(['active', direction].join(' '))
+          that.sliding = false
+          setTimeout(function () { that.$element.trigger('slid') }, 0)
+        })
+      } else {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $active.removeClass('active')
+        $next.addClass('active')
+        this.sliding = false
+        this.$element.trigger('slid')
+      }
+
+      isCycling && this.cycle()
+
+      return this
+    }
+
+  }
+
+
+ /* CAROUSEL PLUGIN DEFINITION
+  * ========================== */
+
+  var old = $.fn.carousel
+
+  $.fn.carousel = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('carousel')
+        , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
+        , action = typeof option == 'string' ? option : options.slide
+      if (!data) $this.data('carousel', (data = new Carousel(this, options)))
+      if (typeof option == 'number') data.to(option)
+      else if (action) data[action]()
+      else if (options.interval) data.pause().cycle()
+    })
+  }
+
+  $.fn.carousel.defaults = {
+    interval: 5000
+  , pause: 'hover'
+  }
+
+  $.fn.carousel.Constructor = Carousel
+
+
+ /* CAROUSEL NO CONFLICT
+  * ==================== */
+
+  $.fn.carousel.noConflict = function () {
+    $.fn.carousel = old
+    return this
+  }
+
+ /* CAROUSEL DATA-API
+  * ================= */
+
+  $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
+    var $this = $(this), href
+      , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+      , options = $.extend({}, $target.data(), $this.data())
+      , slideIndex
+
+    $target.carousel(options)
+
+    if (slideIndex = $this.attr('data-slide-to')) {
+      $target.data('carousel').pause().to(slideIndex).cycle()
+    }
+
+    e.preventDefault()
+  })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-collapse.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* COLLAPSE PUBLIC CLASS DEFINITION
+  * ================================ */
+
+  var Collapse = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.collapse.defaults, options)
+
+    if (this.options.parent) {
+      this.$parent = $(this.options.parent)
+    }
+
+    this.options.toggle && this.toggle()
+  }
+
+  Collapse.prototype = {
+
+    constructor: Collapse
+
+  , dimension: function () {
+      var hasWidth = this.$element.hasClass('width')
+      return hasWidth ? 'width' : 'height'
+    }
+
+  , show: function () {
+      var dimension
+        , scroll
+        , actives
+        , hasData
+
+      if (this.transitioning || this.$element.hasClass('in')) return
+
+      dimension = this.dimension()
+      scroll = $.camelCase(['scroll', dimension].join('-'))
+      actives = this.$parent && this.$parent.find('> .accordion-group > .in')
+
+      if (actives && actives.length) {
+        hasData = actives.data('collapse')
+        if (hasData && hasData.transitioning) return
+        actives.collapse('hide')
+        hasData || actives.data('collapse', null)
+      }
+
+      this.$element[dimension](0)
+      this.transition('addClass', $.Event('show'), 'shown')
+      $.support.transition && this.$element[dimension](this.$element[0][scroll])
+    }
+
+  , hide: function () {
+      var dimension
+      if (this.transitioning || !this.$element.hasClass('in')) return
+      dimension = this.dimension()
+      this.reset(this.$element[dimension]())
+      this.transition('removeClass', $.Event('hide'), 'hidden')
+      this.$element[dimension](0)
+    }
+
+  , reset: function (size) {
+      var dimension = this.dimension()
+
+      this.$element
+        .removeClass('collapse')
+        [dimension](size || 'auto')
+        [0].offsetWidth
+
+      this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
+
+      return this
+    }
+
+  , transition: function (method, startEvent, completeEvent) {
+      var that = this
+        , complete = function () {
+            if (startEvent.type == 'show') that.reset()
+            that.transitioning = 0
+            that.$element.trigger(completeEvent)
+          }
+
+      this.$element.trigger(startEvent)
+
+      if (startEvent.isDefaultPrevented()) return
+
+      this.transitioning = 1
+
+      this.$element[method]('in')
+
+      $.support.transition && this.$element.hasClass('collapse') ?
+        this.$element.one($.support.transition.end, complete) :
+        complete()
+    }
+
+  , toggle: function () {
+      this[this.$element.hasClass('in') ? 'hide' : 'show']()
+    }
+
+  }
+
+
+ /* COLLAPSE PLUGIN DEFINITION
+  * ========================== */
+
+  var old = $.fn.collapse
+
+  $.fn.collapse = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('collapse')
+        , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option)
+      if (!data) $this.data('collapse', (data = new Collapse(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.collapse.defaults = {
+    toggle: true
+  }
+
+  $.fn.collapse.Constructor = Collapse
+
+
+ /* COLLAPSE NO CONFLICT
+  * ==================== */
+
+  $.fn.collapse.noConflict = function () {
+    $.fn.collapse = old
+    return this
+  }
+
+
+ /* COLLAPSE DATA-API
+  * ================= */
+
+  $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
+    var $this = $(this), href
+      , target = $this.attr('data-target')
+        || e.preventDefault()
+        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
+      , option = $(target).data('collapse') ? 'toggle' : $this.data()
+    $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
+    $(target).collapse(option)
+  })
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-dropdown.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* DROPDOWN CLASS DEFINITION
+  * ========================= */
+
+  var toggle = '[data-toggle=dropdown]'
+    , Dropdown = function (element) {
+        var $el = $(element).on('click.dropdown.data-api', this.toggle)
+        $('html').on('click.dropdown.data-api', function () {
+          $el.parent().removeClass('open')
+        })
+      }
+
+  Dropdown.prototype = {
+
+    constructor: Dropdown
+
+  , toggle: function (e) {
+      var $this = $(this)
+        , $parent
+        , isActive
+
+      if ($this.is('.disabled, :disabled')) return
+
+      $parent = getParent($this)
+
+      isActive = $parent.hasClass('open')
+
+      clearMenus()
+
+      if (!isActive) {
+        $parent.toggleClass('open')
+      }
+
+      $this.focus()
+
+      return false
+    }
+
+  , keydown: function (e) {
+      var $this
+        , $items
+        , $active
+        , $parent
+        , isActive
+        , index
+
+      if (!/(38|40|27)/.test(e.keyCode)) return
+
+      $this = $(this)
+
+      e.preventDefault()
+      e.stopPropagation()
+
+      if ($this.is('.disabled, :disabled')) return
+
+      $parent = getParent($this)
+
+      isActive = $parent.hasClass('open')
+
+      if (!isActive || (isActive && e.keyCode == 27)) {
+        if (e.which == 27) $parent.find(toggle).focus()
+        return $this.click()
+      }
+
+      $items = $('[role=menu] li:not(.divider):visible a', $parent)
+
+      if (!$items.length) return
+
+      index = $items.index($items.filter(':focus'))
+
+      if (e.keyCode == 38 && index > 0) index--                                        // up
+      if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
+      if (!~index) index = 0
+
+      $items
+        .eq(index)
+        .focus()
+    }
+
+  }
+
+  function clearMenus() {
+    $(toggle).each(function () {
+      getParent($(this)).removeClass('open')
+    })
+  }
+
+  function getParent($this) {
+    var selector = $this.attr('data-target')
+      , $parent
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+    }
+
+    $parent = selector && $(selector)
+
+    if (!$parent || !$parent.length) $parent = $this.parent()
+
+    return $parent
+  }
+
+
+  /* DROPDOWN PLUGIN DEFINITION
+   * ========================== */
+
+  var old = $.fn.dropdown
+
+  $.fn.dropdown = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('dropdown')
+      if (!data) $this.data('dropdown', (data = new Dropdown(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  $.fn.dropdown.Constructor = Dropdown
+
+
+ /* DROPDOWN NO CONFLICT
+  * ==================== */
+
+  $.fn.dropdown.noConflict = function () {
+    $.fn.dropdown = old
+    return this
+  }
+
+
+  /* APPLY TO STANDARD DROPDOWN ELEMENTS
+   * =================================== */
+
+  $(document)
+    .on('click.dropdown.data-api', clearMenus)
+    .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+    .on('click.dropdown-menu', function (e) { e.stopPropagation() })
+    .on('click.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)
+    .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
+
+}(window.jQuery);
+/* =========================================================
+ * bootstrap-modal.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#modals
+ * =========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* MODAL CLASS DEFINITION
+  * ====================== */
+
+  var Modal = function (element, options) {
+    this.options = options
+    this.$element = $(element)
+      .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+    this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
+  }
+
+  Modal.prototype = {
+
+      constructor: Modal
+
+    , toggle: function () {
+        return this[!this.isShown ? 'show' : 'hide']()
+      }
+
+    , show: function () {
+        var that = this
+          , e = $.Event('show')
+
+        this.$element.trigger(e)
+
+        if (this.isShown || e.isDefaultPrevented()) return
+
+        this.isShown = true
+
+        this.escape()
+
+        this.backdrop(function () {
+          var transition = $.support.transition && that.$element.hasClass('fade')
+
+          if (!that.$element.parent().length) {
+            that.$element.appendTo(document.body) //don't move modals dom position
+          }
+
+          that.$element.show()
+
+          if (transition) {
+            that.$element[0].offsetWidth // force reflow
+          }
+
+          that.$element
+            .addClass('in')
+            .attr('aria-hidden', false)
+
+          that.enforceFocus()
+
+          transition ?
+            that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
+            that.$element.focus().trigger('shown')
+
+        })
+      }
+
+    , hide: function (e) {
+        e && e.preventDefault()
+
+        var that = this
+
+        e = $.Event('hide')
+
+        this.$element.trigger(e)
+
+        if (!this.isShown || e.isDefaultPrevented()) return
+
+        this.isShown = false
+
+        this.escape()
+
+        $(document).off('focusin.modal')
+
+        this.$element
+          .removeClass('in')
+          .attr('aria-hidden', true)
+
+        $.support.transition && this.$element.hasClass('fade') ?
+          this.hideWithTransition() :
+          this.hideModal()
+      }
+
+    , enforceFocus: function () {
+        var that = this
+        $(document).on('focusin.modal', function (e) {
+          if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
+            that.$element.focus()
+          }
+        })
+      }
+
+    , escape: function () {
+        var that = this
+        if (this.isShown && this.options.keyboard) {
+          this.$element.on('keyup.dismiss.modal', function ( e ) {
+            e.which == 27 && that.hide()
+          })
+        } else if (!this.isShown) {
+          this.$element.off('keyup.dismiss.modal')
+        }
+      }
+
+    , hideWithTransition: function () {
+        var that = this
+          , timeout = setTimeout(function () {
+              that.$element.off($.support.transition.end)
+              that.hideModal()
+            }, 500)
+
+        this.$element.one($.support.transition.end, function () {
+          clearTimeout(timeout)
+          that.hideModal()
+        })
+      }
+
+    , hideModal: function () {
+        var that = this
+        this.$element.hide()
+        this.backdrop(function () {
+          that.removeBackdrop()
+          that.$element.trigger('hidden')
+        })
+      }
+
+    , removeBackdrop: function () {
+        this.$backdrop && this.$backdrop.remove()
+        this.$backdrop = null
+      }
+
+    , backdrop: function (callback) {
+        var that = this
+          , animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+        if (this.isShown && this.options.backdrop) {
+          var doAnimate = $.support.transition && animate
+
+          this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+            .appendTo(document.body)
+
+          this.$backdrop.click(
+            this.options.backdrop == 'static' ?
+              $.proxy(this.$element[0].focus, this.$element[0])
+            : $.proxy(this.hide, this)
+          )
+
+          if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+          this.$backdrop.addClass('in')
+
+          if (!callback) return
+
+          doAnimate ?
+            this.$backdrop.one($.support.transition.end, callback) :
+            callback()
+
+        } else if (!this.isShown && this.$backdrop) {
+          this.$backdrop.removeClass('in')
+
+          $.support.transition && this.$element.hasClass('fade')?
+            this.$backdrop.one($.support.transition.end, callback) :
+            callback()
+
+        } else if (callback) {
+          callback()
+        }
+      }
+  }
+
+
+ /* MODAL PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.modal
+
+  $.fn.modal = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('modal')
+        , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
+      if (!data) $this.data('modal', (data = new Modal(this, options)))
+      if (typeof option == 'string') data[option]()
+      else if (options.show) data.show()
+    })
+  }
+
+  $.fn.modal.defaults = {
+      backdrop: true
+    , keyboard: true
+    , show: true
+  }
+
+  $.fn.modal.Constructor = Modal
+
+
+ /* MODAL NO CONFLICT
+  * ================= */
+
+  $.fn.modal.noConflict = function () {
+    $.fn.modal = old
+    return this
+  }
+
+
+ /* MODAL DATA-API
+  * ============== */
+
+  $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
+    var $this = $(this)
+      , href = $this.attr('href')
+      , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
+      , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
+
+    e.preventDefault()
+
+    $target
+      .modal(option)
+      .one('hide', function () {
+        $this.focus()
+      })
+  })
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-tooltip.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* TOOLTIP PUBLIC CLASS DEFINITION
+  * =============================== */
+
+  var Tooltip = function (element, options) {
+    this.init('tooltip', element, options)
+  }
+
+  Tooltip.prototype = {
+
+    constructor: Tooltip
+
+  , init: function (type, element, options) {
+      var eventIn
+        , eventOut
+        , triggers
+        , trigger
+        , i
+
+      this.type = type
+      this.$element = $(element)
+      this.options = this.getOptions(options)
+      this.enabled = true
+
+      triggers = this.options.trigger.split(' ')
+
+      for (i = triggers.length; i--;) {
+        trigger = triggers[i]
+        if (trigger == 'click') {
+          this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+        } else if (trigger != 'manual') {
+          eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
+          eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
+          this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+          this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+        }
+      }
+
+      this.options.selector ?
+        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+        this.fixTitle()
+    }
+
+  , getOptions: function (options) {
+      options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)
+
+      if (options.delay && typeof options.delay == 'number') {
+        options.delay = {
+          show: options.delay
+        , hide: options.delay
+        }
+      }
+
+      return options
+    }
+
+  , enter: function (e) {
+      var defaults = $.fn[this.type].defaults
+        , options = {}
+        , self
+
+      this._options && $.each(this._options, function (key, value) {
+        if (defaults[key] != value) options[key] = value
+      }, this)
+
+      self = $(e.currentTarget)[this.type](options).data(this.type)
+
+      if (!self.options.delay || !self.options.delay.show) return self.show()
+
+      clearTimeout(this.timeout)
+      self.hoverState = 'in'
+      this.timeout = setTimeout(function() {
+        if (self.hoverState == 'in') self.show()
+      }, self.options.delay.show)
+    }
+
+  , leave: function (e) {
+      var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+      if (this.timeout) clearTimeout(this.timeout)
+      if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+      self.hoverState = 'out'
+      this.timeout = setTimeout(function() {
+        if (self.hoverState == 'out') self.hide()
+      }, self.options.delay.hide)
+    }
+
+  , show: function () {
+      var $tip
+        , pos
+        , actualWidth
+        , actualHeight
+        , placement
+        , tp
+        , e = $.Event('show')
+
+      if (this.hasContent() && this.enabled) {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $tip = this.tip()
+        this.setContent()
+
+        if (this.options.animation) {
+          $tip.addClass('fade')
+        }
+
+        placement = typeof this.options.placement == 'function' ?
+          this.options.placement.call(this, $tip[0], this.$element[0]) :
+          this.options.placement
+
+        $tip
+          .detach()
+          .css({ top: 0, left: 0, display: 'block' })
+
+        this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+
+        pos = this.getPosition()
+
+        actualWidth = $tip[0].offsetWidth
+        actualHeight = $tip[0].offsetHeight
+
+        switch (placement) {
+          case 'bottom':
+            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
+            break
+          case 'top':
+            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
+            break
+          case 'left':
+            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
+            break
+          case 'right':
+            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
+            break
+        }
+
+        this.applyPlacement(tp, placement)
+        this.$element.trigger('shown')
+      }
+    }
+
+  , applyPlacement: function(offset, placement){
+      var $tip = this.tip()
+        , width = $tip[0].offsetWidth
+        , height = $tip[0].offsetHeight
+        , actualWidth
+        , actualHeight
+        , delta
+        , replace
+
+      $tip
+        .offset(offset)
+        .addClass(placement)
+        .addClass('in')
+
+      actualWidth = $tip[0].offsetWidth
+      actualHeight = $tip[0].offsetHeight
+
+      if (placement == 'top' && actualHeight != height) {
+        offset.top = offset.top + height - actualHeight
+        replace = true
+      }
+
+      if (placement == 'bottom' || placement == 'top') {
+        delta = 0
+
+        if (offset.left < 0){
+          delta = offset.left * -2
+          offset.left = 0
+          $tip.offset(offset)
+          actualWidth = $tip[0].offsetWidth
+          actualHeight = $tip[0].offsetHeight
+        }
+
+        this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
+      } else {
+        this.replaceArrow(actualHeight - height, actualHeight, 'top')
+      }
+
+      if (replace) $tip.offset(offset)
+    }
+
+  , replaceArrow: function(delta, dimension, position){
+      this
+        .arrow()
+        .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
+    }
+
+  , setContent: function () {
+      var $tip = this.tip()
+        , title = this.getTitle()
+
+      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+      $tip.removeClass('fade in top bottom left right')
+    }
+
+  , hide: function () {
+      var that = this
+        , $tip = this.tip()
+        , e = $.Event('hide')
+
+      this.$element.trigger(e)
+      if (e.isDefaultPrevented()) return
+
+      $tip.removeClass('in')
+
+      function removeWithAnimation() {
+        var timeout = setTimeout(function () {
+          $tip.off($.support.transition.end).detach()
+        }, 500)
+
+        $tip.one($.support.transition.end, function () {
+          clearTimeout(timeout)
+          $tip.detach()
+        })
+      }
+
+      $.support.transition && this.$tip.hasClass('fade') ?
+        removeWithAnimation() :
+        $tip.detach()
+
+      this.$element.trigger('hidden')
+
+      return this
+    }
+
+  , fixTitle: function () {
+      var $e = this.$element
+      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
+        $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+      }
+    }
+
+  , hasContent: function () {
+      return this.getTitle()
+    }
+
+  , getPosition: function () {
+      var el = this.$element[0]
+      return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
+        width: el.offsetWidth
+      , height: el.offsetHeight
+      }, this.$element.offset())
+    }
+
+  , getTitle: function () {
+      var title
+        , $e = this.$element
+        , o = this.options
+
+      title = $e.attr('data-original-title')
+        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
+
+      return title
+    }
+
+  , tip: function () {
+      return this.$tip = this.$tip || $(this.options.template)
+    }
+
+  , arrow: function(){
+      return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
+    }
+
+  , validate: function () {
+      if (!this.$element[0].parentNode) {
+        this.hide()
+        this.$element = null
+        this.options = null
+      }
+    }
+
+  , enable: function () {
+      this.enabled = true
+    }
+
+  , disable: function () {
+      this.enabled = false
+    }
+
+  , toggleEnabled: function () {
+      this.enabled = !this.enabled
+    }
+
+  , toggle: function (e) {
+      var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
+      self.tip().hasClass('in') ? self.hide() : self.show()
+    }
+
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
+  }
+
+
+ /* TOOLTIP PLUGIN DEFINITION
+  * ========================= */
+
+  var old = $.fn.tooltip
+
+  $.fn.tooltip = function ( option ) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('tooltip')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.tooltip.Constructor = Tooltip
+
+  $.fn.tooltip.defaults = {
+    animation: true
+  , placement: 'top'
+  , selector: false
+  , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
+  , trigger: 'hover focus'
+  , title: ''
+  , delay: 0
+  , html: false
+  , container: false
+  }
+
+
+ /* TOOLTIP NO CONFLICT
+  * =================== */
+
+  $.fn.tooltip.noConflict = function () {
+    $.fn.tooltip = old
+    return this
+  }
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-popover.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* POPOVER PUBLIC CLASS DEFINITION
+  * =============================== */
+
+  var Popover = function (element, options) {
+    this.init('popover', element, options)
+  }
+
+
+  /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+     ========================================== */
+
+  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+    constructor: Popover
+
+  , setContent: function () {
+      var $tip = this.tip()
+        , title = this.getTitle()
+        , content = this.getContent()
+
+      $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+      $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
+
+      $tip.removeClass('fade top bottom left right in')
+    }
+
+  , hasContent: function () {
+      return this.getTitle() || this.getContent()
+    }
+
+  , getContent: function () {
+      var content
+        , $e = this.$element
+        , o = this.options
+
+      content = (typeof o.content == 'function' ? o.content.call($e[0]) :  o.content)
+        || $e.attr('data-content')
+
+      return content
+    }
+
+  , tip: function () {
+      if (!this.$tip) {
+        this.$tip = $(this.options.template)
+      }
+      return this.$tip
+    }
+
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
+  })
+
+
+ /* POPOVER PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.popover
+
+  $.fn.popover = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('popover')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('popover', (data = new Popover(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.popover.Constructor = Popover
+
+  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
+    placement: 'right'
+  , trigger: 'click'
+  , content: ''
+  , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+  })
+
+
+ /* POPOVER NO CONFLICT
+  * =================== */
+
+  $.fn.popover.noConflict = function () {
+    $.fn.popover = old
+    return this
+  }
+
+}(window.jQuery);
+/* =============================================================
+ * bootstrap-scrollspy.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#scrollspy
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* SCROLLSPY CLASS DEFINITION
+  * ========================== */
+
+  function ScrollSpy(element, options) {
+    var process = $.proxy(this.process, this)
+      , $element = $(element).is('body') ? $(window) : $(element)
+      , href
+    this.options = $.extend({}, $.fn.scrollspy.defaults, options)
+    this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
+    this.selector = (this.options.target
+      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+      || '') + ' .nav li > a'
+    this.$body = $('body')
+    this.refresh()
+    this.process()
+  }
+
+  ScrollSpy.prototype = {
+
+      constructor: ScrollSpy
+
+    , refresh: function () {
+        var self = this
+          , $targets
+
+        this.offsets = $([])
+        this.targets = $([])
+
+        $targets = this.$body
+          .find(this.selector)
+          .map(function () {
+            var $el = $(this)
+              , href = $el.data('target') || $el.attr('href')
+              , $href = /^#\w/.test(href) && $(href)
+            return ( $href
+              && $href.length
+              && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null
+          })
+          .sort(function (a, b) { return a[0] - b[0] })
+          .each(function () {
+            self.offsets.push(this[0])
+            self.targets.push(this[1])
+          })
+      }
+
+    , process: function () {
+        var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+          , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
+          , maxScroll = scrollHeight - this.$scrollElement.height()
+          , offsets = this.offsets
+          , targets = this.targets
+          , activeTarget = this.activeTarget
+          , i
+
+        if (scrollTop >= maxScroll) {
+          return activeTarget != (i = targets.last()[0])
+            && this.activate ( i )
+        }
+
+        for (i = offsets.length; i--;) {
+          activeTarget != targets[i]
+            && scrollTop >= offsets[i]
+            && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+            && this.activate( targets[i] )
+        }
+      }
+
+    , activate: function (target) {
+        var active
+          , selector
+
+        this.activeTarget = target
+
+        $(this.selector)
+          .parent('.active')
+          .removeClass('active')
+
+        selector = this.selector
+          + '[data-target="' + target + '"],'
+          + this.selector + '[href="' + target + '"]'
+
+        active = $(selector)
+          .parent('li')
+          .addClass('active')
+
+        if (active.parent('.dropdown-menu').length)  {
+          active = active.closest('li.dropdown').addClass('active')
+        }
+
+        active.trigger('activate')
+      }
+
+  }
+
+
+ /* SCROLLSPY PLUGIN DEFINITION
+  * =========================== */
+
+  var old = $.fn.scrollspy
+
+  $.fn.scrollspy = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('scrollspy')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.scrollspy.Constructor = ScrollSpy
+
+  $.fn.scrollspy.defaults = {
+    offset: 10
+  }
+
+
+ /* SCROLLSPY NO CONFLICT
+  * ===================== */
+
+  $.fn.scrollspy.noConflict = function () {
+    $.fn.scrollspy = old
+    return this
+  }
+
+
+ /* SCROLLSPY DATA-API
+  * ================== */
+
+  $(window).on('load', function () {
+    $('[data-spy="scroll"]').each(function () {
+      var $spy = $(this)
+      $spy.scrollspy($spy.data())
+    })
+  })
+
+}(window.jQuery);/* ========================================================
+ * bootstrap-tab.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
+ * ========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* TAB CLASS DEFINITION
+  * ==================== */
+
+  var Tab = function (element) {
+    this.element = $(element)
+  }
+
+  Tab.prototype = {
+
+    constructor: Tab
+
+  , show: function () {
+      var $this = this.element
+        , $ul = $this.closest('ul:not(.dropdown-menu)')
+        , selector = $this.attr('data-target')
+        , previous
+        , $target
+        , e
+
+      if (!selector) {
+        selector = $this.attr('href')
+        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+      }
+
+      if ( $this.parent('li').hasClass('active') ) return
+
+      previous = $ul.find('.active:last a')[0]
+
+      e = $.Event('show', {
+        relatedTarget: previous
+      })
+
+      $this.trigger(e)
+
+      if (e.isDefaultPrevented()) return
+
+      $target = $(selector)
+
+      this.activate($this.parent('li'), $ul)
+      this.activate($target, $target.parent(), function () {
+        $this.trigger({
+          type: 'shown'
+        , relatedTarget: previous
+        })
+      })
+    }
+
+  , activate: function ( element, container, callback) {
+      var $active = container.find('> .active')
+        , transition = callback
+            && $.support.transition
+            && $active.hasClass('fade')
+
+      function next() {
+        $active
+          .removeClass('active')
+          .find('> .dropdown-menu > .active')
+          .removeClass('active')
+
+        element.addClass('active')
+
+        if (transition) {
+          element[0].offsetWidth // reflow for transition
+          element.addClass('in')
+        } else {
+          element.removeClass('fade')
+        }
+
+        if ( element.parent('.dropdown-menu') ) {
+          element.closest('li.dropdown').addClass('active')
+        }
+
+        callback && callback()
+      }
+
+      transition ?
+        $active.one($.support.transition.end, next) :
+        next()
+
+      $active.removeClass('in')
+    }
+  }
+
+
+ /* TAB PLUGIN DEFINITION
+  * ===================== */
+
+  var old = $.fn.tab
+
+  $.fn.tab = function ( option ) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('tab')
+      if (!data) $this.data('tab', (data = new Tab(this)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.tab.Constructor = Tab
+
+
+ /* TAB NO CONFLICT
+  * =============== */
+
+  $.fn.tab.noConflict = function () {
+    $.fn.tab = old
+    return this
+  }
+
+
+ /* TAB DATA-API
+  * ============ */
+
+  $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+    e.preventDefault()
+    $(this).tab('show')
+  })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-typeahead.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#typeahead
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function($){
+
+  "use strict"; // jshint ;_;
+
+
+ /* TYPEAHEAD PUBLIC CLASS DEFINITION
+  * ================================= */
+
+  var Typeahead = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.typeahead.defaults, options)
+    this.matcher = this.options.matcher || this.matcher
+    this.sorter = this.options.sorter || this.sorter
+    this.highlighter = this.options.highlighter || this.highlighter
+    this.updater = this.options.updater || this.updater
+    this.source = this.options.source
+    this.$menu = $(this.options.menu)
+    this.shown = false
+    this.listen()
+  }
+
+  Typeahead.prototype = {
+
+    constructor: Typeahead
+
+  , select: function () {
+      var val = this.$menu.find('.active').attr('data-value')
+      this.$element
+        .val(this.updater(val))
+        .change()
+      return this.hide()
+    }
+
+  , updater: function (item) {
+      return item
+    }
+
+  , show: function () {
+      var pos = $.extend({}, this.$element.position(), {
+        height: this.$element[0].offsetHeight
+      })
+
+      this.$menu
+        .insertAfter(this.$element)
+        .css({
+          top: pos.top + pos.height
+        , left: pos.left
+        })
+        .show()
+
+      this.shown = true
+      return this
+    }
+
+  , hide: function () {
+      this.$menu.hide()
+      this.shown = false
+      return this
+    }
+
+  , lookup: function (event) {
+      var items
+
+      this.query = this.$element.val()
+
+      if (!this.query || this.query.length < this.options.minLength) {
+        return this.shown ? this.hide() : this
+      }
+
+      items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
+
+      return items ? this.process(items) : this
+    }
+
+  , process: function (items) {
+      var that = this
+
+      items = $.grep(items, function (item) {
+        return that.matcher(item)
+      })
+
+      items = this.sorter(items)
+
+      if (!items.length) {
+        return this.shown ? this.hide() : this
+      }
+
+      return this.render(items.slice(0, this.options.items)).show()
+    }
+
+  , matcher: function (item) {
+      return ~item.toLowerCase().indexOf(this.query.toLowerCase())
+    }
+
+  , sorter: function (items) {
+      var beginswith = []
+        , caseSensitive = []
+        , caseInsensitive = []
+        , item
+
+      while (item = items.shift()) {
+        if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
+        else if (~item.indexOf(this.query)) caseSensitive.push(item)
+        else caseInsensitive.push(item)
+      }
+
+      return beginswith.concat(caseSensitive, caseInsensitive)
+    }
+
+  , highlighter: function (item) {
+      var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
+      return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
+        return '<strong>' + match + '</strong>'
+      })
+    }
+
+  , render: function (items) {
+      var that = this
+
+      items = $(items).map(function (i, item) {
+        i = $(that.options.item).attr('data-value', item)
+        i.find('a').html(that.highlighter(item))
+        return i[0]
+      })
+
+      items.first().addClass('active')
+      this.$menu.html(items)
+      return this
+    }
+
+  , next: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , next = active.next()
+
+      if (!next.length) {
+        next = $(this.$menu.find('li')[0])
+      }
+
+      next.addClass('active')
+    }
+
+  , prev: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , prev = active.prev()
+
+      if (!prev.length) {
+        prev = this.$menu.find('li').last()
+      }
+
+      prev.addClass('active')
+    }
+
+  , listen: function () {
+      this.$element
+        .on('focus',    $.proxy(this.focus, this))
+        .on('blur',     $.proxy(this.blur, this))
+        .on('keypress', $.proxy(this.keypress, this))
+        .on('keyup',    $.proxy(this.keyup, this))
+
+      if (this.eventSupported('keydown')) {
+        this.$element.on('keydown', $.proxy(this.keydown, this))
+      }
+
+      this.$menu
+        .on('click', $.proxy(this.click, this))
+        .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
+        .on('mouseleave', 'li', $.proxy(this.mouseleave, this))
+    }
+
+  , eventSupported: function(eventName) {
+      var isSupported = eventName in this.$element
+      if (!isSupported) {
+        this.$element.setAttribute(eventName, 'return;')
+        isSupported = typeof this.$element[eventName] === 'function'
+      }
+      return isSupported
+    }
+
+  , move: function (e) {
+      if (!this.shown) return
+
+      switch(e.keyCode) {
+        case 9: // tab
+        case 13: // enter
+        case 27: // escape
+          e.preventDefault()
+          break
+
+        case 38: // up arrow
+          e.preventDefault()
+          this.prev()
+          break
+
+        case 40: // down arrow
+          e.preventDefault()
+          this.next()
+          break
+      }
+
+      e.stopPropagation()
+    }
+
+  , keydown: function (e) {
+      this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])
+      this.move(e)
+    }
+
+  , keypress: function (e) {
+      if (this.suppressKeyPressRepeat) return
+      this.move(e)
+    }
+
+  , keyup: function (e) {
+      switch(e.keyCode) {
+        case 40: // down arrow
+        case 38: // up arrow
+        case 16: // shift
+        case 17: // ctrl
+        case 18: // alt
+          break
+
+        case 9: // tab
+        case 13: // enter
+          if (!this.shown) return
+          this.select()
+          break
+
+        case 27: // escape
+          if (!this.shown) return
+          this.hide()
+          break
+
+        default:
+          this.lookup()
+      }
+
+      e.stopPropagation()
+      e.preventDefault()
+  }
+
+  , focus: function (e) {
+      this.focused = true
+    }
+
+  , blur: function (e) {
+      this.focused = false
+      if (!this.mousedover && this.shown) this.hide()
+    }
+
+  , click: function (e) {
+      e.stopPropagation()
+      e.preventDefault()
+      this.select()
+      this.$element.focus()
+    }
+
+  , mouseenter: function (e) {
+      this.mousedover = true
+      this.$menu.find('.active').removeClass('active')
+      $(e.currentTarget).addClass('active')
+    }
+
+  , mouseleave: function (e) {
+      this.mousedover = false
+      if (!this.focused && this.shown) this.hide()
+    }
+
+  }
+
+
+  /* TYPEAHEAD PLUGIN DEFINITION
+   * =========================== */
+
+  var old = $.fn.typeahead
+
+  $.fn.typeahead = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('typeahead')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.typeahead.defaults = {
+    source: []
+  , items: 8
+  , menu: '<ul class="typeahead dropdown-menu"></ul>'
+  , item: '<li><a href="#"></a></li>'
+  , minLength: 1
+  }
+
+  $.fn.typeahead.Constructor = Typeahead
+
+
+ /* TYPEAHEAD NO CONFLICT
+  * =================== */
+
+  $.fn.typeahead.noConflict = function () {
+    $.fn.typeahead = old
+    return this
+  }
+
+
+ /* TYPEAHEAD DATA-API
+  * ================== */
+
+  $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
+    var $this = $(this)
+    if ($this.data('typeahead')) return
+    $this.typeahead($this.data())
+  })
+
+}(window.jQuery);
+/* ==========================================================
+ * bootstrap-affix.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#affix
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* AFFIX CLASS DEFINITION
+  * ====================== */
+
+  var Affix = function (element, options) {
+    this.options = $.extend({}, $.fn.affix.defaults, options)
+    this.$window = $(window)
+      .on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
+      .on('click.affix.data-api',  $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this))
+    this.$element = $(element)
+    this.checkPosition()
+  }
+
+  Affix.prototype.checkPosition = function () {
+    if (!this.$element.is(':visible')) return
+
+    var scrollHeight = $(document).height()
+      , scrollTop = this.$window.scrollTop()
+      , position = this.$element.offset()
+      , offset = this.options.offset
+      , offsetBottom = offset.bottom
+      , offsetTop = offset.top
+      , reset = 'affix affix-top affix-bottom'
+      , affix
+
+    if (typeof offset != 'object') offsetBottom = offsetTop = offset
+    if (typeof offsetTop == 'function') offsetTop = offset.top()
+    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
+
+    affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
+      false    : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
+      'bottom' : offsetTop != null && scrollTop <= offsetTop ?
+      'top'    : false
+
+    if (this.affixed === affix) return
+
+    this.affixed = affix
+    this.unpin = affix == 'bottom' ? position.top - scrollTop : null
+
+    this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
+  }
+
+
+ /* AFFIX PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.affix
+
+  $.fn.affix = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('affix')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('affix', (data = new Affix(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.affix.Constructor = Affix
+
+  $.fn.affix.defaults = {
+    offset: 0
+  }
+
+
+ /* AFFIX NO CONFLICT
+  * ================= */
+
+  $.fn.affix.noConflict = function () {
+    $.fn.affix = old
+    return this
+  }
+
+
+ /* AFFIX DATA-API
+  * ============== */
+
+  $(window).on('load', function () {
+    $('[data-spy="affix"]').each(function () {
+      var $spy = $(this)
+        , data = $spy.data()
+
+      data.offset = data.offset || {}
+
+      data.offsetBottom && (data.offset.bottom = data.offsetBottom)
+      data.offsetTop && (data.offset.top = data.offsetTop)
+
+      $spy.affix(data)
+    })
+  })
+
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/doc/asset/js/bootstrap.min.js b/doc/asset/js/bootstrap.min.js
new file mode 100644
index 0000000..a5a55f7
--- /dev/null
+++ b/doc/asset/js/bootstrap.min.js
@@ -0,0 +1,6 @@
+/**
+* Bootstrap.js v2.3.1 by @fat & @mdo
+* Copyright 2012 Twitter, Inc.
+* http://www.apache.org/licenses/LICENSE-2.0.txt
+*/
+!function(e){"use strict";e(function(){e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()};var r=e.fn.alert;e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e.fn.alert.noConflict=function(){return e.fn.alert=r,this},e(document).on("click.alert.data-api",t,n.prototype.close)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")};var n=e.fn.button;e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e.fn.button.noConflict=function(){return e.fn.button=n,this},e(document).on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=n,this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(t){var n=this.getActiveIndex(),r=this;if(t>this.$items.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){r.to(t)}):n==t?this.pause().cycle():this.slide(t>n?"next":"prev",e(this.$items[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f;this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u](),f=e.Event("slide",{relatedTarget:i[0],direction:o});if(i.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var t=e(a.$indicators.children()[a.getActiveIndex()]);t&&t.addClass("active")}));if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}};var n=e.fn.carousel;e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.pause().cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e.fn.carousel.noConflict=function(){return e.fn.carousel=n,this},e(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=e.extend({},i.data(),n.data()),o;i.carousel(s),(o=n.attr("data-slide-to"))&&i.data("carousel").pause().to(o).cycle(),t.preventDefault()})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning||this.$element.hasClass("in"))return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning||!this.$element.hasClass("in"))return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var n=e.fn.collapse;e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=e.extend({},e.fn.collapse.defaults,r.data(),typeof n=="object"&&n);i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e.fn.collapse.noConflict=function(){return e.fn.collapse=n,this},e(document).on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})}(window.jQuery),!function(e){"use strict";function r(){e(t).each(function(){i(e(this)).removeClass("open")})}function i(t){var n=t.attr("data-target"),r;n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=n&&e(n);if(!r||!r.length)r=t.parent();return r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||s.toggleClass("open"),n.focus(),!1},keydown:function(n){var r,s,o,u,a,f;if(!/(38|40|27)/.test(n.keyCode))return;r=e(this),n.preventDefault(),n.stopPropagation();if(r.is(".disabled, :disabled"))return;u=i(r),a=u.hasClass("open");if(!a||a&&n.keyCode==27)return n.which==27&&u.find(t).focus(),r.click();s=e("[role=menu] li:not(.divider):visible a",u);if(!s.length)return;f=s.index(s.filter(":focus")),n.keyCode==38&&f>0&&f--,n.keyCode==40&&f<s.length-1&&f++,~f||(f=0),s.eq(f).focus()}};var s=e.fn.dropdown;e.fn.dropdown=function(t){return this.each(function(){var r=e(this),i=r.data("dropdown");i||r.data("dropdown",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.dropdown.Constructor=n,e.fn.dropdown.noConflict=function(){return e.fn.dropdown=s,this},e(document).on("click.dropdown.data-api",r).on("click.dropdown.data-api",".dropdown form",function(e){e.stopPropagation()}).on("click.dropdown-menu",function(e){e.stopPropagation()}).on("click.dropdown.data-api",t,n.prototype.toggle).on("keydown.dropdown.data-api",t+", [role=menu]",n.prototype.keydown)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=n,this.$element=e(t).delegate('[data-dismiss="modal"]',"click.dismiss.modal",e.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};t.prototype={constructor:t,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var t=this,n=e.Event("show");this.$element.trigger(n);if(this.isShown||n.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var n=e.support.transition&&t.$element.hasClass("fade");t.$element.parent().length||t.$element.appendTo(document.body),t.$element.show(),n&&t.$element[0].offsetWidth,t.$element.addClass("in").attr("aria-hidden",!1),t.enforceFocus(),n?t.$element.one(e.support.transition.end,function(){t.$element.focus().trigger("shown")}):t.$element.focus().trigger("shown")})},hide:function(t){t&&t.preventDefault();var n=this;t=e.Event("hide"),this.$element.trigger(t);if(!this.isShown||t.isDefaultPrevented())return;this.isShown=!1,this.escape(),e(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),e.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var t=this;e(document).on("focusin.modal",function(e){t.$element[0]!==e.target&&!t.$element.has(e.target).length&&t.$element.focus()})},escape:function(){var e=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(t){t.which==27&&e.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var t=this,n=setTimeout(function(){t.$element.off(e.support.transition.end),t.hideModal()},500);this.$element.one(e.support.transition.end,function(){clearTimeout(n),t.hideModal()})},hideModal:function(){var e=this;this.$element.hide(),this.backdrop(function(){e.removeBackdrop(),e.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},backdrop:function(t){var n=this,r=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var i=e.support.transition&&r;this.$backdrop=e('<div class="modal-backdrop '+r+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?e.proxy(this.$element[0].focus,this.$element[0]):e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!t)return;i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.transition.end,t):t()):t&&t()}};var n=e.fn.modal;e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e.fn.modal.noConflict=function(){return e.fn.modal=n,this},e(document).on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s,o,u,a;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,o=this.options.trigger.split(" ");for(a=o.length;a--;)u=o[a],u=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):u!="manual"&&(i=u=="hover"?"mouseenter":"focus",s=u=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this)));this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,this.$element.data(),t),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e.fn[this.type].defaults,r={},i;this._options&&e.each(this._options,function(e,t){n[e]!=t&&(r[e]=t)},this),i=e(t.currentTarget)[this.type](r).data(this.type);if(!i.options.delay||!i.options.delay.show)return i.show();clearTimeout(this.timeout),i.hoverState="in",this.timeout=setTimeout(function(){i.hoverState=="in"&&i.show()},i.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var t,n,r,i,s,o,u=e.Event("show");if(this.hasContent()&&this.enabled){this.$element.trigger(u);if(u.isDefaultPrevented())return;t=this.tip(),this.setContent(),this.options.animation&&t.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,t[0],this.$element[0]):this.options.placement,t.detach().css({top:0,left:0,display:"block"}),this.options.container?t.appendTo(this.options.container):t.insertAfter(this.$element),n=this.getPosition(),r=t[0].offsetWidth,i=t[0].offsetHeight;switch(s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}this.applyPlacement(o,s),this.$element.trigger("shown")}},applyPlacement:function(e,t){var n=this.tip(),r=n[0].offsetWidth,i=n[0].offsetHeight,s,o,u,a;n.offset(e).addClass(t).addClass("in"),s=n[0].offsetWidth,o=n[0].offsetHeight,t=="top"&&o!=i&&(e.top=e.top+i-o,a=!0),t=="bottom"||t=="top"?(u=0,e.left<0&&(u=e.left*-2,e.left=0,n.offset(e),s=n[0].offsetWidth,o=n[0].offsetHeight),this.replaceArrow(u-r+s,s,"left")):this.replaceArrow(o-i,o,"top"),a&&n.offset(e)},replaceArrow:function(e,t,n){this.arrow().css(n,e?50*(1-e/t)+"%":"")},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function i(){var t=setTimeout(function(){n.off(e.support.transition.end).detach()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.detach()})}var t=this,n=this.tip(),r=e.Event("hide");this.$element.trigger(r);if(r.isDefaultPrevented())return;return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?i():n.detach(),this.$element.trigger("hidden"),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").attr("title","")},hasContent:function(){return this.getTitle()},getPosition:function(){var t=this.$element[0];return e.extend({},typeof t.getBoundingClientRect=="function"?t.getBoundingClientRect():{width:t.offsetWidth,height:t.offsetHeight},this.$element.offset())},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},arrow:function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(t){var n=t?e(t.currentTarget)[this.type](this._options).data(this.type):this;n.tip().hasClass("in")?n.hide():n.show()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var n=e.fn.tooltip;e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},e.fn.tooltip.noConflict=function(){return e.fn.tooltip=n,this}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=(typeof n.content=="function"?n.content.call(t[0]):n.content)||t.attr("data-content"),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var n=e.fn.popover;e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),e.fn.popover.noConflict=function(){return e.fn.popover=n,this}}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var n=e(this),r=n.data("target")||n.attr("href"),i=/^#\w/.test(r)&&e(r);return i&&i.length&&[[i.position().top+(!e.isWindow(t.$scrollElement.get(0))&&t.$scrollElement.scrollTop()),r]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}};var n=e.fn.scrollspy;e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scrollspy.defaults={offset:10},e.fn.scrollspy.noConflict=function(){return e.fn.scrollspy=n,this},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active:last a")[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dropdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}};var n=e.fn.tab;e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e.fn.tab.noConflict=function(){return e.fn.tab=n,this},e(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=e(this.options.menu),this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:t.top+t.height,left:t.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(n=e.isFunction(this.source)?this.source(this.query,e.proxy(this.process,this)):this.source,n?this.process(n):this)},process:function(t){var n=this;return t=e.grep(t,function(e){return n.matcher(e)}),t=this.sorter(t),t.length?this.render(t.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(e){var t=[],n=[],r=[],i;while(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);return t.concat(n,r)},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return"<strong>"+t+"</strong>"})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("focus",e.proxy(this.focus,this)).on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this)).on("mouseleave","li",e.proxy(this.mouseleave,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},focus:function(e){this.focused=!0},blur:function(e){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(e){e.stopPropagation(),e.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(t){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")},mouseleave:function(e){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var n=e.fn.typeahead;e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)).on("click.affix.data-api",e.proxy(function(){setTimeout(e.proxy(this.checkPosition,this),1)},this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))};var n=e.fn.affix;e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e.fn.affix.noConflict=function(){return e.fn.affix=n,this},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery);
\ No newline at end of file
diff --git a/doc/asset/js/codemirror.js b/doc/asset/js/codemirror.js
new file mode 100644
index 0000000..87339d0
--- /dev/null
+++ b/doc/asset/js/codemirror.js
@@ -0,0 +1,5384 @@
+// CodeMirror version 3.1
+//
+// CodeMirror is the only global var we claim
+window.CodeMirror = (function() {
+  "use strict";
+
+  // BROWSER SNIFFING
+
+  // Crude, but necessary to handle a number of hard-to-feature-detect
+  // bugs and behavior differences.
+  var gecko = /gecko\/\d/i.test(navigator.userAgent);
+  var ie = /MSIE \d/.test(navigator.userAgent);
+  var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8);
+  var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
+  var webkit = /WebKit\//.test(navigator.userAgent);
+  var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
+  var chrome = /Chrome\//.test(navigator.userAgent);
+  var opera = /Opera\//.test(navigator.userAgent);
+  var safari = /Apple Computer/.test(navigator.vendor);
+  var khtml = /KHTML\//.test(navigator.userAgent);
+  var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
+  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
+  var phantom = /PhantomJS/.test(navigator.userAgent);
+
+  var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
+  // This is woefully incomplete. Suggestions for alternative methods welcome.
+  var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
+  var mac = ios || /Mac/.test(navigator.platform);
+  var windows = /windows/i.test(navigator.platform);
+
+  var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
+  if (opera_version) opera_version = Number(opera_version[1]);
+  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
+  var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
+  var captureMiddleClick = gecko || (ie && !ie_lt9);
+
+  // Optimize some code when these features are not used
+  var sawReadOnlySpans = false, sawCollapsedSpans = false;
+
+  // CONSTRUCTOR
+
+  function CodeMirror(place, options) {
+    if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
+    
+    this.options = options = options || {};
+    // Determine effective options based on given values and defaults.
+    for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
+      options[opt] = defaults[opt];
+    setGuttersForLineNumbers(options);
+
+    var docStart = typeof options.value == "string" ? 0 : options.value.first;
+    var display = this.display = makeDisplay(place, docStart);
+    display.wrapper.CodeMirror = this;
+    updateGutters(this);
+    if (options.autofocus && !mobile) focusInput(this);
+
+    this.state = {keyMaps: [],
+                  overlays: [],
+                  modeGen: 0,
+                  overwrite: false, focused: false,
+                  suppressEdits: false, pasteIncoming: false,
+                  draggingText: false,
+                  highlight: new Delayed()};
+
+    themeChanged(this);
+    if (options.lineWrapping)
+      this.display.wrapper.className += " CodeMirror-wrap";
+
+    var doc = options.value;
+    if (typeof doc == "string") doc = new Doc(options.value, options.mode);
+    operation(this, attachDoc)(this, doc);
+
+    // Override magic textarea content restore that IE sometimes does
+    // on our hidden textarea on reload
+    if (ie) setTimeout(bind(resetInput, this, true), 20);
+
+    registerEventHandlers(this);
+    // IE throws unspecified error in certain cases, when
+    // trying to access activeElement before onload
+    var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }
+    if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);
+    else onBlur(this);
+
+    operation(this, function() {
+      for (var opt in optionHandlers)
+        if (optionHandlers.propertyIsEnumerable(opt))
+          optionHandlers[opt](this, options[opt], Init);
+      for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
+    })();
+  }
+
+  // DISPLAY CONSTRUCTOR
+
+  function makeDisplay(place, docStart) {
+    var d = {};
+    var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none;");
+    if (webkit) input.style.width = "1000px";
+    else input.setAttribute("wrap", "off");
+    input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off");
+    // Wraps and hides input textarea
+    d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
+    // The actual fake scrollbars.
+    d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
+    d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
+    d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
+    // DIVs containing the selection and the actual code
+    d.lineDiv = elt("div");
+    d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
+    // Blinky cursor, and element used to ensure cursor fits at the end of a line
+    d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
+    // Secondary cursor, shown when on a 'jump' in bi-directional text
+    d.otherCursor = elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");
+    // Used to measure text size
+    d.measure = elt("div", null, "CodeMirror-measure");
+    // Wraps everything that needs to exist inside the vertically-padded coordinate system
+    d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],
+                         null, "position: relative; outline: none");
+    // Moved around its parent to cover visible view
+    d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
+    // Set to the height of the text, causes scrolling
+    d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
+    // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
+    d.heightForcer = elt("div", "\u00a0", null, "position: absolute; height: " + scrollerCutOff + "px");
+    // Will contain the gutters, if any
+    d.gutters = elt("div", null, "CodeMirror-gutters");
+    d.lineGutter = null;
+    // Helper element to properly size the gutter backgrounds
+    var scrollerInner = elt("div", [d.sizer, d.heightForcer, d.gutters], null, "position: relative; min-height: 100%");
+    // Provides scrolling
+    d.scroller = elt("div", [scrollerInner], "CodeMirror-scroll");
+    d.scroller.setAttribute("tabIndex", "-1");
+    // The element in which the editor lives.
+    d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
+                            d.scrollbarFiller, d.scroller], "CodeMirror");
+    // Work around IE7 z-index bug
+    if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
+    if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
+
+    // Needed to hide big blue blinking cursor on Mobile Safari
+    if (ios) input.style.width = "0px";
+    if (!webkit) d.scroller.draggable = true;
+    // Needed to handle Tab key in KHTML
+    if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
+    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
+    else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";
+
+    // Current visible range (may be bigger than the view window).
+    d.viewOffset = d.lastSizeC = 0;
+    d.showingFrom = d.showingTo = docStart;
+
+    // Used to only resize the line number gutter when necessary (when
+    // the amount of lines crosses a boundary that makes its width change)
+    d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
+    // See readInput and resetInput
+    d.prevInput = "";
+    // Set to true when a non-horizontal-scrolling widget is added. As
+    // an optimization, widget aligning is skipped when d is false.
+    d.alignWidgets = false;
+    // Flag that indicates whether we currently expect input to appear
+    // (after some event like 'keypress' or 'input') and are polling
+    // intensively.
+    d.pollingFast = false;
+    // Self-resetting timeout for the poller
+    d.poll = new Delayed();
+    // True when a drag from the editor is active
+    d.draggingText = false;
+
+    d.cachedCharWidth = d.cachedTextHeight = null;
+    d.measureLineCache = [];
+    d.measureLineCachePos = 0;
+
+    // Tracks when resetInput has punted to just putting a short
+    // string instead of the (large) selection.
+    d.inaccurateSelection = false;
+
+    // Tracks the maximum line length so that the horizontal scrollbar
+    // can be kept static when scrolling.
+    d.maxLine = null;
+    d.maxLineLength = 0;
+    d.maxLineChanged = false;
+
+    // Used for measuring wheel scrolling granularity
+    d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
+    
+    return d;
+  }
+
+  // STATE UPDATES
+
+  // Used to get the editor into a consistent state again when options change.
+
+  function loadMode(cm) {
+    cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
+    cm.doc.iter(function(line) {
+      if (line.stateAfter) line.stateAfter = null;
+      if (line.styles) line.styles = null;
+    });
+    cm.doc.frontier = cm.doc.first;
+    startWorker(cm, 100);
+    cm.state.modeGen++;
+    if (cm.curOp) regChange(cm);
+  }
+
+  function wrappingChanged(cm) {
+    if (cm.options.lineWrapping) {
+      cm.display.wrapper.className += " CodeMirror-wrap";
+      cm.display.sizer.style.minWidth = "";
+    } else {
+      cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
+      computeMaxLength(cm);
+    }
+    estimateLineHeights(cm);
+    regChange(cm);
+    clearCaches(cm);
+    setTimeout(function(){updateScrollbars(cm.display, cm.doc.height);}, 100);
+  }
+
+  function estimateHeight(cm) {
+    var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
+    var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
+    return function(line) {
+      if (lineIsHidden(cm.doc, line))
+        return 0;
+      else if (wrapping)
+        return (Math.ceil(line.text.length / perLine) || 1) * th;
+      else
+        return th;
+    };
+  }
+
+  function estimateLineHeights(cm) {
+    var doc = cm.doc, est = estimateHeight(cm);
+    doc.iter(function(line) {
+      var estHeight = est(line);
+      if (estHeight != line.height) updateLineHeight(line, estHeight);
+    });
+  }
+
+  function keyMapChanged(cm) {
+    var style = keyMap[cm.options.keyMap].style;
+    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
+      (style ? " cm-keymap-" + style : "");
+  }
+
+  function themeChanged(cm) {
+    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
+      cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
+    clearCaches(cm);
+  }
+
+  function guttersChanged(cm) {
+    updateGutters(cm);
+    regChange(cm);
+  }
+
+  function updateGutters(cm) {
+    var gutters = cm.display.gutters, specs = cm.options.gutters;
+    removeChildren(gutters);
+    for (var i = 0; i < specs.length; ++i) {
+      var gutterClass = specs[i];
+      var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
+      if (gutterClass == "CodeMirror-linenumbers") {
+        cm.display.lineGutter = gElt;
+        gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
+      }
+    }
+    gutters.style.display = i ? "" : "none";
+  }
+
+  function lineLength(doc, line) {
+    if (line.height == 0) return 0;
+    var len = line.text.length, merged, cur = line;
+    while (merged = collapsedSpanAtStart(cur)) {
+      var found = merged.find();
+      cur = getLine(doc, found.from.line);
+      len += found.from.ch - found.to.ch;
+    }
+    cur = line;
+    while (merged = collapsedSpanAtEnd(cur)) {
+      var found = merged.find();
+      len -= cur.text.length - found.from.ch;
+      cur = getLine(doc, found.to.line);
+      len += cur.text.length - found.to.ch;
+    }
+    return len;
+  }
+
+  function computeMaxLength(cm) {
+    var d = cm.display, doc = cm.doc;
+    d.maxLine = getLine(doc, doc.first);
+    d.maxLineLength = lineLength(doc, d.maxLine);
+    d.maxLineChanged = true;
+    doc.iter(function(line) {
+      var len = lineLength(doc, line);
+      if (len > d.maxLineLength) {
+        d.maxLineLength = len;
+        d.maxLine = line;
+      }
+    });
+  }
+
+  // Make sure the gutters options contains the element
+  // "CodeMirror-linenumbers" when the lineNumbers option is true.
+  function setGuttersForLineNumbers(options) {
+    var found = false;
+    for (var i = 0; i < options.gutters.length; ++i) {
+      if (options.gutters[i] == "CodeMirror-linenumbers") {
+        if (options.lineNumbers) found = true;
+        else options.gutters.splice(i--, 1);
+      }
+    }
+    if (!found && options.lineNumbers)
+      options.gutters.push("CodeMirror-linenumbers");
+  }
+
+  // SCROLLBARS
+
+  // Re-synchronize the fake scrollbars with the actual size of the
+  // content. Optionally force a scrollTop.
+  function updateScrollbars(d /* display */, docHeight) {
+    var totalHeight = docHeight + 2 * paddingTop(d);
+    d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
+    var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
+    var needsH = d.scroller.scrollWidth > d.scroller.clientWidth;
+    var needsV = scrollHeight > d.scroller.clientHeight;
+    if (needsV) {
+      d.scrollbarV.style.display = "block";
+      d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
+      d.scrollbarV.firstChild.style.height = 
+        (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
+    } else d.scrollbarV.style.display = "";
+    if (needsH) {
+      d.scrollbarH.style.display = "block";
+      d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
+      d.scrollbarH.firstChild.style.width =
+        (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
+    } else d.scrollbarH.style.display = "";
+    if (needsH && needsV) {
+      d.scrollbarFiller.style.display = "block";
+      d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
+    } else d.scrollbarFiller.style.display = "";
+
+    if (mac_geLion && scrollbarWidth(d.measure) === 0)
+      d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
+  }
+
+  function visibleLines(display, doc, viewPort) {
+    var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;
+    if (typeof viewPort == "number") top = viewPort;
+    else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}
+    top = Math.floor(top - paddingTop(display));
+    var bottom = Math.ceil(top + height);
+    return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};
+  }
+
+  // LINE NUMBERS
+
+  function alignHorizontally(cm) {
+    var display = cm.display;
+    if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
+    var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
+    var gutterW = display.gutters.offsetWidth, l = comp + "px";
+    for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
+      for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
+    }
+    if (cm.options.fixedGutter)
+      display.gutters.style.left = (comp + gutterW) + "px";
+  }
+
+  function maybeUpdateLineNumberWidth(cm) {
+    if (!cm.options.lineNumbers) return false;
+    var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
+    if (last.length != display.lineNumChars) {
+      var test = display.measure.appendChild(elt("div", [elt("div", last)],
+                                                 "CodeMirror-linenumber CodeMirror-gutter-elt"));
+      var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
+      display.lineGutter.style.width = "";
+      display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
+      display.lineNumWidth = display.lineNumInnerWidth + padding;
+      display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
+      display.lineGutter.style.width = display.lineNumWidth + "px";
+      return true;
+    }
+    return false;
+  }
+
+  function lineNumberFor(options, i) {
+    return String(options.lineNumberFormatter(i + options.firstLineNumber));
+  }
+  function compensateForHScroll(display) {
+    return getRect(display.scroller).left - getRect(display.sizer).left;
+  }
+
+  // DISPLAY DRAWING
+
+  function updateDisplay(cm, changes, viewPort) {
+    var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo;
+    var updated = updateDisplayInner(cm, changes, viewPort);
+    if (updated) {
+      signalLater(cm, "update", cm);
+      if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
+        signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
+    }
+    updateSelection(cm);
+    updateScrollbars(cm.display, cm.doc.height);
+
+    return updated;
+  }
+
+  // Uses a set of changes plus the current scroll position to
+  // determine which DOM updates have to be made, and makes the
+  // updates.
+  function updateDisplayInner(cm, changes, viewPort) {
+    var display = cm.display, doc = cm.doc;
+    if (!display.wrapper.clientWidth) {
+      display.showingFrom = display.showingTo = doc.first;
+      display.viewOffset = 0;
+      return;
+    }
+
+    // Compute the new visible window
+    // If scrollTop is specified, use that to determine which lines
+    // to render instead of the current scrollbar position.
+    var visible = visibleLines(display, doc, viewPort);
+    // Bail out if the visible area is already rendered and nothing changed.
+    if (changes.length == 0 &&
+        visible.from > display.showingFrom && visible.to < display.showingTo)
+      return;
+
+    if (maybeUpdateLineNumberWidth(cm))
+      changes = [{from: doc.first, to: doc.first + doc.size}];
+    var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px";
+    display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0";
+
+    // Used to determine which lines need their line numbers updated
+    var positionsChangedFrom = Infinity;
+    if (cm.options.lineNumbers)
+      for (var i = 0; i < changes.length; ++i)
+        if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
+
+    var end = doc.first + doc.size;
+    var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
+    var to = Math.min(end, visible.to + cm.options.viewportMargin);
+    if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);
+    if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);
+    if (sawCollapsedSpans) {
+      from = lineNo(visualLine(doc, getLine(doc, from)));
+      while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;
+    }
+
+    // Create a range of theoretically intact lines, and punch holes
+    // in that using the change info.
+    var intact = [{from: Math.max(display.showingFrom, doc.first),
+                   to: Math.min(display.showingTo, end)}];
+    if (intact[0].from >= intact[0].to) intact = [];
+    else intact = computeIntact(intact, changes);
+    // When merged lines are present, we might have to reduce the
+    // intact ranges because changes in continued fragments of the
+    // intact lines do require the lines to be redrawn.
+    if (sawCollapsedSpans)
+      for (var i = 0; i < intact.length; ++i) {
+        var range = intact[i], merged;
+        while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {
+          var newTo = merged.find().from.line;
+          if (newTo > range.from) range.to = newTo;
+          else { intact.splice(i--, 1); break; }
+        }
+      }
+
+    // Clip off the parts that won't be visible
+    var intactLines = 0;
+    for (var i = 0; i < intact.length; ++i) {
+      var range = intact[i];
+      if (range.from < from) range.from = from;
+      if (range.to > to) range.to = to;
+      if (range.from >= range.to) intact.splice(i--, 1);
+      else intactLines += range.to - range.from;
+    }
+    if (intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
+      updateViewOffset(cm);
+      return;
+    }
+    intact.sort(function(a, b) {return a.from - b.from;});
+
+    var focused = document.activeElement;
+    if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
+    patchDisplay(cm, from, to, intact, positionsChangedFrom);
+    display.lineDiv.style.display = "";
+    if (document.activeElement != focused && focused.offsetHeight) focused.focus();
+
+    var different = from != display.showingFrom || to != display.showingTo ||
+      display.lastSizeC != display.wrapper.clientHeight;
+    // This is just a bogus formula that detects when the editor is
+    // resized or the font size changes.
+    if (different) display.lastSizeC = display.wrapper.clientHeight;
+    display.showingFrom = from; display.showingTo = to;
+    startWorker(cm, 100);
+
+    var prevBottom = display.lineDiv.offsetTop;
+    for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
+      if (ie_lt8) {
+        var bot = node.offsetTop + node.offsetHeight;
+        height = bot - prevBottom;
+        prevBottom = bot;
+      } else {
+        var box = getRect(node);
+        height = box.bottom - box.top;
+      }
+      var diff = node.lineObj.height - height;
+      if (height < 2) height = textHeight(display);
+      if (diff > .001 || diff < -.001) {
+        updateLineHeight(node.lineObj, height);
+        var widgets = node.lineObj.widgets;
+        if (widgets) for (var i = 0; i < widgets.length; ++i)
+          widgets[i].height = widgets[i].node.offsetHeight;
+      }
+    }
+    updateViewOffset(cm);
+
+    if (visibleLines(display, doc, viewPort).to > to)
+      updateDisplayInner(cm, [], viewPort);
+    return true;
+  }
+
+  function updateViewOffset(cm) {
+    var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));
+    // Position the mover div to align with the current virtual scroll position
+    cm.display.mover.style.top = off + "px";
+  }
+
+  function computeIntact(intact, changes) {
+    for (var i = 0, l = changes.length || 0; i < l; ++i) {
+      var change = changes[i], intact2 = [], diff = change.diff || 0;
+      for (var j = 0, l2 = intact.length; j < l2; ++j) {
+        var range = intact[j];
+        if (change.to <= range.from && change.diff) {
+          intact2.push({from: range.from + diff, to: range.to + diff});
+        } else if (change.to <= range.from || change.from >= range.to) {
+          intact2.push(range);
+        } else {
+          if (change.from > range.from)
+            intact2.push({from: range.from, to: change.from});
+          if (change.to < range.to)
+            intact2.push({from: change.to + diff, to: range.to + diff});
+        }
+      }
+      intact = intact2;
+    }
+    return intact;
+  }
+
+  function getDimensions(cm) {
+    var d = cm.display, left = {}, width = {};
+    for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
+      left[cm.options.gutters[i]] = n.offsetLeft;
+      width[cm.options.gutters[i]] = n.offsetWidth;
+    }
+    return {fixedPos: compensateForHScroll(d),
+            gutterTotalWidth: d.gutters.offsetWidth,
+            gutterLeft: left,
+            gutterWidth: width,
+            wrapperWidth: d.wrapper.clientWidth};
+  }
+
+  function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
+    var dims = getDimensions(cm);
+    var display = cm.display, lineNumbers = cm.options.lineNumbers;
+    if (!intact.length && (!webkit || !cm.display.currentWheelTarget))
+      removeChildren(display.lineDiv);
+    var container = display.lineDiv, cur = container.firstChild;
+
+    function rm(node) {
+      var next = node.nextSibling;
+      if (webkit && mac && cm.display.currentWheelTarget == node) {
+        node.style.display = "none";
+        node.lineObj = null;
+      } else {
+        node.parentNode.removeChild(node);
+      }
+      return next;
+    }
+
+    var nextIntact = intact.shift(), lineN = from;
+    cm.doc.iter(from, to, function(line) {
+      if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
+      if (lineIsHidden(cm.doc, line)) {
+        if (line.height != 0) updateLineHeight(line, 0);
+        if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i)
+          if (line.widgets[i].showIfHidden) {
+            var prev = cur.previousSibling;
+            if (/pre/i.test(prev.nodeName)) {
+              var wrap = elt("div", null, null, "position: relative");
+              prev.parentNode.replaceChild(wrap, prev);
+              wrap.appendChild(prev);
+              prev = wrap;
+            }
+            var wnode = prev.appendChild(elt("div", [line.widgets[i].node], "CodeMirror-linewidget"));
+            positionLineWidget(line.widgets[i], wnode, prev, dims);
+          }
+      } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
+        // This line is intact. Skip to the actual node. Update its
+        // line number if needed.
+        while (cur.lineObj != line) cur = rm(cur);
+        if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)
+          setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));
+        cur = cur.nextSibling;
+      } else {
+        // For lines with widgets, make an attempt to find and reuse
+        // the existing element, so that widgets aren't needlessly
+        // removed and re-inserted into the dom
+        if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)
+          if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }
+        // This line needs to be generated.
+        var lineNode = buildLineElement(cm, line, lineN, dims, reuse);
+        if (lineNode != reuse) {
+          container.insertBefore(lineNode, cur);
+        } else {
+          while (cur != reuse) cur = rm(cur);
+          cur = cur.nextSibling;
+        }
+
+        lineNode.lineObj = line;
+      }
+      ++lineN;
+    });
+    while (cur) cur = rm(cur);
+  }
+
+  function buildLineElement(cm, line, lineNo, dims, reuse) {
+    var lineElement = lineContent(cm, line);
+    var markers = line.gutterMarkers, display = cm.display, wrap;
+
+    if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets)
+      return lineElement;
+
+    // Lines with gutter elements, widgets or a background class need
+    // to be wrapped again, and have the extra elements added to the
+    // wrapper div
+    
+    if (reuse) {
+      reuse.alignable = null;
+      var isOk = true, widgetsSeen = 0;
+      for (var n = reuse.firstChild, next; n; n = next) {
+        next = n.nextSibling;
+        if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
+          reuse.removeChild(n);
+        } else {
+          for (var i = 0, first = true; i < line.widgets.length; ++i) {
+            var widget = line.widgets[i], isFirst = false;
+            if (!widget.above) { isFirst = first; first = false; }
+            if (widget.node == n.firstChild) {
+              positionLineWidget(widget, n, reuse, dims);
+              ++widgetsSeen;
+              if (isFirst) reuse.insertBefore(lineElement, n);
+              break;
+            }
+          }
+          if (i == line.widgets.length) { isOk = false; break; }
+        }
+      }
+      if (isOk && widgetsSeen == line.widgets.length) {
+        wrap = reuse;
+        reuse.className = line.wrapClass || "";
+      }
+    }
+    if (!wrap) {
+      wrap = elt("div", null, line.wrapClass, "position: relative");
+      wrap.appendChild(lineElement);
+    }
+    // Kludge to make sure the styled element lies behind the selection (by z-index)
+    if (line.bgClass)
+      wrap.insertBefore(elt("div", "\u00a0", line.bgClass + " CodeMirror-linebackground"), wrap.firstChild);
+    if (cm.options.lineNumbers || markers) {
+      var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
+                                             (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
+                                         wrap.firstChild);
+      if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);
+      if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
+        wrap.lineNumber = gutterWrap.appendChild(
+          elt("div", lineNumberFor(cm.options, lineNo),
+              "CodeMirror-linenumber CodeMirror-gutter-elt",
+              "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
+              + display.lineNumInnerWidth + "px"));
+      if (markers)
+        for (var k = 0; k < cm.options.gutters.length; ++k) {
+          var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
+          if (found)
+            gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
+                                       dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
+        }
+    }
+    if (ie_lt8) wrap.style.zIndex = 2;
+    if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
+      var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
+      positionLineWidget(widget, node, wrap, dims);
+      if (widget.above)
+        wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
+      else
+        wrap.appendChild(node);
+      signalLater(widget, "redraw");
+    }
+    return wrap;
+  }
+
+  function positionLineWidget(widget, node, wrap, dims) {
+    if (widget.noHScroll) {
+      (wrap.alignable || (wrap.alignable = [])).push(node);
+      var width = dims.wrapperWidth;
+      node.style.left = dims.fixedPos + "px";
+      if (!widget.coverGutter) {
+        width -= dims.gutterTotalWidth;
+        node.style.paddingLeft = dims.gutterTotalWidth + "px";
+      }
+      node.style.width = width + "px";
+    }
+    if (widget.coverGutter) {
+      node.style.zIndex = 5;
+      node.style.position = "relative";
+      if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
+    }
+  }
+
+  // SELECTION / CURSOR
+
+  function updateSelection(cm) {
+    var display = cm.display;
+    var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);
+    if (collapsed || cm.options.showCursorWhenSelecting)
+      updateSelectionCursor(cm);
+    else
+      display.cursor.style.display = display.otherCursor.style.display = "none";
+    if (!collapsed)
+      updateSelectionRange(cm);
+    else
+      display.selectionDiv.style.display = "none";
+
+    // Move the hidden textarea near the cursor to prevent scrolling artifacts
+    var headPos = cursorCoords(cm, cm.doc.sel.head, "div");
+    var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);
+    display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
+                                                      headPos.top + lineOff.top - wrapOff.top)) + "px";
+    display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
+                                                       headPos.left + lineOff.left - wrapOff.left)) + "px";
+  }
+
+  // No selection, plain cursor
+  function updateSelectionCursor(cm) {
+    var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div");
+    display.cursor.style.left = pos.left + "px";
+    display.cursor.style.top = pos.top + "px";
+    display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
+    display.cursor.style.display = "";
+
+    if (pos.other) {
+      display.otherCursor.style.display = "";
+      display.otherCursor.style.left = pos.other.left + "px";
+      display.otherCursor.style.top = pos.other.top + "px";
+      display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
+    } else { display.otherCursor.style.display = "none"; }
+  }
+
+  // Highlight selection
+  function updateSelectionRange(cm) {
+    var display = cm.display, doc = cm.doc, sel = cm.doc.sel;
+    var fragment = document.createDocumentFragment();
+    var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);
+
+    function add(left, top, width, bottom) {
+      if (top < 0) top = 0;
+      fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
+                               "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) +
+                               "px; height: " + (bottom - top) + "px"));
+    }
+
+    function drawForLine(line, fromArg, toArg, retTop) {
+      var lineObj = getLine(doc, line);
+      var lineLen = lineObj.text.length, rVal = retTop ? Infinity : -Infinity;
+      function coords(ch) {
+        return charCoords(cm, Pos(line, ch), "div", lineObj);
+      }
+
+      iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
+        var leftPos = coords(dir == "rtl" ? to - 1 : from);
+        var rightPos = coords(dir == "rtl" ? from : to - 1);
+        var left = leftPos.left, right = rightPos.right;
+        if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
+          add(left, leftPos.top, null, leftPos.bottom);
+          left = pl;
+          if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
+        }
+        if (toArg == null && to == lineLen) right = clientWidth;
+        if (fromArg == null && from == 0) left = pl;
+        rVal = retTop ? Math.min(rightPos.top, rVal) : Math.max(rightPos.bottom, rVal);
+        if (left < pl + 1) left = pl;
+        add(left, rightPos.top, right - left, rightPos.bottom);
+      });
+      return rVal;
+    }
+
+    if (sel.from.line == sel.to.line) {
+      drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
+    } else {
+      var fromObj = getLine(doc, sel.from.line);
+      var cur = fromObj, merged, path = [sel.from.line, sel.from.ch], singleLine;
+      while (merged = collapsedSpanAtEnd(cur)) {
+        var found = merged.find();
+        path.push(found.from.ch, found.to.line, found.to.ch);
+        if (found.to.line == sel.to.line) {
+          path.push(sel.to.ch);
+          singleLine = true;
+          break;
+        }
+        cur = getLine(doc, found.to.line);
+      }
+
+      // This is a single, merged line
+      if (singleLine) {
+        for (var i = 0; i < path.length; i += 3)
+          drawForLine(path[i], path[i+1], path[i+2]);
+      } else {
+        var middleTop, middleBot, toObj = getLine(doc, sel.to.line);
+        if (sel.from.ch)
+          // Draw the first line of selection.
+          middleTop = drawForLine(sel.from.line, sel.from.ch, null, false);
+        else
+          // Simply include it in the middle block.
+          middleTop = heightAtLine(cm, fromObj) - display.viewOffset;
+
+        if (!sel.to.ch)
+          middleBot = heightAtLine(cm, toObj) - display.viewOffset;
+        else
+          middleBot = drawForLine(sel.to.line, collapsedSpanAtStart(toObj) ? null : 0, sel.to.ch, true);
+
+        if (middleTop < middleBot) add(pl, middleTop, null, middleBot);
+      }
+    }
+
+    removeChildrenAndAdd(display.selectionDiv, fragment);
+    display.selectionDiv.style.display = "";
+  }
+
+  // Cursor-blinking
+  function restartBlink(cm) {
+    var display = cm.display;
+    clearInterval(display.blinker);
+    var on = true;
+    display.cursor.style.visibility = display.otherCursor.style.visibility = "";
+    display.blinker = setInterval(function() {
+      if (!display.cursor.offsetHeight) return;
+      display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
+    }, cm.options.cursorBlinkRate);
+  }
+
+  // HIGHLIGHT WORKER
+
+  function startWorker(cm, time) {
+    if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)
+      cm.state.highlight.set(time, bind(highlightWorker, cm));
+  }
+
+  function highlightWorker(cm) {
+    var doc = cm.doc;
+    if (doc.frontier < doc.first) doc.frontier = doc.first;
+    if (doc.frontier >= cm.display.showingTo) return;
+    var end = +new Date + cm.options.workTime;
+    var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
+    var changed = [], prevChange;
+    doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
+      if (doc.frontier >= cm.display.showingFrom) { // Visible
+        var oldStyles = line.styles;
+        line.styles = highlightLine(cm, line, state);
+        var ischange = !oldStyles || oldStyles.length != line.styles.length;
+        for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
+        if (ischange) {
+          if (prevChange && prevChange.end == doc.frontier) prevChange.end++;
+          else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});
+        }
+        line.stateAfter = copyState(doc.mode, state);
+      } else {
+        processLine(cm, line, state);
+        line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
+      }
+      ++doc.frontier;
+      if (+new Date > end) {
+        startWorker(cm, cm.options.workDelay);
+        return true;
+      }
+    });
+    if (changed.length)
+      operation(cm, function() {
+        for (var i = 0; i < changed.length; ++i)
+          regChange(this, changed[i].start, changed[i].end);
+      })();
+  }
+
+  // Finds the line to start with when starting a parse. Tries to
+  // find a line with a stateAfter, so that it can start with a
+  // valid state. If that fails, it returns the line with the
+  // smallest indentation, which tends to need the least context to
+  // parse correctly.
+  function findStartLine(cm, n) {
+    var minindent, minline, doc = cm.doc;
+    for (var search = n, lim = n - 100; search > lim; --search) {
+      if (search <= doc.first) return doc.first;
+      var line = getLine(doc, search - 1);
+      if (line.stateAfter) return search;
+      var indented = countColumn(line.text, null, cm.options.tabSize);
+      if (minline == null || minindent > indented) {
+        minline = search - 1;
+        minindent = indented;
+      }
+    }
+    return minline;
+  }
+
+  function getStateBefore(cm, n) {
+    var doc = cm.doc, display = cm.display;
+      if (!doc.mode.startState) return true;
+    var pos = findStartLine(cm, n), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
+    if (!state) state = startState(doc.mode);
+    else state = copyState(doc.mode, state);
+    doc.iter(pos, n, function(line) {
+      processLine(cm, line, state);
+      var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;
+      line.stateAfter = save ? copyState(doc.mode, state) : null;
+      ++pos;
+    });
+    return state;
+  }
+
+  // POSITION MEASUREMENT
+  
+  function paddingTop(display) {return display.lineSpace.offsetTop;}
+  function paddingLeft(display) {
+    var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x"));
+    return e.offsetLeft;
+  }
+
+  function measureChar(cm, line, ch, data) {
+    var dir = -1;
+    data = data || measureLine(cm, line);
+    
+    for (var pos = ch;; pos += dir) {
+      var r = data[pos];
+      if (r) break;
+      if (dir < 0 && pos == 0) dir = 1;
+    }
+    return {left: pos < ch ? r.right : r.left,
+            right: pos > ch ? r.left : r.right,
+            top: r.top, bottom: r.bottom};
+  }
+
+  function measureLine(cm, line) {
+    // First look in the cache
+    var display = cm.display, cache = cm.display.measureLineCache;
+    for (var i = 0; i < cache.length; ++i) {
+      var memo = cache[i];
+      if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
+          display.scroller.clientWidth == memo.width &&
+          memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
+        return memo.measure;
+    }
+    
+    var measure = measureLineInner(cm, line);
+    // Store result in the cache
+    var memo = {text: line.text, width: display.scroller.clientWidth,
+                markedSpans: line.markedSpans, measure: measure,
+                classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
+    if (cache.length == 16) cache[++display.measureLineCachePos % 16] = memo;
+    else cache.push(memo);
+    return measure;
+  }
+
+  function measureLineInner(cm, line) {
+    var display = cm.display, measure = emptyArray(line.text.length);
+    var pre = lineContent(cm, line, measure);
+
+    // IE does not cache element positions of inline elements between
+    // calls to getBoundingClientRect. This makes the loop below,
+    // which gathers the positions of all the characters on the line,
+    // do an amount of layout work quadratic to the number of
+    // characters. When line wrapping is off, we try to improve things
+    // by first subdividing the line into a bunch of inline blocks, so
+    // that IE can reuse most of the layout information from caches
+    // for those blocks. This does interfere with line wrapping, so it
+    // doesn't work when wrapping is on, but in that case the
+    // situation is slightly better, since IE does cache line-wrapping
+    // information and only recomputes per-line.
+    if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
+      var fragment = document.createDocumentFragment();
+      var chunk = 10, n = pre.childNodes.length;
+      for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
+        var wrap = elt("div", null, null, "display: inline-block");
+        for (var j = 0; j < chunk && n; ++j) {
+          wrap.appendChild(pre.firstChild);
+          --n;
+        }
+        fragment.appendChild(wrap);
+      }
+      pre.appendChild(fragment);
+    }
+
+    removeChildrenAndAdd(display.measure, pre);
+
+    var outer = getRect(display.lineDiv);
+    var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
+    // Work around an IE7/8 bug where it will sometimes have randomly
+    // replaced our pre with a clone at this point.
+    if (ie_lt9 && display.measure.first != pre)
+      removeChildrenAndAdd(display.measure, pre);
+
+    for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
+      var size = getRect(cur);
+      var top = Math.max(0, size.top - outer.top), bot = Math.min(size.bottom - outer.top, maxBot);
+      for (var j = 0; j < vranges.length; j += 2) {
+        var rtop = vranges[j], rbot = vranges[j+1];
+        if (rtop > bot || rbot < top) continue;
+        if (rtop <= top && rbot >= bot ||
+            top <= rtop && bot >= rbot ||
+            Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
+          vranges[j] = Math.min(top, rtop);
+          vranges[j+1] = Math.max(bot, rbot);
+          break;
+        }
+      }
+      if (j == vranges.length) vranges.push(top, bot);
+      var right = size.right;
+      if (cur.measureRight) right = getRect(cur.measureRight).left;
+      data[i] = {left: size.left - outer.left, right: right - outer.left, top: j};
+    }
+    for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
+      var vr = cur.top;
+      cur.top = vranges[vr]; cur.bottom = vranges[vr+1];
+    }
+    if (!cm.options.lineWrapping) {
+      var last = pre.lastChild;
+      if (last.nodeType == 3) last = pre.appendChild(elt("span", "\u200b"));
+      data.width = getRect(last).right - outer.left;
+    }
+
+    return data;
+  }
+
+  function clearCaches(cm) {
+    cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
+    cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
+    cm.display.maxLineChanged = true;
+    cm.display.lineNumChars = null;
+  }
+
+  // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
+  function intoCoordSystem(cm, lineObj, rect, context) {
+    if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
+      var size = widgetHeight(lineObj.widgets[i]);
+      rect.top += size; rect.bottom += size;
+    }
+    if (context == "line") return rect;
+    if (!context) context = "local";
+    var yOff = heightAtLine(cm, lineObj);
+    if (context != "local") yOff -= cm.display.viewOffset;
+    if (context == "page") {
+      var lOff = getRect(cm.display.lineSpace);
+      yOff += lOff.top + (window.pageYOffset || (document.documentElement || document.body).scrollTop);
+      var xOff = lOff.left + (window.pageXOffset || (document.documentElement || document.body).scrollLeft);
+      rect.left += xOff; rect.right += xOff;
+    }
+    rect.top += yOff; rect.bottom += yOff;
+    return rect;
+  }
+
+  function charCoords(cm, pos, context, lineObj) {
+    if (!lineObj) lineObj = getLine(cm.doc, pos.line);
+    return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch), context);
+  }
+
+  function cursorCoords(cm, pos, context, lineObj, measurement) {
+    lineObj = lineObj || getLine(cm.doc, pos.line);
+    if (!measurement) measurement = measureLine(cm, lineObj);
+    function get(ch, right) {
+      var m = measureChar(cm, lineObj, ch, measurement);
+      if (right) m.left = m.right; else m.right = m.left;
+      return intoCoordSystem(cm, lineObj, m, context);
+    }
+    var order = getOrder(lineObj), ch = pos.ch;
+    if (!order) return get(ch);
+    var main, other, linedir = order[0].level;
+    for (var i = 0; i < order.length; ++i) {
+      var part = order[i], rtl = part.level % 2, nb, here;
+      if (part.from < ch && part.to > ch) return get(ch, rtl);
+      var left = rtl ? part.to : part.from, right = rtl ? part.from : part.to;
+      if (left == ch) {
+        // IE returns bogus offsets and widths for edges where the
+        // direction flips, but only for the side with the lower
+        // level. So we try to use the side with the higher level.
+        if (i && part.level < (nb = order[i-1]).level) here = get(nb.level % 2 ? nb.from : nb.to - 1, true);
+        else here = get(rtl && part.from != part.to ? ch - 1 : ch);
+        if (rtl == linedir) main = here; else other = here;
+      } else if (right == ch) {
+        var nb = i < order.length - 1 && order[i+1];
+        if (!rtl && nb && nb.from == nb.to) continue;
+        if (nb && part.level < nb.level) here = get(nb.level % 2 ? nb.to - 1 : nb.from);
+        else here = get(rtl ? ch : ch - 1, true);
+        if (rtl == linedir) main = here; else other = here;
+      }
+    }
+    if (linedir && !ch) other = get(order[0].to - 1);
+    if (!main) return other;
+    if (other) main.other = other;
+    return main;
+  }
+
+  function PosMaybeOutside(line, ch, outside) {
+    var pos = new Pos(line, ch);
+    if (outside) pos.outside = true;
+    return pos;
+  }
+
+  // Coords must be lineSpace-local
+  function coordsChar(cm, x, y) {
+    var doc = cm.doc;
+    y += cm.display.viewOffset;
+    if (y < 0) return PosMaybeOutside(doc.first, 0, true);
+    var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
+    if (lineNo > last)
+      return PosMaybeOutside(doc.first + doc.size - 1, getLine(doc, last).text.length, true);
+    if (x < 0) x = 0;
+
+    for (;;) {
+      var lineObj = getLine(doc, lineNo);
+      var found = coordsCharInner(cm, lineObj, lineNo, x, y);
+      var merged = collapsedSpanAtEnd(lineObj);
+      var mergedPos = merged && merged.find();
+      if (merged && found.ch >= mergedPos.from.ch)
+        lineNo = mergedPos.to.line;
+      else
+        return found;
+    }
+  }
+
+  function coordsCharInner(cm, lineObj, lineNo, x, y) {
+    var innerOff = y - heightAtLine(cm, lineObj);
+    var wrongLine = false, cWidth = cm.display.wrapper.clientWidth;
+    var measurement = measureLine(cm, lineObj);
+
+    function getX(ch) {
+      var sp = cursorCoords(cm, Pos(lineNo, ch), "line",
+                            lineObj, measurement);
+      wrongLine = true;
+      if (innerOff > sp.bottom) return Math.max(0, sp.left - cWidth);
+      else if (innerOff < sp.top) return sp.left + cWidth;
+      else wrongLine = false;
+      return sp.left;
+    }
+
+    var bidi = getOrder(lineObj), dist = lineObj.text.length;
+    var from = lineLeft(lineObj), to = lineRight(lineObj);
+    var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
+
+    if (x > toX) return PosMaybeOutside(lineNo, to, toOutside);
+    // Do a binary search between these bounds.
+    for (;;) {
+      if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
+        var after = x - fromX < toX - x, ch = after ? from : to;
+        while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
+        var pos = PosMaybeOutside(lineNo, ch, after ? fromOutside : toOutside);
+        pos.after = after;
+        return pos;
+      }
+      var step = Math.ceil(dist / 2), middle = from + step;
+      if (bidi) {
+        middle = from;
+        for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
+      }
+      var middleX = getX(middle);
+      if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist -= step;}
+      else {from = middle; fromX = middleX; fromOutside = wrongLine; dist = step;}
+    }
+  }
+
+  var measureText;
+  function textHeight(display) {
+    if (display.cachedTextHeight != null) return display.cachedTextHeight;
+    if (measureText == null) {
+      measureText = elt("pre");
+      // Measure a bunch of lines, for browsers that compute
+      // fractional heights.
+      for (var i = 0; i < 49; ++i) {
+        measureText.appendChild(document.createTextNode("x"));
+        measureText.appendChild(elt("br"));
+      }
+      measureText.appendChild(document.createTextNode("x"));
+    }
+    removeChildrenAndAdd(display.measure, measureText);
+    var height = measureText.offsetHeight / 50;
+    if (height > 3) display.cachedTextHeight = height;
+    removeChildren(display.measure);
+    return height || 1;
+  }
+
+  function charWidth(display) {
+    if (display.cachedCharWidth != null) return display.cachedCharWidth;
+    var anchor = elt("span", "x");
+    var pre = elt("pre", [anchor]);
+    removeChildrenAndAdd(display.measure, pre);
+    var width = anchor.offsetWidth;
+    if (width > 2) display.cachedCharWidth = width;
+    return width || 10;
+  }
+
+  // OPERATIONS
+
+  // Operations are used to wrap changes in such a way that each
+  // change won't have to update the cursor and display (which would
+  // be awkward, slow, and error-prone), but instead updates are
+  // batched and then all combined and executed at once.
+
+  var nextOpId = 0;
+  function startOperation(cm) {
+    cm.curOp = {
+      // An array of ranges of lines that have to be updated. See
+      // updateDisplay.
+      changes: [],
+      updateInput: null,
+      userSelChange: null,
+      textChanged: null,
+      selectionChanged: false,
+      updateMaxLine: false,
+      updateScrollPos: false,
+      id: ++nextOpId
+    };
+    if (!delayedCallbackDepth++) delayedCallbacks = [];
+  }
+
+  function endOperation(cm) {
+    var op = cm.curOp, doc = cm.doc, display = cm.display;
+    cm.curOp = null;
+
+    if (op.updateMaxLine) computeMaxLength(cm);
+    if (display.maxLineChanged && !cm.options.lineWrapping) {
+      var width = measureLine(cm, display.maxLine).width;
+      display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px";
+      display.maxLineChanged = false;
+      var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);
+      if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)
+        setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
+    }
+    var newScrollPos, updated;
+    if (op.updateScrollPos) {
+      newScrollPos = op.updateScrollPos;
+    } else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible
+      var coords = cursorCoords(cm, doc.sel.head);
+      newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
+    }
+    if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null)
+      updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop);
+    if (!updated && op.selectionChanged) updateSelection(cm);
+    if (op.updateScrollPos) {
+      display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
+      display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
+      alignHorizontally(cm);
+    } else if (newScrollPos) {
+      scrollCursorIntoView(cm);
+    }
+    if (op.selectionChanged) restartBlink(cm);
+
+    if (cm.state.focused && op.updateInput)
+      resetInput(cm, op.userSelChange);
+
+    var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
+    if (hidden) for (var i = 0; i < hidden.length; ++i)
+      if (!hidden[i].lines.length) signal(hidden[i], "hide");
+    if (unhidden) for (var i = 0; i < unhidden.length; ++i)
+      if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
+
+    var delayed;
+    if (!--delayedCallbackDepth) {
+      delayed = delayedCallbacks;
+      delayedCallbacks = null;
+    }
+    if (op.textChanged)
+      signal(cm, "change", cm, op.textChanged);
+    if (op.selectionChanged) signal(cm, "cursorActivity", cm);
+    if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
+  }
+
+  // Wraps a function in an operation. Returns the wrapped function.
+  function operation(cm1, f) {
+    return function() {
+      var cm = cm1 || this, withOp = !cm.curOp;
+      if (withOp) startOperation(cm);
+      try { var result = f.apply(cm, arguments); }
+      finally { if (withOp) endOperation(cm); }
+      return result;
+    };
+  }
+  function docOperation(f) {
+    return function() {
+      var withOp = this.cm && !this.cm.curOp, result;
+      if (withOp) startOperation(this.cm);
+      try { result = f.apply(this, arguments); }
+      finally { if (withOp) endOperation(this.cm); }
+      return result;
+    };
+  }
+  function runInOp(cm, f) {
+    var withOp = !cm.curOp, result;
+    if (withOp) startOperation(cm);
+    try { result = f(); }
+    finally { if (withOp) endOperation(cm); }
+    return result;
+  }
+
+  function regChange(cm, from, to, lendiff) {
+    if (from == null) from = cm.doc.first;
+    if (to == null) to = cm.doc.first + cm.doc.size;
+    cm.curOp.changes.push({from: from, to: to, diff: lendiff});
+  }
+
+  // INPUT HANDLING
+
+  function slowPoll(cm) {
+    if (cm.display.pollingFast) return;
+    cm.display.poll.set(cm.options.pollInterval, function() {
+      readInput(cm);
+      if (cm.state.focused) slowPoll(cm);
+    });
+  }
+
+  function fastPoll(cm) {
+    var missed = false;
+    cm.display.pollingFast = true;
+    function p() {
+      var changed = readInput(cm);
+      if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
+      else {cm.display.pollingFast = false; slowPoll(cm);}
+    }
+    cm.display.poll.set(20, p);
+  }
+
+  // prevInput is a hack to work with IME. If we reset the textarea
+  // on every change, that breaks IME. So we look for changes
+  // compared to the previous content instead. (Modern browsers have
+  // events that indicate IME taking place, but these are not widely
+  // supported or compatible enough yet to rely on.)
+  function readInput(cm) {
+    var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
+    if (!cm.state.focused || hasSelection(input) || isReadOnly(cm)) return false;
+    var text = input.value;
+    if (text == prevInput && posEq(sel.from, sel.to)) return false;
+    // IE enjoys randomly deselecting our input's text when
+    // re-focusing. If the selection is gone but the cursor is at the
+    // start of the input, that's probably what happened.
+    if (ie && text && input.selectionStart === 0) {
+      resetInput(cm, true);
+      return false;
+    }
+    var withOp = !cm.curOp;
+    if (withOp) startOperation(cm);
+    sel.shift = false;
+    var same = 0, l = Math.min(prevInput.length, text.length);
+    while (same < l && prevInput[same] == text[same]) ++same;
+    var from = sel.from, to = sel.to;
+    if (same < prevInput.length)
+      from = Pos(from.line, from.ch - (prevInput.length - same));
+    else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
+      to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
+    var updateInput = cm.curOp.updateInput;
+    makeChange(cm.doc, {from: from, to: to, text: splitLines(text.slice(same)),
+                        origin: cm.state.pasteIncoming ? "paste" : "+input"}, "end");
+               
+    cm.curOp.updateInput = updateInput;
+    if (text.length > 1000) input.value = cm.display.prevInput = "";
+    else cm.display.prevInput = text;
+    if (withOp) endOperation(cm);
+    cm.state.pasteIncoming = false;
+    return true;
+  }
+
+  function resetInput(cm, user) {
+    var minimal, selected, doc = cm.doc;
+    if (!posEq(doc.sel.from, doc.sel.to)) {
+      cm.display.prevInput = "";
+      minimal = hasCopyEvent &&
+        (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
+      if (minimal) cm.display.input.value = "-";
+      else cm.display.input.value = selected || cm.getSelection();
+      if (cm.state.focused) selectInput(cm.display.input);
+    } else if (user) cm.display.prevInput = cm.display.input.value = "";
+    cm.display.inaccurateSelection = minimal;
+  }
+
+  function focusInput(cm) {
+    if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input))
+      cm.display.input.focus();
+  }
+
+  function isReadOnly(cm) {
+    return cm.options.readOnly || cm.doc.cantEdit;
+  }
+
+  // EVENT HANDLERS
+
+  function registerEventHandlers(cm) {
+    var d = cm.display;
+    on(d.scroller, "mousedown", operation(cm, onMouseDown));
+    on(d.scroller, "dblclick", operation(cm, e_preventDefault));
+    on(d.lineSpace, "selectstart", function(e) {
+      if (!eventInWidget(d, e)) e_preventDefault(e);
+    });
+    // Gecko browsers fire contextmenu *after* opening the menu, at
+    // which point we can't mess with it anymore. Context menu is
+    // handled in onMouseDown for Gecko.
+    if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
+
+    on(d.scroller, "scroll", function() {
+      setScrollTop(cm, d.scroller.scrollTop);
+      setScrollLeft(cm, d.scroller.scrollLeft, true);
+      signal(cm, "scroll", cm);
+    });
+    on(d.scrollbarV, "scroll", function() {
+      setScrollTop(cm, d.scrollbarV.scrollTop);
+    });
+    on(d.scrollbarH, "scroll", function() {
+      setScrollLeft(cm, d.scrollbarH.scrollLeft);
+    });
+
+    on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
+    on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
+
+    function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
+    on(d.scrollbarH, "mousedown", reFocus);
+    on(d.scrollbarV, "mousedown", reFocus);
+    // Prevent wrapper from ever scrolling
+    on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
+
+    function onResize() {
+      // Might be a text scaling operation, clear size caches.
+      d.cachedCharWidth = d.cachedTextHeight = null;
+      clearCaches(cm);
+      runInOp(cm, bind(regChange, cm));
+    }
+    on(window, "resize", onResize);
+    // Above handler holds on to the editor and its data structures.
+    // Here we poll to unregister it when the editor is no longer in
+    // the document, so that it can be garbage-collected.
+    function unregister() {
+      for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}
+      if (p) setTimeout(unregister, 5000);
+      else off(window, "resize", onResize);
+    }    
+    setTimeout(unregister, 5000);
+
+    on(d.input, "keyup", operation(cm, function(e) {
+      if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+      if (e.keyCode == 16) cm.doc.sel.shift = false;
+    }));
+    on(d.input, "input", bind(fastPoll, cm));
+    on(d.input, "keydown", operation(cm, onKeyDown));
+    on(d.input, "keypress", operation(cm, onKeyPress));
+    on(d.input, "focus", bind(onFocus, cm));
+    on(d.input, "blur", bind(onBlur, cm));
+
+    function drag_(e) {
+      if (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
+      e_stop(e);
+    }
+    if (cm.options.dragDrop) {
+      on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
+      on(d.scroller, "dragenter", drag_);
+      on(d.scroller, "dragover", drag_);
+      on(d.scroller, "drop", operation(cm, onDrop));
+    }
+    on(d.scroller, "paste", function(e){
+      if (eventInWidget(d, e)) return;
+      focusInput(cm); 
+      fastPoll(cm);
+    });
+    on(d.input, "paste", function() {
+      cm.state.pasteIncoming = true;
+      fastPoll(cm);
+    });
+
+    function prepareCopy() {
+      if (d.inaccurateSelection) {
+        d.prevInput = "";
+        d.inaccurateSelection = false;
+        d.input.value = cm.getSelection();
+        selectInput(d.input);
+      }
+    }
+    on(d.input, "cut", prepareCopy);
+    on(d.input, "copy", prepareCopy);
+
+    // Needed to handle Tab key in KHTML
+    if (khtml) on(d.sizer, "mouseup", function() {
+        if (document.activeElement == d.input) d.input.blur();
+        focusInput(cm);
+    });
+  }
+
+  function eventInWidget(display, e) {
+    for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
+      if (!n) return true;
+      if (/\bCodeMirror-(?:line)?widget\b/.test(n.className) ||
+          n.parentNode == display.sizer && n != display.mover) return true;
+    }
+  }
+
+  function posFromMouse(cm, e, liberal) {
+    var display = cm.display;
+    if (!liberal) {
+      var target = e_target(e);
+      if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
+          target == display.scrollbarV || target == display.scrollbarV.firstChild ||
+          target == display.scrollbarFiller) return null;
+    }
+    var x, y, space = getRect(display.lineSpace);
+    // Fails unpredictably on IE[67] when mouse is dragged around quickly.
+    try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
+    return coordsChar(cm, x - space.left, y - space.top);
+  }
+
+  var lastClick, lastDoubleClick;
+  function onMouseDown(e) {
+    var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
+    sel.shift = e.shiftKey;
+
+    if (eventInWidget(display, e)) {
+      if (!webkit) {
+        display.scroller.draggable = false;
+        setTimeout(function(){display.scroller.draggable = true;}, 100);
+      }
+      return;
+    }
+    if (clickInGutter(cm, e)) return;
+    var start = posFromMouse(cm, e);
+
+    switch (e_button(e)) {
+    case 3:
+      if (captureMiddleClick) onContextMenu.call(cm, cm, e);
+      return;
+    case 2:
+      if (start) extendSelection(cm.doc, start);
+      setTimeout(bind(focusInput, cm), 20);
+      e_preventDefault(e);
+      return;
+    }
+    // For button 1, if it was clicked inside the editor
+    // (posFromMouse returning non-null), we have to adjust the
+    // selection.
+    if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}
+
+    if (!cm.state.focused) onFocus(cm);
+
+    var now = +new Date, type = "single";
+    if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
+      type = "triple";
+      e_preventDefault(e);
+      setTimeout(bind(focusInput, cm), 20);
+      selectLine(cm, start.line);
+    } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
+      type = "double";
+      lastDoubleClick = {time: now, pos: start};
+      e_preventDefault(e);
+      var word = findWordAt(getLine(doc, start.line).text, start);
+      extendSelection(cm.doc, word.from, word.to);
+    } else { lastClick = {time: now, pos: start}; }
+
+    var last = start;
+    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&
+        !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
+      var dragEnd = operation(cm, function(e2) {
+        if (webkit) display.scroller.draggable = false;
+        cm.state.draggingText = false;
+        off(document, "mouseup", dragEnd);
+        off(display.scroller, "drop", dragEnd);
+        if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
+          e_preventDefault(e2);
+          extendSelection(cm.doc, start);
+          focusInput(cm);
+        }
+      });
+      // Let the drag handler handle this.
+      if (webkit) display.scroller.draggable = true;
+      cm.state.draggingText = dragEnd;
+      // IE's approach to draggable
+      if (display.scroller.dragDrop) display.scroller.dragDrop();
+      on(document, "mouseup", dragEnd);
+      on(display.scroller, "drop", dragEnd);
+      return;
+    }
+    e_preventDefault(e);
+    if (type == "single") extendSelection(cm.doc, clipPos(doc, start));
+
+    var startstart = sel.from, startend = sel.to;
+
+    function doSelect(cur) {
+      if (type == "single") {
+        extendSelection(cm.doc, clipPos(doc, start), cur);
+        return;
+      }
+
+      startstart = clipPos(doc, startstart);
+      startend = clipPos(doc, startend);
+      if (type == "double") {
+        var word = findWordAt(getLine(doc, cur.line).text, cur);
+        if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);
+        else extendSelection(cm.doc, startstart, word.to);
+      } else if (type == "triple") {
+        if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));
+        else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));
+      }
+    }
+
+    var editorSize = getRect(display.wrapper);
+    // Used to ensure timeout re-tries don't fire when another extend
+    // happened in the meantime (clearTimeout isn't reliable -- at
+    // least on Chrome, the timeouts still happen even when cleared,
+    // if the clear happens after their scheduled firing time).
+    var counter = 0;
+
+    function extend(e) {
+      var curCount = ++counter;
+      var cur = posFromMouse(cm, e, true);
+      if (!cur) return;
+      if (!posEq(cur, last)) {
+        if (!cm.state.focused) onFocus(cm);
+        last = cur;
+        doSelect(cur);
+        var visible = visibleLines(display, doc);
+        if (cur.line >= visible.to || cur.line < visible.from)
+          setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
+      } else {
+        var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
+        if (outside) setTimeout(operation(cm, function() {
+          if (counter != curCount) return;
+          display.scroller.scrollTop += outside;
+          extend(e);
+        }), 50);
+      }
+    }
+
+    function done(e) {
+      counter = Infinity;
+      var cur = posFromMouse(cm, e);
+      if (cur) doSelect(cur);
+      e_preventDefault(e);
+      focusInput(cm);
+      off(document, "mousemove", move);
+      off(document, "mouseup", up);
+    }
+
+    var move = operation(cm, function(e) {
+      if (!ie && !e_button(e)) done(e);
+      else extend(e);
+    });
+    var up = operation(cm, done);
+    on(document, "mousemove", move);
+    on(document, "mouseup", up);
+  }
+
+  function onDrop(e) {
+    var cm = this;
+    if (eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
+      return;
+    e_preventDefault(e);
+    var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
+    if (!pos || isReadOnly(cm)) return;
+    if (files && files.length && window.FileReader && window.File) {
+      var n = files.length, text = Array(n), read = 0;
+      var loadFile = function(file, i) {
+        var reader = new FileReader;
+        reader.onload = function() {
+          text[i] = reader.result;
+          if (++read == n) {
+            pos = clipPos(cm.doc, pos);
+            replaceRange(cm.doc, text.join(""), pos, "around", "paste");
+          }
+        };
+        reader.readAsText(file);
+      };
+      for (var i = 0; i < n; ++i) loadFile(files[i], i);
+    } else {
+      // Don't do a replace if the drop happened inside of the selected text.
+      if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {
+        cm.state.draggingText(e);
+        // Ensure the editor is re-focused
+        setTimeout(bind(focusInput, cm), 20);
+        return;
+      }
+      try {
+        var text = e.dataTransfer.getData("Text");
+        if (text) {
+          var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;
+          setSelection(cm.doc, pos, pos);
+          if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");
+          cm.replaceSelection(text, null, "paste");
+          focusInput(cm);
+          onFocus(cm);
+        }
+      }
+      catch(e){}
+    }
+  }
+
+  function clickInGutter(cm, e) {
+    var display = cm.display;
+    try { var mX = e.clientX, mY = e.clientY; }
+    catch(e) { return false; }
+
+    if (mX >= Math.floor(getRect(display.gutters).right)) return false;
+    e_preventDefault(e);
+    if (!hasHandler(cm, "gutterClick")) return true;
+
+    var lineBox = getRect(display.lineDiv);
+    if (mY > lineBox.bottom) return true;
+    mY -= lineBox.top - display.viewOffset;
+
+    for (var i = 0; i < cm.options.gutters.length; ++i) {
+      var g = display.gutters.childNodes[i];
+      if (g && getRect(g).right >= mX) {
+        var line = lineAtHeight(cm.doc, mY);
+        var gutter = cm.options.gutters[i];
+        signalLater(cm, "gutterClick", cm, line, gutter, e);
+        break;
+      }
+    }
+    return true;
+  }
+
+  function onDragStart(cm, e) {
+    if (eventInWidget(cm.display, e)) return;
+    
+    var txt = cm.getSelection();
+    e.dataTransfer.setData("Text", txt);
+
+    // Use dummy image instead of default browsers image.
+    // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
+    if (e.dataTransfer.setDragImage && !safari) {
+      var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
+      if (opera) {
+        img.width = img.height = 1;
+        cm.display.wrapper.appendChild(img);
+        // Force a relayout, or Opera won't use our image for some obscure reason
+        img._top = img.offsetTop;
+      }
+      e.dataTransfer.setDragImage(img, 0, 0);
+      if (opera) img.parentNode.removeChild(img);
+    }
+  }
+
+  function setScrollTop(cm, val) {
+    if (Math.abs(cm.doc.scrollTop - val) < 2) return;
+    cm.doc.scrollTop = val;
+    if (!gecko) updateDisplay(cm, [], val);
+    if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
+    if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
+    if (gecko) updateDisplay(cm, []);
+  }
+  function setScrollLeft(cm, val, isScroller) {
+    if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
+    val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
+    cm.doc.scrollLeft = val;
+    alignHorizontally(cm);
+    if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
+    if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
+  }
+
+  // Since the delta values reported on mouse wheel events are
+  // unstandardized between browsers and even browser versions, and
+  // generally horribly unpredictable, this code starts by measuring
+  // the scroll effect that the first few mouse wheel events have,
+  // and, from that, detects the way it can convert deltas to pixel
+  // offsets afterwards.
+  //
+  // The reason we want to know the amount a wheel event will scroll
+  // is that it gives us a chance to update the display before the
+  // actual scrolling happens, reducing flickering.
+
+  var wheelSamples = 0, wheelPixelsPerUnit = null;
+  // Fill in a browser-detected starting value on browsers where we
+  // know one. These don't have to be accurate -- the result of them
+  // being wrong would just be a slight flicker on the first wheel
+  // scroll (if it is large enough).
+  if (ie) wheelPixelsPerUnit = -.53;
+  else if (gecko) wheelPixelsPerUnit = 15;
+  else if (chrome) wheelPixelsPerUnit = -.7;
+  else if (safari) wheelPixelsPerUnit = -1/3;
+
+  function onScrollWheel(cm, e) {
+    var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
+    if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
+    if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
+    else if (dy == null) dy = e.wheelDelta;
+
+    // Webkit browsers on OS X abort momentum scrolls when the target
+    // of the scroll event is removed from the scrollable element.
+    // This hack (see related code in patchDisplay) makes sure the
+    // element is kept around.
+    if (dy && mac && webkit) {
+      for (var cur = e.target; cur != scroll; cur = cur.parentNode) {
+        if (cur.lineObj) {
+          cm.display.currentWheelTarget = cur;
+          break;
+        }
+      }
+    }
+
+    var display = cm.display, scroll = display.scroller;
+    // On some browsers, horizontal scrolling will cause redraws to
+    // happen before the gutter has been realigned, causing it to
+    // wriggle around in a most unseemly way. When we have an
+    // estimated pixels/delta value, we just handle horizontal
+    // scrolling entirely here. It'll be slightly off from native, but
+    // better than glitching out.
+    if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {
+      if (dy)
+        setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
+      setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
+      e_preventDefault(e);
+      display.wheelStartX = null; // Abort measurement, if in progress
+      return;
+    }
+
+    if (dy && wheelPixelsPerUnit != null) {
+      var pixels = dy * wheelPixelsPerUnit;
+      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
+      if (pixels < 0) top = Math.max(0, top + pixels - 50);
+      else bot = Math.min(cm.doc.height, bot + pixels + 50);
+      updateDisplay(cm, [], {top: top, bottom: bot});
+    }
+
+    if (wheelSamples < 20) {
+      if (display.wheelStartX == null) {
+        display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
+        display.wheelDX = dx; display.wheelDY = dy;
+        setTimeout(function() {
+          if (display.wheelStartX == null) return;
+          var movedX = scroll.scrollLeft - display.wheelStartX;
+          var movedY = scroll.scrollTop - display.wheelStartY;
+          var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
+            (movedX && display.wheelDX && movedX / display.wheelDX);
+          display.wheelStartX = display.wheelStartY = null;
+          if (!sample) return;
+          wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
+          ++wheelSamples;
+        }, 200);
+      } else {
+        display.wheelDX += dx; display.wheelDY += dy;
+      }
+    }
+  }
+
+  function doHandleBinding(cm, bound, dropShift) {
+    if (typeof bound == "string") {
+      bound = commands[bound];
+      if (!bound) return false;
+    }
+    // Ensure previous input has been read, so that the handler sees a
+    // consistent view of the document
+    if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
+    var doc = cm.doc, prevShift = doc.sel.shift, done = false;
+    try {
+      if (isReadOnly(cm)) cm.state.suppressEdits = true;
+      if (dropShift) doc.sel.shift = false;
+      done = bound(cm) != Pass;
+    } finally {
+      doc.sel.shift = prevShift;
+      cm.state.suppressEdits = false;
+    }
+    return done;
+  }
+
+  function allKeyMaps(cm) {
+    var maps = cm.state.keyMaps.slice(0);
+    maps.push(cm.options.keyMap);
+    if (cm.options.extraKeys) maps.unshift(cm.options.extraKeys);
+    return maps;
+  }
+
+  var maybeTransition;
+  function handleKeyBinding(cm, e) {
+    // Handle auto keymap transitions
+    var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
+    clearTimeout(maybeTransition);
+    if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
+      if (getKeyMap(cm.options.keyMap) == startMap)
+        cm.options.keyMap = (next.call ? next.call(null, cm) : next);
+    }, 50);
+
+    var name = keyName(e, true), handled = false;
+    if (!name) return false;
+    var keymaps = allKeyMaps(cm);
+
+    if (e.shiftKey) {
+      // First try to resolve full name (including 'Shift-'). Failing
+      // that, see if there is a cursor-motion command (starting with
+      // 'go') bound to the keyname without 'Shift-'.
+      handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
+             || lookupKey(name, keymaps, function(b) {
+                  if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(cm, b);
+                });
+    } else {
+      handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
+    }
+    if (handled == "stop") handled = false;
+
+    if (handled) {
+      e_preventDefault(e);
+      restartBlink(cm);
+      if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
+    }
+    return handled;
+  }
+
+  function handleCharBinding(cm, e, ch) {
+    var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
+                            function(b) { return doHandleBinding(cm, b, true); });
+    if (handled) {
+      e_preventDefault(e);
+      restartBlink(cm);
+    }
+    return handled;
+  }
+
+  var lastStoppedKey = null;
+  function onKeyDown(e) {
+    var cm = this;
+    if (!cm.state.focused) onFocus(cm);
+    if (ie && e.keyCode == 27) { e.returnValue = false; }
+    if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+    var code = e.keyCode;
+    // IE does strange things with escape.
+    cm.doc.sel.shift = code == 16 || e.shiftKey;
+    // First give onKeyEvent option a chance to handle this.
+    var handled = handleKeyBinding(cm, e);
+    if (opera) {
+      lastStoppedKey = handled ? code : null;
+      // Opera has no cut event... we try to at least catch the key combo
+      if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
+        cm.replaceSelection("");
+    }
+  }
+
+  function onKeyPress(e) {
+    var cm = this;
+    if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+    var keyCode = e.keyCode, charCode = e.charCode;
+    if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
+    if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
+    var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
+    if (this.options.electricChars && this.doc.mode.electricChars &&
+        this.options.smartIndent && !isReadOnly(this) &&
+        this.doc.mode.electricChars.indexOf(ch) > -1)
+      setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75);
+    if (handleCharBinding(cm, e, ch)) return;
+    fastPoll(cm);
+  }
+
+  function onFocus(cm) {
+    if (cm.options.readOnly == "nocursor") return;
+    if (!cm.state.focused) {
+      signal(cm, "focus", cm);
+      cm.state.focused = true;
+      if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
+        cm.display.wrapper.className += " CodeMirror-focused";
+      resetInput(cm, true);
+    }
+    slowPoll(cm);
+    restartBlink(cm);
+  }
+  function onBlur(cm) {
+    if (cm.state.focused) {
+      signal(cm, "blur", cm);
+      cm.state.focused = false;
+      cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
+    }
+    clearInterval(cm.display.blinker);
+    setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);
+  }
+
+  var detectingSelectAll;
+  function onContextMenu(cm, e) {
+    var display = cm.display, sel = cm.doc.sel;
+    if (eventInWidget(display, e)) return;
+
+    var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
+    if (!pos || opera) return; // Opera is difficult.
+    if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
+      operation(cm, setSelection)(cm.doc, pos, pos);
+
+    var oldCSS = display.input.style.cssText;
+    display.inputDiv.style.position = "absolute";
+    display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
+      "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
+      "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);";
+    focusInput(cm);
+    resetInput(cm, true);
+    // Adds "Select all" to context menu in FF
+    if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";
+
+    function rehide() {
+      display.inputDiv.style.position = "relative";
+      display.input.style.cssText = oldCSS;
+      if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
+      slowPoll(cm);
+
+      // Try to detect the user choosing select-all 
+      if (display.input.selectionStart != null && (!ie || ie_lt9)) {
+        clearTimeout(detectingSelectAll);
+        var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value), i = 0;
+        display.prevInput = " ";
+        display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
+        var poll = function(){
+          if (display.prevInput == " " && display.input.selectionStart == 0)
+            operation(cm, commands.selectAll)(cm);
+          else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
+          else resetInput(cm);
+        };
+        detectingSelectAll = setTimeout(poll, 200);
+      }
+    }
+
+    if (captureMiddleClick) {
+      e_stop(e);
+      var mouseup = function() {
+        off(window, "mouseup", mouseup);
+        setTimeout(rehide, 20);
+      };
+      on(window, "mouseup", mouseup);
+    } else {
+      setTimeout(rehide, 50);
+    }
+  }
+
+  // UPDATING
+
+  function changeEnd(change) {
+    return Pos(change.from.line + change.text.length - 1,
+               lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
+  }
+
+  // Make sure a position will be valid after the given change.
+  function clipPostChange(doc, change, pos) {
+    if (!posLess(change.from, pos)) return clipPos(doc, pos);
+    var diff = (change.text.length - 1) - (change.to.line - change.from.line);
+    if (pos.line > change.to.line + diff) {
+      var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1;
+      if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length);
+      return clipToLen(pos, getLine(doc, preLine).text.length);
+    }
+    if (pos.line == change.to.line + diff)
+      return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) +
+                       getLine(doc, change.to.line).text.length - change.to.ch);
+    var inside = pos.line - change.from.line;
+    return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch));
+  }
+
+  // Hint can be null|"end"|"start"|"around"|{anchor,head}
+  function computeSelAfterChange(doc, change, hint) {
+    if (hint && typeof hint == "object") // Assumed to be {anchor, head} object
+      return {anchor: clipPostChange(doc, change, hint.anchor),
+              head: clipPostChange(doc, change, hint.head)};
+
+    if (hint == "start") return {anchor: change.from, head: change.from};
+    
+    var end = changeEnd(change);
+    if (hint == "around") return {anchor: change.from, head: end};
+    if (hint == "end") return {anchor: end, head: end};
+
+    // hint is null, leave the selection alone as much as possible
+    var adjustPos = function(pos) {
+      if (posLess(pos, change.from)) return pos;
+      if (!posLess(change.to, pos)) return end;
+
+      var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
+      if (pos.line == change.to.line) ch += end.ch - change.to.ch;
+      return Pos(line, ch);
+    };
+    return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};
+  }
+
+  function filterChange(doc, change) {
+    var obj = {
+      canceled: false,
+      from: change.from,
+      to: change.to,
+      text: change.text,
+      origin: change.origin,
+      update: function(from, to, text, origin) {
+        if (from) this.from = clipPos(doc, from);
+        if (to) this.to = clipPos(doc, to);
+        if (text) this.text = text;
+        if (origin !== undefined) this.origin = origin;
+      },
+      cancel: function() { this.canceled = true; }
+    };
+    signal(doc, "beforeChange", doc, obj);
+    if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
+
+    if (obj.canceled) return null;
+    return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
+  }
+
+  // Replace the range from from to to by the strings in replacement.
+  // change is a {from, to, text [, origin]} object
+  function makeChange(doc, change, selUpdate, ignoreReadOnly) {
+    if (doc.cm) {
+      if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly);
+      if (doc.cm.state.suppressEdits) return;
+    }
+
+    if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
+      change = filterChange(doc, change);
+      if (!change) return;
+    }
+
+    // Possibly split or suppress the update based on the presence
+    // of read-only spans in its range.
+    var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
+    if (split) {
+      for (var i = split.length - 1; i >= 1; --i)
+        makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]});
+      if (split.length)
+        makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate);
+    } else {
+      makeChangeNoReadonly(doc, change, selUpdate);
+    }
+  }
+
+  function makeChangeNoReadonly(doc, change, selUpdate) {
+    var selAfter = computeSelAfterChange(doc, change, selUpdate);
+    addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
+
+    makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
+    var rebased = [];
+
+    linkedDocs(doc, function(doc, sharedHist) {
+      if (!sharedHist && indexOf(rebased, doc.history) == -1) {
+        rebaseHist(doc.history, change);
+        rebased.push(doc.history);
+      }
+      makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
+    });
+  }
+
+  function makeChangeFromHistory(doc, type) {
+    var hist = doc.history;
+    var event = (type == "undo" ? hist.done : hist.undone).pop();
+    if (!event) return;
+    hist.dirtyCounter += type == "undo" ? -1 : 1;
+
+    var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
+                anchorAfter: event.anchorBefore, headAfter: event.headBefore};
+    (type == "undo" ? hist.undone : hist.done).push(anti);
+
+    for (var i = event.changes.length - 1; i >= 0; --i) {
+      var change = event.changes[i];
+      change.origin = type;
+      anti.changes.push(historyChangeFromChange(doc, change));
+
+      var after = i ? computeSelAfterChange(doc, change, null)
+                    : {anchor: event.anchorBefore, head: event.headBefore};
+      makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
+      var rebased = [];
+
+      linkedDocs(doc, function(doc, sharedHist) {
+        if (!sharedHist && indexOf(rebased, doc.history) == -1) {
+          rebaseHist(doc.history, change);
+          rebased.push(doc.history);
+        }
+        makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
+      });
+    }
+  }
+
+  function shiftDoc(doc, distance) {
+    function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);}
+    doc.first += distance;
+    if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance);
+    doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor);
+    doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to);
+  }
+
+  function makeChangeSingleDoc(doc, change, selAfter, spans) {
+    if (doc.cm && !doc.cm.curOp)
+      return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
+
+    if (change.to.line < doc.first) {
+      shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
+      return;
+    }
+    if (change.from.line > doc.lastLine()) return;
+
+    // Clip the change to the size of this doc
+    if (change.from.line < doc.first) {
+      var shift = change.text.length - 1 - (doc.first - change.from.line);
+      shiftDoc(doc, shift);
+      change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
+                text: [lst(change.text)], origin: change.origin};
+    }
+    var last = doc.lastLine();
+    if (change.to.line > last) {
+      change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
+                text: [change.text[0]], origin: change.origin};
+    }
+
+    if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);
+    if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter);
+    else updateDoc(doc, change, spans, selAfter);
+  }
+
+  function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {
+    var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
+
+    var recomputeMaxLength = false, checkWidthStart = from.line;
+    if (!cm.options.lineWrapping) {
+      checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line)));
+      doc.iter(checkWidthStart, to.line + 1, function(line) {
+        if (line == display.maxLine) {
+          recomputeMaxLength = true;
+          return true;
+        }
+      });
+    }
+
+    updateDoc(doc, change, spans, selAfter, estimateHeight(cm));
+
+    if (!cm.options.lineWrapping) {
+      doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
+        var len = lineLength(doc, line);
+        if (len > display.maxLineLength) {
+          display.maxLine = line;
+          display.maxLineLength = len;
+          display.maxLineChanged = true;
+          recomputeMaxLength = false;
+        }
+      });
+      if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
+    }
+
+    // Adjust frontier, schedule worker
+    doc.frontier = Math.min(doc.frontier, from.line);
+    startWorker(cm, 400);
+
+    var lendiff = change.text.length - (to.line - from.line) - 1;
+    // Remember that these lines changed, for updating the display
+    regChange(cm, from.line, to.line + 1, lendiff);
+    if (hasHandler(cm, "change")) {
+      var changeObj = {from: from, to: to, text: change.text, origin: change.origin};
+      if (cm.curOp.textChanged) {
+        for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}
+        cur.next = changeObj;
+      } else cm.curOp.textChanged = changeObj;
+    }
+  }
+
+  function replaceRange(doc, code, from, to, origin) {
+    if (!to) to = from;
+    if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }
+    if (typeof code == "string") code = splitLines(code);
+    makeChange(doc, {from: from, to: to, text: code, origin: origin}, null);
+  }
+
+  // POSITION OBJECT
+
+  function Pos(line, ch) {
+    if (!(this instanceof Pos)) return new Pos(line, ch);
+    this.line = line; this.ch = ch;
+  }
+  CodeMirror.Pos = Pos;
+
+  function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
+  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
+  function copyPos(x) {return Pos(x.line, x.ch);}
+
+  // SELECTION
+
+  function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
+  function clipPos(doc, pos) {
+    if (pos.line < doc.first) return Pos(doc.first, 0);
+    var last = doc.first + doc.size - 1;
+    if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
+    return clipToLen(pos, getLine(doc, pos.line).text.length);
+  }
+  function clipToLen(pos, linelen) {
+    var ch = pos.ch;
+    if (ch == null || ch > linelen) return Pos(pos.line, linelen);
+    else if (ch < 0) return Pos(pos.line, 0);
+    else return pos;
+  }
+  function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
+
+  // If shift is held, this will move the selection anchor. Otherwise,
+  // it'll set the whole selection.
+  function extendSelection(doc, pos, other, bias) {
+    if (doc.sel.shift || doc.sel.extend) {
+      var anchor = doc.sel.anchor;
+      if (other) {
+        var posBefore = posLess(pos, anchor);
+        if (posBefore != posLess(other, anchor)) {
+          anchor = pos;
+          pos = other;
+        } else if (posBefore != posLess(pos, other)) {
+          pos = other;
+        }
+      }
+      setSelection(doc, anchor, pos, bias);
+    } else {
+      setSelection(doc, pos, other || pos, bias);
+    }
+    if (doc.cm) doc.cm.curOp.userSelChange = true;
+  }
+
+  function filterSelectionChange(doc, anchor, head) {
+    var obj = {anchor: anchor, head: head};
+    signal(doc, "beforeSelectionChange", doc, obj);
+    if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
+    obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head);
+    return obj;
+  }
+
+  // Update the selection. Last two args are only used by
+  // updateDoc, since they have to be expressed in the line
+  // numbers before the update.
+  function setSelection(doc, anchor, head, bias, checkAtomic) {
+    if (!checkAtomic && hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) {
+      var filtered = filterSelectionChange(doc, anchor, head);
+      head = filtered.head;
+      anchor = filtered.anchor;
+    }
+
+    var sel = doc.sel;
+    sel.goalColumn = null;
+    // Skip over atomic spans.
+    if (checkAtomic || !posEq(anchor, sel.anchor))
+      anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");
+    if (checkAtomic || !posEq(head, sel.head))
+      head = skipAtomic(doc, head, bias, checkAtomic != "push");
+
+    if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;
+
+    sel.anchor = anchor; sel.head = head;
+    var inv = posLess(head, anchor);
+    sel.from = inv ? head : anchor;
+    sel.to = inv ? anchor : head;
+
+    if (doc.cm)
+      doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true;
+
+    signalLater(doc, "cursorActivity", doc);
+  }
+
+  function reCheckSelection(cm) {
+    setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push");
+  }
+
+  function skipAtomic(doc, pos, bias, mayClear) {
+    var flipped = false, curPos = pos;
+    var dir = bias || 1;
+    doc.cantEdit = false;
+    search: for (;;) {
+      var line = getLine(doc, curPos.line), toClear;
+      if (line.markedSpans) {
+        for (var i = 0; i < line.markedSpans.length; ++i) {
+          var sp = line.markedSpans[i], m = sp.marker;
+          if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
+              (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
+            if (mayClear && m.clearOnEnter) {
+              (toClear || (toClear = [])).push(m);
+              continue;
+            } else if (!m.atomic) continue;
+            var newPos = m.find()[dir < 0 ? "from" : "to"];
+            if (posEq(newPos, curPos)) {
+              newPos.ch += dir;
+              if (newPos.ch < 0) {
+                if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
+                else newPos = null;
+              } else if (newPos.ch > line.text.length) {
+                if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
+                else newPos = null;
+              }
+              if (!newPos) {
+                if (flipped) {
+                  // Driven in a corner -- no valid cursor position found at all
+                  // -- try again *with* clearing, if we didn't already
+                  if (!mayClear) return skipAtomic(doc, pos, bias, true);
+                  // Otherwise, turn off editing until further notice, and return the start of the doc
+                  doc.cantEdit = true;
+                  return Pos(doc.first, 0);
+                }
+                flipped = true; newPos = pos; dir = -dir;
+              }
+            }
+            curPos = newPos;
+            continue search;
+          }
+        }
+        if (toClear) for (var i = 0; i < toClear.length; ++i) toClear[i].clear();
+      }
+      return curPos;
+    }
+  }
+
+  // SCROLLING
+
+  function scrollCursorIntoView(cm) {
+    var coords = scrollPosIntoView(cm, cm.doc.sel.head);
+    if (!cm.state.focused) return;
+    var display = cm.display, box = getRect(display.sizer), doScroll = null;
+    if (coords.top + box.top < 0) doScroll = true;
+    else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
+    if (doScroll != null && !phantom) {
+      var hidden = display.cursor.style.display == "none";
+      if (hidden) {
+        display.cursor.style.display = "";
+        display.cursor.style.left = coords.left + "px";
+        display.cursor.style.top = (coords.top - display.viewOffset) + "px";
+      }
+      display.cursor.scrollIntoView(doScroll);
+      if (hidden) display.cursor.style.display = "none";
+    }
+  }
+
+  function scrollPosIntoView(cm, pos) {
+    for (;;) {
+      var changed = false, coords = cursorCoords(cm, pos);
+      var scrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
+      var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
+      if (scrollPos.scrollTop != null) {
+        setScrollTop(cm, scrollPos.scrollTop);
+        if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
+      }
+      if (scrollPos.scrollLeft != null) {
+        setScrollLeft(cm, scrollPos.scrollLeft);
+        if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
+      }
+      if (!changed) return coords;
+    }
+  }
+
+  function scrollIntoView(cm, x1, y1, x2, y2) {
+    var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
+    if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
+    if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
+  }
+
+  function calculateScrollPos(cm, x1, y1, x2, y2) {
+    var display = cm.display, pt = paddingTop(display);
+    y1 += pt; y2 += pt;
+    var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
+    var docBottom = cm.doc.height + 2 * pt;
+    var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10;
+    if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1);
+    else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen;
+
+    var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;
+    x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
+    var gutterw = display.gutters.offsetWidth;
+    var atLeft = x1 < gutterw + 10;
+    if (x1 < screenleft + gutterw || atLeft) {
+      if (atLeft) x1 = 0;
+      result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
+    } else if (x2 > screenw + screenleft - 3) {
+      result.scrollLeft = x2 + 10 - screenw;
+    }
+    return result;
+  }
+
+  // API UTILITIES
+
+  function indentLine(cm, n, how, aggressive) {
+    var doc = cm.doc;
+    if (!how) how = "add";
+    if (how == "smart") {
+      if (!cm.doc.mode.indent) how = "prev";
+      else var state = getStateBefore(cm, n);
+    }
+
+    var tabSize = cm.options.tabSize;
+    var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
+    var curSpaceString = line.text.match(/^\s*/)[0], indentation;
+    if (how == "smart") {
+      indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
+      if (indentation == Pass) {
+        if (!aggressive) return;
+        how = "prev";
+      }
+    }
+    if (how == "prev") {
+      if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
+      else indentation = 0;
+    } else if (how == "add") {
+      indentation = curSpace + cm.options.indentUnit;
+    } else if (how == "subtract") {
+      indentation = curSpace - cm.options.indentUnit;
+    }
+    indentation = Math.max(0, indentation);
+
+    var indentString = "", pos = 0;
+    if (cm.options.indentWithTabs)
+      for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
+    if (pos < indentation) indentString += spaceStr(indentation - pos);
+
+    if (indentString != curSpaceString)
+      replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
+    line.stateAfter = null;
+  }
+
+  function changeLine(cm, handle, op) {
+    var no = handle, line = handle, doc = cm.doc;
+    if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
+    else no = lineNo(handle);
+    if (no == null) return null;
+    if (op(line, no)) regChange(cm, no, no + 1);
+    else return null;
+    return line;
+  }
+
+  function findPosH(doc, pos, dir, unit, visually) {
+    var line = pos.line, ch = pos.ch;
+    var lineObj = getLine(doc, line);
+    var possible = true;
+    function findNextLine() {
+      var l = line + dir;
+      if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
+      line = l;
+      return lineObj = getLine(doc, l);
+    }
+    function moveOnce(boundToLine) {
+      var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
+      if (next == null) {
+        if (!boundToLine && findNextLine()) {
+          if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
+          else ch = dir < 0 ? lineObj.text.length : 0;
+        } else return (possible = false);
+      } else ch = next;
+      return true;
+    }
+
+    if (unit == "char") moveOnce();
+    else if (unit == "column") moveOnce(true);
+    else if (unit == "word") {
+      var sawWord = false;
+      for (;;) {
+        if (dir < 0) if (!moveOnce()) break;
+        if (isWordChar(lineObj.text.charAt(ch))) sawWord = true;
+        else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;}
+        if (dir > 0) if (!moveOnce()) break;
+      }
+    }
+    var result = skipAtomic(doc, Pos(line, ch), dir, true);
+    if (!possible) result.hitSide = true;
+    return result;
+  }
+
+  function findPosV(cm, pos, dir, unit) {
+    var doc = cm.doc, x = pos.left, y;
+    if (unit == "page") {
+      var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
+      y = pos.top + dir * pageSize;
+    } else if (unit == "line") {
+      y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
+    }
+    for (;;) {
+      var target = coordsChar(cm, x, y);
+      if (!target.outside) break;
+      if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
+      y += dir * 5;
+    }
+    return target;
+  }
+
+  function findWordAt(line, pos) {
+    var start = pos.ch, end = pos.ch;
+    if (line) {
+      if (pos.after === false || end == line.length) --start; else ++end;
+      var startChar = line.charAt(start);
+      var check = isWordChar(startChar) ? isWordChar :
+        /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} :
+      function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
+      while (start > 0 && check(line.charAt(start - 1))) --start;
+      while (end < line.length && check(line.charAt(end))) ++end;
+    }
+    return {from: Pos(pos.line, start), to: Pos(pos.line, end)};
+  }
+
+  function selectLine(cm, line) {
+    extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0)));
+  }
+
+  // PROTOTYPE
+
+  // The publicly visible API. Note that operation(null, f) means
+  // 'wrap f in an operation, performed on its `this` parameter'
+
+  CodeMirror.prototype = {
+    focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},
+
+    setOption: function(option, value) {
+      var options = this.options, old = options[option];
+      if (options[option] == value && option != "mode") return;
+      options[option] = value;
+      if (optionHandlers.hasOwnProperty(option))
+        operation(this, optionHandlers[option])(this, value, old);
+    },
+
+    getOption: function(option) {return this.options[option];},
+    getDoc: function() {return this.doc;},
+
+    addKeyMap: function(map) {
+      this.state.keyMaps.push(map);
+    },
+    removeKeyMap: function(map) {
+      var maps = this.state.keyMaps;
+      for (var i = 0; i < maps.length; ++i)
+        if ((typeof map == "string" ? maps[i].name : maps[i]) == map) {
+          maps.splice(i, 1);
+          return true;
+        }
+    },
+
+    addOverlay: operation(null, function(spec, options) {
+      var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
+      if (mode.startState) throw new Error("Overlays may not be stateful.");
+      this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
+      this.state.modeGen++;
+      regChange(this);
+    }),
+    removeOverlay: operation(null, function(spec) {
+      var overlays = this.state.overlays;
+      for (var i = 0; i < overlays.length; ++i) {
+        if (overlays[i].modeSpec == spec) {
+          overlays.splice(i, 1);
+          this.state.modeGen++;
+          regChange(this);
+          return;
+        }
+      }
+    }),
+
+    indentLine: operation(null, function(n, dir, aggressive) {
+      if (typeof dir != "string") {
+        if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
+        else dir = dir ? "add" : "subtract";
+      }
+      if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
+    }),
+    indentSelection: operation(null, function(how) {
+      var sel = this.doc.sel;
+      if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
+      var e = sel.to.line - (sel.to.ch ? 0 : 1);
+      for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
+    }),
+
+    // Fetch the parser token for a given character. Useful for hacks
+    // that want to inspect the mode state (say, for completion).
+    getTokenAt: function(pos) {
+      var doc = this.doc;
+      pos = clipPos(doc, pos);
+      var state = getStateBefore(this, pos.line), mode = this.doc.mode;
+      var line = getLine(doc, pos.line);
+      var stream = new StringStream(line.text, this.options.tabSize);
+      while (stream.pos < pos.ch && !stream.eol()) {
+        stream.start = stream.pos;
+        var style = mode.token(stream, state);
+      }
+      return {start: stream.start,
+              end: stream.pos,
+              string: stream.current(),
+              className: style || null, // Deprecated, use 'type' instead
+              type: style || null,
+              state: state};
+    },
+
+    getStateAfter: function(line) {
+      var doc = this.doc;
+      line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
+      return getStateBefore(this, line + 1);
+    },
+
+    cursorCoords: function(start, mode) {
+      var pos, sel = this.doc.sel;
+      if (start == null) pos = sel.head;
+      else if (typeof start == "object") pos = clipPos(this.doc, start);
+      else pos = start ? sel.from : sel.to;
+      return cursorCoords(this, pos, mode || "page");
+    },
+
+    charCoords: function(pos, mode) {
+      return charCoords(this, clipPos(this.doc, pos), mode || "page");
+    },
+
+    coordsChar: function(coords) {
+      var off = getRect(this.display.lineSpace);
+      var scrollY = window.pageYOffset || (document.documentElement || document.body).scrollTop;
+      var scrollX = window.pageXOffset || (document.documentElement || document.body).scrollLeft;
+      return coordsChar(this, coords.left - off.left - scrollX, coords.top - off.top - scrollY);
+    },
+
+    defaultTextHeight: function() { return textHeight(this.display); },
+
+    setGutterMarker: operation(null, function(line, gutterID, value) {
+      return changeLine(this, line, function(line) {
+        var markers = line.gutterMarkers || (line.gutterMarkers = {});
+        markers[gutterID] = value;
+        if (!value && isEmpty(markers)) line.gutterMarkers = null;
+        return true;
+      });
+    }),
+
+    clearGutter: operation(null, function(gutterID) {
+      var cm = this, doc = cm.doc, i = doc.first;
+      doc.iter(function(line) {
+        if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
+          line.gutterMarkers[gutterID] = null;
+          regChange(cm, i, i + 1);
+          if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
+        }
+        ++i;
+      });
+    }),
+
+    addLineClass: operation(null, function(handle, where, cls) {
+      return changeLine(this, handle, function(line) {
+        var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
+        if (!line[prop]) line[prop] = cls;
+        else if (new RegExp("\\b" + cls + "\\b").test(line[prop])) return false;
+        else line[prop] += " " + cls;
+        return true;
+      });
+    }),
+
+    removeLineClass: operation(null, function(handle, where, cls) {
+      return changeLine(this, handle, function(line) {
+        var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
+        var cur = line[prop];
+        if (!cur) return false;
+        else if (cls == null) line[prop] = null;
+        else {
+          var upd = cur.replace(new RegExp("^" + cls + "\\b\\s*|\\s*\\b" + cls + "\\b"), "");
+          if (upd == cur) return false;
+          line[prop] = upd || null;
+        }
+        return true;
+      });
+    }),
+
+    addLineWidget: operation(null, function(handle, node, options) {
+      return addLineWidget(this, handle, node, options);
+    }),
+
+    removeLineWidget: function(widget) { widget.clear(); },
+
+    lineInfo: function(line) {
+      if (typeof line == "number") {
+        if (!isLine(this.doc, line)) return null;
+        var n = line;
+        line = getLine(this.doc, line);
+        if (!line) return null;
+      } else {
+        var n = lineNo(line);
+        if (n == null) return null;
+      }
+      return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
+              textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
+              widgets: line.widgets};
+    },
+
+    getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},
+
+    addWidget: function(pos, node, scroll, vert, horiz) {
+      var display = this.display;
+      pos = cursorCoords(this, clipPos(this.doc, pos));
+      var top = pos.bottom, left = pos.left;
+      node.style.position = "absolute";
+      display.sizer.appendChild(node);
+      if (vert == "over") {
+        top = pos.top;
+      } else if (vert == "above" || vert == "near") {
+        var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
+        hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
+        // Default to positioning above (if specified and possible); otherwise default to positioning below
+        if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
+          top = pos.top - node.offsetHeight;
+        else if (pos.bottom + node.offsetHeight <= vspace)
+          top = pos.bottom;
+        if (left + node.offsetWidth > hspace)
+          left = hspace - node.offsetWidth;
+      }
+      node.style.top = (top + paddingTop(display)) + "px";
+      node.style.left = node.style.right = "";
+      if (horiz == "right") {
+        left = display.sizer.clientWidth - node.offsetWidth;
+        node.style.right = "0px";
+      } else {
+        if (horiz == "left") left = 0;
+        else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
+        node.style.left = left + "px";
+      }
+      if (scroll)
+        scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
+    },
+
+    triggerOnKeyDown: operation(null, onKeyDown),
+
+    execCommand: function(cmd) {return commands[cmd](this);},
+
+    findPosH: function(from, amount, unit, visually) {
+      var dir = 1;
+      if (amount < 0) { dir = -1; amount = -amount; }
+      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
+        cur = findPosH(this.doc, cur, dir, unit, visually);
+        if (cur.hitSide) break;
+      }
+      return cur;
+    },
+
+    moveH: operation(null, function(dir, unit) {
+      var sel = this.doc.sel, pos;
+      if (sel.shift || sel.extend || posEq(sel.from, sel.to))
+        pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually);
+      else
+        pos = dir < 0 ? sel.from : sel.to;
+      extendSelection(this.doc, pos, pos, dir);
+    }),
+
+    deleteH: operation(null, function(dir, unit) {
+      var sel = this.doc.sel;
+      if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete");
+      else replaceRange(this.doc, "", sel.from, findPosH(this.doc, sel.head, dir, unit, false), "+delete");
+      this.curOp.userSelChange = true;
+    }),
+
+    findPosV: function(from, amount, unit, goalColumn) {
+      var dir = 1, x = goalColumn;
+      if (amount < 0) { dir = -1; amount = -amount; }
+      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
+        var coords = cursorCoords(this, cur, "div");
+        if (x == null) x = coords.left;
+        else coords.left = x;
+        cur = findPosV(this, coords, dir, unit);
+        if (cur.hitSide) break;
+      }
+      return cur;
+    },
+
+    moveV: operation(null, function(dir, unit) {
+      var sel = this.doc.sel;
+      var pos = cursorCoords(this, sel.head, "div");
+      if (sel.goalColumn != null) pos.left = sel.goalColumn;
+      var target = findPosV(this, pos, dir, unit);
+
+      if (unit == "page")
+        this.display.scrollbarV.scrollTop += charCoords(this, target, "div").top - pos.top;
+      extendSelection(this.doc, target, target, dir);
+      sel.goalColumn = pos.left;
+    }),
+
+    toggleOverwrite: function() {
+      if (this.state.overwrite = !this.state.overwrite)
+        this.display.cursor.className += " CodeMirror-overwrite";
+      else
+        this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");
+    },
+
+    scrollTo: operation(null, function(x, y) {
+      this.curOp.updateScrollPos = {scrollLeft: x, scrollTop: y};
+    }),
+    getScrollInfo: function() {
+      var scroller = this.display.scroller, co = scrollerCutOff;
+      return {left: scroller.scrollLeft, top: scroller.scrollTop,
+              height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
+              clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
+    },
+
+    scrollIntoView: function(pos) {
+      if (typeof pos == "number") pos = Pos(pos, 0);
+      if (!pos || pos.line != null) {
+        pos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
+        scrollPosIntoView(this, pos);
+      } else {
+        scrollIntoView(this, pos.left, pos.top, pos.right, pos.bottom);
+      }
+    },
+
+    setSize: function(width, height) {
+      function interpret(val) {
+        return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
+      }
+      if (width != null) this.display.wrapper.style.width = interpret(width);
+      if (height != null) this.display.wrapper.style.height = interpret(height);
+      this.refresh();
+    },
+
+    on: function(type, f) {on(this, type, f);},
+    off: function(type, f) {off(this, type, f);},
+
+    operation: function(f){return runInOp(this, f);},
+
+    refresh: operation(null, function() {
+      clearCaches(this);
+      this.curOp.updateScrollPos = {scrollTop: this.doc.scrollTop, scrollLeft: this.doc.scrollLeft};
+      regChange(this);
+    }),
+
+    swapDoc: operation(null, function(doc) {
+      var old = this.doc;
+      old.cm = null;
+      attachDoc(this, doc);
+      clearCaches(this);
+      this.curOp.updateScrollPos = {scrollTop: doc.scrollTop, scrollLeft: doc.scrollLeft};
+      return old;
+    }),
+
+    getInputField: function(){return this.display.input;},
+    getWrapperElement: function(){return this.display.wrapper;},
+    getScrollerElement: function(){return this.display.scroller;},
+    getGutterElement: function(){return this.display.gutters;}
+  };
+
+  // OPTION DEFAULTS
+
+  var optionHandlers = CodeMirror.optionHandlers = {};
+
+  // The default configuration options.
+  var defaults = CodeMirror.defaults = {};
+
+  function option(name, deflt, handle, notOnInit) {
+    CodeMirror.defaults[name] = deflt;
+    if (handle) optionHandlers[name] =
+      notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
+  }
+
+  var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
+
+  // These two are, on init, called from the constructor because they
+  // have to be initialized before the editor can start at all.
+  option("value", "", function(cm, val) {
+    cm.setValue(val);
+  }, true);
+  option("mode", null, function(cm, val) {
+    cm.doc.modeOption = val;
+    loadMode(cm);
+  }, true);
+
+  option("indentUnit", 2, loadMode, true);
+  option("indentWithTabs", false);
+  option("smartIndent", true);
+  option("tabSize", 4, function(cm) {
+    loadMode(cm);
+    clearCaches(cm);
+    regChange(cm);
+  }, true);
+  option("electricChars", true);
+  option("rtlMoveVisually", !windows);
+
+  option("theme", "default", function(cm) {
+    themeChanged(cm);
+    guttersChanged(cm);
+  }, true);
+  option("keyMap", "default", keyMapChanged);
+  option("extraKeys", null);
+
+  option("onKeyEvent", null);
+  option("onDragEvent", null);
+
+  option("lineWrapping", false, wrappingChanged, true);
+  option("gutters", [], function(cm) {
+    setGuttersForLineNumbers(cm.options);
+    guttersChanged(cm);
+  }, true);
+  option("fixedGutter", true, function(cm, val) {
+    cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
+    cm.refresh();
+  }, true);
+  option("lineNumbers", false, function(cm) {
+    setGuttersForLineNumbers(cm.options);
+    guttersChanged(cm);
+  }, true);
+  option("firstLineNumber", 1, guttersChanged, true);
+  option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
+  option("showCursorWhenSelecting", false, updateSelection, true);
+  
+  option("readOnly", false, function(cm, val) {
+    if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
+    else if (!val) resetInput(cm, true);
+  });
+  option("dragDrop", true);
+
+  option("cursorBlinkRate", 530);
+  option("cursorHeight", 1);
+  option("workTime", 100);
+  option("workDelay", 100);
+  option("flattenSpans", true);
+  option("pollInterval", 100);
+  option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;});
+  option("viewportMargin", 10, function(cm){cm.refresh();}, true);
+
+  option("tabindex", null, function(cm, val) {
+    cm.display.input.tabIndex = val || "";
+  });
+  option("autofocus", null);
+
+  // MODE DEFINITION AND QUERYING
+
+  // Known modes, by name and by MIME
+  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
+
+  CodeMirror.defineMode = function(name, mode) {
+    if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
+    if (arguments.length > 2) {
+      mode.dependencies = [];
+      for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
+    }
+    modes[name] = mode;
+  };
+
+  CodeMirror.defineMIME = function(mime, spec) {
+    mimeModes[mime] = spec;
+  };
+
+  CodeMirror.resolveMode = function(spec) {
+    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
+      spec = mimeModes[spec];
+    else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec))
+      return CodeMirror.resolveMode("application/xml");
+    if (typeof spec == "string") return {name: spec};
+    else return spec || {name: "null"};
+  };
+
+  CodeMirror.getMode = function(options, spec) {
+    spec = CodeMirror.resolveMode(spec);
+    var mfactory = modes[spec.name];
+    if (!mfactory) return CodeMirror.getMode(options, "text/plain");
+    var modeObj = mfactory(options, spec);
+    if (modeExtensions.hasOwnProperty(spec.name)) {
+      var exts = modeExtensions[spec.name];
+      for (var prop in exts) {
+        if (!exts.hasOwnProperty(prop)) continue;
+        if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
+        modeObj[prop] = exts[prop];
+      }
+    }
+    modeObj.name = spec.name;
+    return modeObj;
+  };
+
+  CodeMirror.defineMode("null", function() {
+    return {token: function(stream) {stream.skipToEnd();}};
+  });
+  CodeMirror.defineMIME("text/plain", "null");
+
+  var modeExtensions = CodeMirror.modeExtensions = {};
+  CodeMirror.extendMode = function(mode, properties) {
+    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
+    copyObj(properties, exts);
+  };
+
+  // EXTENSIONS
+
+  CodeMirror.defineExtension = function(name, func) {
+    CodeMirror.prototype[name] = func;
+  };
+
+  CodeMirror.defineOption = option;
+
+  var initHooks = [];
+  CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
+
+  // MODE STATE HANDLING
+
+  // Utility functions for working with state. Exported because modes
+  // sometimes need to do this.
+  function copyState(mode, state) {
+    if (state === true) return state;
+    if (mode.copyState) return mode.copyState(state);
+    var nstate = {};
+    for (var n in state) {
+      var val = state[n];
+      if (val instanceof Array) val = val.concat([]);
+      nstate[n] = val;
+    }
+    return nstate;
+  }
+  CodeMirror.copyState = copyState;
+
+  function startState(mode, a1, a2) {
+    return mode.startState ? mode.startState(a1, a2) : true;
+  }
+  CodeMirror.startState = startState;
+
+  CodeMirror.innerMode = function(mode, state) {
+    while (mode.innerMode) {
+      var info = mode.innerMode(state);
+      state = info.state;
+      mode = info.mode;
+    }
+    return info || {mode: mode, state: state};
+  };
+
+  // STANDARD COMMANDS
+
+  var commands = CodeMirror.commands = {
+    selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));},
+    killLine: function(cm) {
+      var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
+      if (!sel && cm.getLine(from.line).length == from.ch)
+        cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete");
+      else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete");
+    },
+    deleteLine: function(cm) {
+      var l = cm.getCursor().line;
+      cm.replaceRange("", Pos(l, 0), Pos(l), "+delete");
+    },
+    undo: function(cm) {cm.undo();},
+    redo: function(cm) {cm.redo();},
+    goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
+    goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
+    goLineStart: function(cm) {
+      cm.extendSelection(lineStart(cm, cm.getCursor().line));
+    },
+    goLineStartSmart: function(cm) {
+      var cur = cm.getCursor(), start = lineStart(cm, cur.line);
+      var line = cm.getLineHandle(start.line);
+      var order = getOrder(line);
+      if (!order || order[0].level == 0) {
+        var firstNonWS = Math.max(0, line.text.search(/\S/));
+        var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;
+        cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS));
+      } else cm.extendSelection(start);
+    },
+    goLineEnd: function(cm) {
+      cm.extendSelection(lineEnd(cm, cm.getCursor().line));
+    },
+    goLineUp: function(cm) {cm.moveV(-1, "line");},
+    goLineDown: function(cm) {cm.moveV(1, "line");},
+    goPageUp: function(cm) {cm.moveV(-1, "page");},
+    goPageDown: function(cm) {cm.moveV(1, "page");},
+    goCharLeft: function(cm) {cm.moveH(-1, "char");},
+    goCharRight: function(cm) {cm.moveH(1, "char");},
+    goColumnLeft: function(cm) {cm.moveH(-1, "column");},
+    goColumnRight: function(cm) {cm.moveH(1, "column");},
+    goWordLeft: function(cm) {cm.moveH(-1, "word");},
+    goWordRight: function(cm) {cm.moveH(1, "word");},
+    delCharBefore: function(cm) {cm.deleteH(-1, "char");},
+    delCharAfter: function(cm) {cm.deleteH(1, "char");},
+    delWordBefore: function(cm) {cm.deleteH(-1, "word");},
+    delWordAfter: function(cm) {cm.deleteH(1, "word");},
+    indentAuto: function(cm) {cm.indentSelection("smart");},
+    indentMore: function(cm) {cm.indentSelection("add");},
+    indentLess: function(cm) {cm.indentSelection("subtract");},
+    insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");},
+    defaultTab: function(cm) {
+      if (cm.somethingSelected()) cm.indentSelection("add");
+      else cm.replaceSelection("\t", "end", "+input");
+    },
+    transposeChars: function(cm) {
+      var cur = cm.getCursor(), line = cm.getLine(cur.line);
+      if (cur.ch > 0 && cur.ch < line.length - 1)
+        cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
+                        Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
+    },
+    newlineAndIndent: function(cm) {
+      operation(cm, function() {
+        cm.replaceSelection("\n", "end", "+input");
+        cm.indentLine(cm.getCursor().line, null, true);
+      })();
+    },
+    toggleOverwrite: function(cm) {cm.toggleOverwrite();}
+  };
+
+  // STANDARD KEYMAPS
+
+  var keyMap = CodeMirror.keyMap = {};
+  keyMap.basic = {
+    "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
+    "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
+    "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
+    "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
+  };
+  // Note that the save and find-related commands aren't defined by
+  // default. Unknown commands are simply ignored.
+  keyMap.pcDefault = {
+    "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
+    "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
+    "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
+    "Ctrl-Backspace": "delWordBefore", "Ctrl-Delete": "delWordAfter", "Ctrl-S": "save", "Ctrl-F": "find",
+    "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
+    "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
+    fallthrough: "basic"
+  };
+  keyMap.macDefault = {
+    "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
+    "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft",
+    "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordBefore",
+    "Ctrl-Alt-Backspace": "delWordAfter", "Alt-Delete": "delWordAfter", "Cmd-S": "save", "Cmd-F": "find",
+    "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
+    "Cmd-[": "indentLess", "Cmd-]": "indentMore",
+    fallthrough: ["basic", "emacsy"]
+  };
+  keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
+  keyMap.emacsy = {
+    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
+    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
+    "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
+    "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
+  };
+
+  // KEYMAP DISPATCH
+
+  function getKeyMap(val) {
+    if (typeof val == "string") return keyMap[val];
+    else return val;
+  }
+
+  function lookupKey(name, maps, handle) {
+    function lookup(map) {
+      map = getKeyMap(map);
+      var found = map[name];
+      if (found === false) return "stop";
+      if (found != null && handle(found)) return true;
+      if (map.nofallthrough) return "stop";
+
+      var fallthrough = map.fallthrough;
+      if (fallthrough == null) return false;
+      if (Object.prototype.toString.call(fallthrough) != "[object Array]")
+        return lookup(fallthrough);
+      for (var i = 0, e = fallthrough.length; i < e; ++i) {
+        var done = lookup(fallthrough[i]);
+        if (done) return done;
+      }
+      return false;
+    }
+
+    for (var i = 0; i < maps.length; ++i) {
+      var done = lookup(maps[i]);
+      if (done) return done;
+    }
+  }
+  function isModifierKey(event) {
+    var name = keyNames[event.keyCode];
+    return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
+  }
+  function keyName(event, noShift) {
+    var name = keyNames[event.keyCode];
+    if (name == null || event.altGraphKey) return false;
+    if (event.altKey) name = "Alt-" + name;
+    if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
+    if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
+    if (!noShift && event.shiftKey) name = "Shift-" + name;
+    return name;
+  }
+  CodeMirror.lookupKey = lookupKey;
+  CodeMirror.isModifierKey = isModifierKey;
+  CodeMirror.keyName = keyName;
+
+  // FROMTEXTAREA
+
+  CodeMirror.fromTextArea = function(textarea, options) {
+    if (!options) options = {};
+    options.value = textarea.value;
+    if (!options.tabindex && textarea.tabindex)
+      options.tabindex = textarea.tabindex;
+    // Set autofocus to true if this textarea is focused, or if it has
+    // autofocus and no other element is focused.
+    if (options.autofocus == null) {
+      var hasFocus = document.body;
+      // doc.activeElement occasionally throws on IE
+      try { hasFocus = document.activeElement; } catch(e) {}
+      options.autofocus = hasFocus == textarea ||
+        textarea.getAttribute("autofocus") != null && hasFocus == document.body;
+    }
+
+    function save() {textarea.value = cm.getValue();}
+    if (textarea.form) {
+      // Deplorable hack to make the submit method do the right thing.
+      on(textarea.form, "submit", save);
+      var form = textarea.form, realSubmit = form.submit;
+      try {
+        var wrappedSubmit = form.submit = function() {
+          save();
+          form.submit = realSubmit;
+          form.submit();
+          form.submit = wrappedSubmit;
+        };
+      } catch(e) {}
+    }
+
+    textarea.style.display = "none";
+    var cm = CodeMirror(function(node) {
+      textarea.parentNode.insertBefore(node, textarea.nextSibling);
+    }, options);
+    cm.save = save;
+    cm.getTextArea = function() { return textarea; };
+    cm.toTextArea = function() {
+      save();
+      textarea.parentNode.removeChild(cm.getWrapperElement());
+      textarea.style.display = "";
+      if (textarea.form) {
+        off(textarea.form, "submit", save);
+        if (typeof textarea.form.submit == "function")
+          textarea.form.submit = realSubmit;
+      }
+    };
+    return cm;
+  };
+
+  // STRING STREAM
+
+  // Fed to the mode parsers, provides helper functions to make
+  // parsers more succinct.
+
+  // The character stream used by a mode's parser.
+  function StringStream(string, tabSize) {
+    this.pos = this.start = 0;
+    this.string = string;
+    this.tabSize = tabSize || 8;
+  }
+
+  StringStream.prototype = {
+    eol: function() {return this.pos >= this.string.length;},
+    sol: function() {return this.pos == 0;},
+    peek: function() {return this.string.charAt(this.pos) || undefined;},
+    next: function() {
+      if (this.pos < this.string.length)
+        return this.string.charAt(this.pos++);
+    },
+    eat: function(match) {
+      var ch = this.string.charAt(this.pos);
+      if (typeof match == "string") var ok = ch == match;
+      else var ok = ch && (match.test ? match.test(ch) : match(ch));
+      if (ok) {++this.pos; return ch;}
+    },
+    eatWhile: function(match) {
+      var start = this.pos;
+      while (this.eat(match)){}
+      return this.pos > start;
+    },
+    eatSpace: function() {
+      var start = this.pos;
+      while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
+      return this.pos > start;
+    },
+    skipToEnd: function() {this.pos = this.string.length;},
+    skipTo: function(ch) {
+      var found = this.string.indexOf(ch, this.pos);
+      if (found > -1) {this.pos = found; return true;}
+    },
+    backUp: function(n) {this.pos -= n;},
+    column: function() {return countColumn(this.string, this.start, this.tabSize);},
+    indentation: function() {return countColumn(this.string, null, this.tabSize);},
+    match: function(pattern, consume, caseInsensitive) {
+      if (typeof pattern == "string") {
+        var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
+        if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
+          if (consume !== false) this.pos += pattern.length;
+          return true;
+        }
+      } else {
+        var match = this.string.slice(this.pos).match(pattern);
+        if (match && match.index > 0) return null;
+        if (match && consume !== false) this.pos += match[0].length;
+        return match;
+      }
+    },
+    current: function(){return this.string.slice(this.start, this.pos);}
+  };
+  CodeMirror.StringStream = StringStream;
+
+  // TEXTMARKERS
+
+  function TextMarker(doc, type) {
+    this.lines = [];
+    this.type = type;
+    this.doc = doc;
+  }
+  CodeMirror.TextMarker = TextMarker;
+
+  TextMarker.prototype.clear = function() {
+    if (this.explicitlyCleared) return;
+    var cm = this.doc.cm, withOp = cm && !cm.curOp;
+    if (withOp) startOperation(cm);
+    var min = null, max = null;
+    for (var i = 0; i < this.lines.length; ++i) {
+      var line = this.lines[i];
+      var span = getMarkedSpanFor(line.markedSpans, this);
+      if (span.to != null) max = lineNo(line);
+      line.markedSpans = removeMarkedSpan(line.markedSpans, span);
+      if (span.from != null)
+        min = lineNo(line);
+      else if (this.collapsed && !lineIsHidden(this.doc, line) && cm)
+        updateLineHeight(line, textHeight(cm.display));
+    }
+    if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
+      var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual);
+      if (len > cm.display.maxLineLength) {
+        cm.display.maxLine = visual;
+        cm.display.maxLineLength = len;
+        cm.display.maxLineChanged = true;
+      }
+    }
+
+    if (min != null && cm) regChange(cm, min, max + 1);
+    this.lines.length = 0;
+    this.explicitlyCleared = true;
+    if (this.collapsed && this.doc.cantEdit) {
+      this.doc.cantEdit = false;
+      if (cm) reCheckSelection(cm);
+    }
+    if (withOp) endOperation(cm);
+    signalLater(this, "clear");
+  };
+
+  TextMarker.prototype.find = function() {
+    var from, to;
+    for (var i = 0; i < this.lines.length; ++i) {
+      var line = this.lines[i];
+      var span = getMarkedSpanFor(line.markedSpans, this);
+      if (span.from != null || span.to != null) {
+        var found = lineNo(line);
+        if (span.from != null) from = Pos(found, span.from);
+        if (span.to != null) to = Pos(found, span.to);
+      }
+    }
+    if (this.type == "bookmark") return from;
+    return from && {from: from, to: to};
+  };
+
+  TextMarker.prototype.getOptions = function(copyWidget) {
+    var repl = this.replacedWith;
+    return {className: this.className,
+            inclusiveLeft: this.inclusiveLeft, inclusiveRight: this.inclusiveRight,
+            atomic: this.atomic,
+            collapsed: this.collapsed,
+            clearOnEnter: this.clearOnEnter,
+            replacedWith: copyWidget ? repl && repl.cloneNode(true) : repl,
+            readOnly: this.readOnly,
+            startStyle: this.startStyle, endStyle: this.endStyle};
+  };
+
+  TextMarker.prototype.attachLine = function(line) {
+    if (!this.lines.length && this.doc.cm) {
+      var op = this.doc.cm.curOp;
+      if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
+        (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
+    }
+    this.lines.push(line);
+  };
+  TextMarker.prototype.detachLine = function(line) {
+    this.lines.splice(indexOf(this.lines, line), 1);
+    if (!this.lines.length && this.doc.cm) {
+      var op = this.doc.cm.curOp;
+      (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
+    }
+  };
+
+  function markText(doc, from, to, options, type) {
+    if (options && options.shared) return markTextShared(doc, from, to, options, type);
+    if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
+
+    var marker = new TextMarker(doc, type);
+    if (type == "range" && !posLess(from, to)) return marker;
+    if (options) copyObj(options, marker);
+    if (marker.replacedWith) {
+      marker.collapsed = true;
+      marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
+    }
+    if (marker.collapsed) sawCollapsedSpans = true;
+
+    var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine;
+    doc.iter(curLine, to.line + 1, function(line) {
+      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)
+        updateMaxLine = true;
+      var span = {from: null, to: null, marker: marker};
+      size += line.text.length;
+      if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
+      if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;}
+      if (marker.collapsed) {
+        if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch);
+        if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch);
+        else updateLineHeight(line, 0);
+      }
+      addMarkedSpan(line, span);
+      ++curLine;
+    });
+    if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
+      if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
+    });
+
+    if (marker.readOnly) {
+      sawReadOnlySpans = true;
+      if (doc.history.done.length || doc.history.undone.length)
+        doc.clearHistory();
+    }
+    if (marker.collapsed) {
+      if (collapsedAtStart != collapsedAtEnd)
+        throw new Error("Inserting collapsed marker overlapping an existing one");
+      marker.size = size;
+      marker.atomic = true;
+    }
+    if (cm) {
+      if (updateMaxLine) cm.curOp.updateMaxLine = true;
+      if (marker.className || marker.startStyle || marker.endStyle || marker.collapsed)
+        regChange(cm, from.line, to.line + 1);
+      if (marker.atomic) reCheckSelection(cm);
+    }
+    return marker;
+  }
+
+  // SHARED TEXTMARKERS
+
+  function SharedTextMarker(markers, primary) {
+    this.markers = markers;
+    this.primary = primary;
+    for (var i = 0, me = this; i < markers.length; ++i) {
+      markers[i].parent = this;
+      on(markers[i], "clear", function(){me.clear();});
+    }
+  }
+  CodeMirror.SharedTextMarker = SharedTextMarker;
+
+  SharedTextMarker.prototype.clear = function() {
+    if (this.explicitlyCleared) return;
+    this.explicitlyCleared = true;
+    for (var i = 0; i < this.markers.length; ++i)
+      this.markers[i].clear();
+    signalLater(this, "clear");
+  };
+  SharedTextMarker.prototype.find = function() {
+    return this.primary.find();
+  };
+  SharedTextMarker.prototype.getOptions = function(copyWidget) {
+    var inner = this.primary.getOptions(copyWidget);
+    inner.shared = true;
+    return inner;
+  };
+
+  function markTextShared(doc, from, to, options, type) {
+    options = copyObj(options);
+    options.shared = false;
+    var markers = [markText(doc, from, to, options, type)], primary = markers[0];
+    linkedDocs(doc, function(doc) {
+      markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
+      for (var i = 0; i < doc.linked.length; ++i)
+        if (doc.linked[i].isParent) return;
+      primary = lst(markers);
+    });
+    return new SharedTextMarker(markers, primary);
+  }
+
+  // TEXTMARKER SPANS
+
+  function getMarkedSpanFor(spans, marker) {
+    if (spans) for (var i = 0; i < spans.length; ++i) {
+      var span = spans[i];
+      if (span.marker == marker) return span;
+    }
+  }
+  function removeMarkedSpan(spans, span) {
+    for (var r, i = 0; i < spans.length; ++i)
+      if (spans[i] != span) (r || (r = [])).push(spans[i]);
+    return r;
+  }
+  function addMarkedSpan(line, span) {
+    line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
+    span.marker.attachLine(line);
+  }
+
+  function markedSpansBefore(old, startCh, isInsert) {
+    if (old) for (var i = 0, nw; i < old.length; ++i) {
+      var span = old[i], marker = span.marker;
+      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
+      if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
+        var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
+        (nw || (nw = [])).push({from: span.from,
+                                to: endsAfter ? null : span.to,
+                                marker: marker});
+      }
+    }
+    return nw;
+  }
+
+  function markedSpansAfter(old, endCh, isInsert) {
+    if (old) for (var i = 0, nw; i < old.length; ++i) {
+      var span = old[i], marker = span.marker;
+      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
+      if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) {
+        var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
+        (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
+                                to: span.to == null ? null : span.to - endCh,
+                                marker: marker});
+      }
+    }
+    return nw;
+  }
+
+  function stretchSpansOverChange(doc, change) {
+    var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
+    var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
+    if (!oldFirst && !oldLast) return null;
+
+    var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);
+    // Get the spans that 'stick out' on both sides
+    var first = markedSpansBefore(oldFirst, startCh, isInsert);
+    var last = markedSpansAfter(oldLast, endCh, isInsert);
+
+    // Next, merge those two ends
+    var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
+    if (first) {
+      // Fix up .to properties of first
+      for (var i = 0; i < first.length; ++i) {
+        var span = first[i];
+        if (span.to == null) {
+          var found = getMarkedSpanFor(last, span.marker);
+          if (!found) span.to = startCh;
+          else if (sameLine) span.to = found.to == null ? null : found.to + offset;
+        }
+      }
+    }
+    if (last) {
+      // Fix up .from in last (or move them into first in case of sameLine)
+      for (var i = 0; i < last.length; ++i) {
+        var span = last[i];
+        if (span.to != null) span.to += offset;
+        if (span.from == null) {
+          var found = getMarkedSpanFor(first, span.marker);
+          if (!found) {
+            span.from = offset;
+            if (sameLine) (first || (first = [])).push(span);
+          }
+        } else {
+          span.from += offset;
+          if (sameLine) (first || (first = [])).push(span);
+        }
+      }
+    }
+
+    var newMarkers = [first];
+    if (!sameLine) {
+      // Fill gap with whole-line-spans
+      var gap = change.text.length - 2, gapMarkers;
+      if (gap > 0 && first)
+        for (var i = 0; i < first.length; ++i)
+          if (first[i].to == null)
+            (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
+      for (var i = 0; i < gap; ++i)
+        newMarkers.push(gapMarkers);
+      newMarkers.push(last);
+    }
+    return newMarkers;
+  }
+
+  function mergeOldSpans(doc, change) {
+    var old = getOldSpans(doc, change);
+    var stretched = stretchSpansOverChange(doc, change);
+    if (!old) return stretched;
+    if (!stretched) return old;
+
+    for (var i = 0; i < old.length; ++i) {
+      var oldCur = old[i], stretchCur = stretched[i];
+      if (oldCur && stretchCur) {
+        spans: for (var j = 0; j < stretchCur.length; ++j) {
+          var span = stretchCur[j];
+          for (var k = 0; k < oldCur.length; ++k)
+            if (oldCur[k].marker == span.marker) continue spans;
+          oldCur.push(span);
+        }
+      } else if (stretchCur) {
+        old[i] = stretchCur;
+      }
+    }
+    return old;
+  }
+
+  function removeReadOnlyRanges(doc, from, to) {
+    var markers = null;
+    doc.iter(from.line, to.line + 1, function(line) {
+      if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
+        var mark = line.markedSpans[i].marker;
+        if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
+          (markers || (markers = [])).push(mark);
+      }
+    });
+    if (!markers) return null;
+    var parts = [{from: from, to: to}];
+    for (var i = 0; i < markers.length; ++i) {
+      var mk = markers[i], m = mk.find();
+      for (var j = 0; j < parts.length; ++j) {
+        var p = parts[j];
+        if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue;
+        var newParts = [j, 1];
+        if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from))
+          newParts.push({from: p.from, to: m.from});
+        if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to))
+          newParts.push({from: m.to, to: p.to});
+        parts.splice.apply(parts, newParts);
+        j += newParts.length - 1;
+      }
+    }
+    return parts;
+  }
+
+  function collapsedSpanAt(line, ch) {
+    var sps = sawCollapsedSpans && line.markedSpans, found;
+    if (sps) for (var sp, i = 0; i < sps.length; ++i) {
+      sp = sps[i];
+      if (!sp.marker.collapsed) continue;
+      if ((sp.from == null || sp.from < ch) &&
+          (sp.to == null || sp.to > ch) &&
+          (!found || found.width < sp.marker.width))
+        found = sp.marker;
+    }
+    return found;
+  }
+  function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
+  function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); }
+
+  function visualLine(doc, line) {
+    var merged;
+    while (merged = collapsedSpanAtStart(line))
+      line = getLine(doc, merged.find().from.line);
+    return line;
+  }
+
+  function lineIsHidden(doc, line) {
+    var sps = sawCollapsedSpans && line.markedSpans;
+    if (sps) for (var sp, i = 0; i < sps.length; ++i) {
+      sp = sps[i];
+      if (!sp.marker.collapsed) continue;
+      if (sp.from == null) return true;
+      if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
+        return true;
+    }
+  }
+  function lineIsHiddenInner(doc, line, span) {
+    if (span.to == null) {
+      var end = span.marker.find().to, endLine = getLine(doc, end.line);
+      return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));
+    }
+    if (span.marker.inclusiveRight && span.to == line.text.length)
+      return true;
+    for (var sp, i = 0; i < line.markedSpans.length; ++i) {
+      sp = line.markedSpans[i];
+      if (sp.marker.collapsed && sp.from == span.to &&
+          (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
+          lineIsHiddenInner(doc, line, sp)) return true;
+    }
+  }
+
+  function detachMarkedSpans(line) {
+    var spans = line.markedSpans;
+    if (!spans) return;
+    for (var i = 0; i < spans.length; ++i)
+      spans[i].marker.detachLine(line);
+    line.markedSpans = null;
+  }
+
+  function attachMarkedSpans(line, spans) {
+    if (!spans) return;
+    for (var i = 0; i < spans.length; ++i)
+      spans[i].marker.attachLine(line);
+    line.markedSpans = spans;
+  }
+
+  // LINE WIDGETS
+
+  var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
+    for (var opt in options) if (options.hasOwnProperty(opt))
+      this[opt] = options[opt];
+    this.cm = cm;
+    this.node = node;
+  };
+  function widgetOperation(f) {
+    return function() {
+      var withOp = !this.cm.curOp;
+      if (withOp) startOperation(this.cm);
+      try {var result = f.apply(this, arguments);}
+      finally {if (withOp) endOperation(this.cm);}
+      return result;
+    };
+  }
+  LineWidget.prototype.clear = widgetOperation(function() {
+    var ws = this.line.widgets, no = lineNo(this.line);
+    if (no == null || !ws) return;
+    for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
+    if (!ws.length) this.line.widgets = null;
+    updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));
+    regChange(this.cm, no, no + 1);
+  });
+  LineWidget.prototype.changed = widgetOperation(function() {
+    var oldH = this.height;
+    this.height = null;
+    var diff = widgetHeight(this) - oldH;
+    if (!diff) return;
+    updateLineHeight(this.line, this.line.height + diff);
+    var no = lineNo(this.line);
+    regChange(this.cm, no, no + 1);
+  });
+
+  function widgetHeight(widget) {
+    if (widget.height != null) return widget.height;
+    if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1)
+      removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative"));
+    return widget.height = widget.node.offsetHeight;
+  }
+
+  function addLineWidget(cm, handle, node, options) {
+    var widget = new LineWidget(cm, node, options);
+    if (widget.noHScroll) cm.display.alignWidgets = true;
+    changeLine(cm, handle, function(line) {
+      (line.widgets || (line.widgets = [])).push(widget);
+      widget.line = line;
+      if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {
+        var aboveVisible = heightAtLine(cm, line) < cm.display.scroller.scrollTop;
+        updateLineHeight(line, line.height + widgetHeight(widget));
+        if (aboveVisible)
+          cm.curOp.updateScrollPos = {scrollTop: cm.doc.scrollTop + widget.height,
+                                      scrollLeft: cm.doc.scrollLeft};
+      }
+      return true;
+    });
+    return widget;
+  }
+
+  // LINE DATA STRUCTURE
+
+  // Line objects. These hold state related to a line, including
+  // highlighting info (the styles array).
+  function makeLine(text, markedSpans, estimateHeight) {
+    var line = {text: text};
+    attachMarkedSpans(line, markedSpans);
+    line.height = estimateHeight ? estimateHeight(line) : 1;
+    return line;
+  }
+
+  function updateLine(line, text, markedSpans, estimateHeight) {
+    line.text = text;
+    if (line.stateAfter) line.stateAfter = null;
+    if (line.styles) line.styles = null;
+    if (line.order != null) line.order = null;
+    detachMarkedSpans(line);
+    attachMarkedSpans(line, markedSpans);
+    var estHeight = estimateHeight ? estimateHeight(line) : 1;
+    if (estHeight != line.height) updateLineHeight(line, estHeight);
+    signalLater(line, "change");
+  }
+
+  function cleanUpLine(line) {
+    line.parent = null;
+    detachMarkedSpans(line);
+  }
+
+  // Run the given mode's parser over a line, update the styles
+  // array, which contains alternating fragments of text and CSS
+  // classes.
+  function runMode(cm, text, mode, state, f) {
+    var flattenSpans = cm.options.flattenSpans;
+    var curText = "", curStyle = null;
+    var stream = new StringStream(text, cm.options.tabSize);
+    if (text == "" && mode.blankLine) mode.blankLine(state);
+    while (!stream.eol()) {
+      var style = mode.token(stream, state);
+      if (stream.pos > 5000) {
+        flattenSpans = false;
+        // Webkit seems to refuse to render text nodes longer than 57444 characters
+        stream.pos = Math.min(text.length, stream.start + 50000);
+        style = null;
+      }
+      var substr = stream.current();
+      stream.start = stream.pos;
+      if (!flattenSpans || curStyle != style) {
+        if (curText) f(curText, curStyle);
+        curText = substr; curStyle = style;
+      } else curText = curText + substr;
+    }
+    if (curText) f(curText, curStyle);
+  }
+
+  function highlightLine(cm, line, state) {
+    // A styles array always starts with a number identifying the
+    // mode/overlays that it is based on (for easy invalidation).
+    var st = [cm.state.modeGen];
+    // Compute the base array of styles
+    runMode(cm, line.text, cm.doc.mode, state, function(txt, style) {st.push(txt, style);});
+
+    // Run overlays, adjust style array.
+    for (var o = 0; o < cm.state.overlays.length; ++o) {
+      var overlay = cm.state.overlays[o], i = 1;
+      runMode(cm, line.text, overlay.mode, true, function(txt, style) {
+        var start = i, len = txt.length;
+        // Ensure there's a token end at the current position, and that i points at it
+        while (len) {
+          var cur = st[i], len_ = cur.length;
+          if (len_ <= len) {
+            len -= len_;
+          } else {
+            st.splice(i, 1, cur.slice(0, len), st[i+1], cur.slice(len));
+            len = 0;
+          }
+          i += 2;
+        }
+        if (!style) return;
+        if (overlay.opaque) {
+          st.splice(start, i - start, txt, style);
+          i = start + 2;
+        } else {
+          for (; start < i; start += 2) {
+            var cur = st[start+1];
+            st[start+1] = cur ? cur + " " + style : style;
+          }
+        }
+      });
+    }
+
+    return st;
+  }
+
+  function getLineStyles(cm, line) {
+    if (!line.styles || line.styles[0] != cm.state.modeGen)
+      line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
+    return line.styles;
+  }
+
+  // Lightweight form of highlight -- proceed over this line and
+  // update state, but don't save a style array.
+  function processLine(cm, line, state) {
+    var mode = cm.doc.mode;
+    var stream = new StringStream(line.text, cm.options.tabSize);
+    if (line.text == "" && mode.blankLine) mode.blankLine(state);
+    while (!stream.eol() && stream.pos <= 5000) {
+      mode.token(stream, state);
+      stream.start = stream.pos;
+    }
+  }
+
+  var styleToClassCache = {};
+  function styleToClass(style) {
+    if (!style) return null;
+    return styleToClassCache[style] ||
+      (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
+  }
+
+  function lineContent(cm, realLine, measure) {
+    var merged, line = realLine, lineBefore, sawBefore, simple = true;
+    while (merged = collapsedSpanAtStart(line)) {
+      simple = false;
+      line = getLine(cm.doc, merged.find().from.line);
+      if (!lineBefore) lineBefore = line;
+    }
+
+    var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure,
+                   measure: null, addedOne: false, cm: cm};
+    if (line.textClass) builder.pre.className = line.textClass;
+
+    do {
+      builder.measure = line == realLine && measure;
+      builder.pos = 0;
+      builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
+      if (measure && sawBefore && line != realLine && !builder.addedOne) {
+        measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
+        builder.addedOne = true;
+      }
+      var next = insertLineContent(line, builder, getLineStyles(cm, line));
+      sawBefore = line == lineBefore;
+      if (next) {
+        line = getLine(cm.doc, next.to.line);
+        simple = false;
+      }
+    } while (next);
+
+    if (measure && !builder.addedOne)
+      measure[0] = builder.pre.appendChild(simple ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
+    if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
+      builder.pre.appendChild(document.createTextNode("\u00a0"));
+
+    var order;
+    // Work around problem with the reported dimensions of single-char
+    // direction spans on IE (issue #1129). See also the comment in
+    // cursorCoords.
+    if (measure && ie && (order = getOrder(line))) {
+      var l = order.length - 1;
+      if (order[l].from == order[l].to) --l;
+      var last = order[l], prev = order[l - 1];
+      if (last.from + 1 == last.to && prev && last.level < prev.level) {
+        var span = measure[builder.pos - 1];
+        if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure),
+                                               span.nextSibling);
+      }
+    }
+
+    return builder.pre;
+  }
+
+  var tokenSpecialChars = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g;
+  function buildToken(builder, text, style, startStyle, endStyle) {
+    if (!text) return;
+    if (!tokenSpecialChars.test(text)) {
+      builder.col += text.length;
+      var content = document.createTextNode(text);
+    } else {
+      var content = document.createDocumentFragment(), pos = 0;
+      while (true) {
+        tokenSpecialChars.lastIndex = pos;
+        var m = tokenSpecialChars.exec(text);
+        var skipped = m ? m.index - pos : text.length - pos;
+        if (skipped) {
+          content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
+          builder.col += skipped;
+        }
+        if (!m) break;
+        pos += skipped + 1;
+        if (m[0] == "\t") {
+          var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
+          content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
+          builder.col += tabWidth;
+        } else {
+          var token = elt("span", "\u2022", "cm-invalidchar");
+          token.title = "\\u" + m[0].charCodeAt(0).toString(16);
+          content.appendChild(token);
+          builder.col += 1;
+        }
+      }
+    }
+    if (style || startStyle || endStyle || builder.measure) {
+      var fullStyle = style || "";
+      if (startStyle) fullStyle += startStyle;
+      if (endStyle) fullStyle += endStyle;
+      return builder.pre.appendChild(elt("span", [content], fullStyle));
+    }
+    builder.pre.appendChild(content);
+  }
+
+  function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
+    for (var i = 0; i < text.length; ++i) {
+      var ch = text.charAt(i), start = i == 0;
+      if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
+        ch = text.slice(i, i + 2);
+        ++i;
+      } else if (i && builder.cm.options.lineWrapping &&
+                 spanAffectsWrapping.test(text.slice(i - 1, i + 1))) {
+        builder.pre.appendChild(elt("wbr"));
+      }
+      builder.measure[builder.pos] =
+        buildToken(builder, ch, style,
+                   start && startStyle, i == text.length - 1 && endStyle);
+      builder.pos += ch.length;
+    }
+    if (text.length) builder.addedOne = true;
+  }
+
+  function buildCollapsedSpan(builder, size, widget) {
+    if (widget) {
+      if (!builder.display) widget = widget.cloneNode(true);
+      builder.pre.appendChild(widget);
+      if (builder.measure && size) {
+        builder.measure[builder.pos] = widget;
+        builder.addedOne = true;
+      }
+    }
+    builder.pos += size;
+  }
+
+  // Outputs a number of spans to make up a line, taking highlighting
+  // and marked text into account.
+  function insertLineContent(line, builder, styles) {
+    var spans = line.markedSpans;
+    if (!spans) {
+      for (var i = 1; i < styles.length; i+=2)
+        builder.addToken(builder, styles[i], styleToClass(styles[i+1]));
+      return;
+    }
+
+    var allText = line.text, len = allText.length;
+    var pos = 0, i = 1, text = "", style;
+    var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed;
+    for (;;) {
+      if (nextChange == pos) { // Update current marker set
+        spanStyle = spanEndStyle = spanStartStyle = "";
+        collapsed = null; nextChange = Infinity;
+        var foundBookmark = null;
+        for (var j = 0; j < spans.length; ++j) {
+          var sp = spans[j], m = sp.marker;
+          if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
+            if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
+            if (m.className) spanStyle += " " + m.className;
+            if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
+            if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
+            if (m.collapsed && (!collapsed || collapsed.marker.width < m.width))
+              collapsed = sp;
+          } else if (sp.from > pos && nextChange > sp.from) {
+            nextChange = sp.from;
+          }
+          if (m.type == "bookmark" && sp.from == pos && m.replacedWith)
+            foundBookmark = m.replacedWith;
+        }
+        if (collapsed && (collapsed.from || 0) == pos) {
+          buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
+                             collapsed.from != null && collapsed.marker.replacedWith);
+          if (collapsed.to == null) return collapsed.marker.find();
+        }
+        if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
+      }
+      if (pos >= len) break;
+
+      var upto = Math.min(len, nextChange);
+      while (true) {
+        if (text) {
+          var end = pos + text.length;
+          if (!collapsed) {
+            var tokenText = end > upto ? text.slice(0, upto - pos) : text;
+            builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
+                             spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "");
+          }
+          if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
+          pos = end;
+          spanStartStyle = "";
+        }
+        text = styles[i++]; style = styleToClass(styles[i++]);
+      }
+    }
+  }
+
+  // DOCUMENT DATA STRUCTURE
+
+  function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {
+    function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
+
+    var from = change.from, to = change.to, text = change.text;
+    var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
+    var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
+
+    // First adjust the line structure
+    if (from.ch == 0 && to.ch == 0 && lastText == "") {
+      // This is a whole-line replace. Treated specially to make
+      // sure line objects move the way they are supposed to.
+      for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
+        added.push(makeLine(text[i], spansFor(i), estimateHeight));
+      updateLine(lastLine, lastLine.text, lastSpans, estimateHeight);
+      if (nlines) doc.remove(from.line, nlines);
+      if (added.length) doc.insert(from.line, added);
+    } else if (firstLine == lastLine) {
+      if (text.length == 1) {
+        updateLine(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch),
+                   lastSpans, estimateHeight);
+      } else {
+        for (var added = [], i = 1, e = text.length - 1; i < e; ++i)
+          added.push(makeLine(text[i], spansFor(i), estimateHeight));
+        added.push(makeLine(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
+        updateLine(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0), estimateHeight);
+        doc.insert(from.line + 1, added);
+      }
+    } else if (text.length == 1) {
+      updateLine(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch),
+                 spansFor(0), estimateHeight);
+      doc.remove(from.line + 1, nlines);
+    } else {
+      updateLine(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0), estimateHeight);
+      updateLine(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans, estimateHeight);
+      for (var i = 1, e = text.length - 1, added = []; i < e; ++i)
+        added.push(makeLine(text[i], spansFor(i), estimateHeight));
+      if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
+      doc.insert(from.line + 1, added);
+    }
+
+    signalLater(doc, "change", doc, change);
+    setSelection(doc, selAfter.anchor, selAfter.head, null, true);
+  }
+
+  function LeafChunk(lines) {
+    this.lines = lines;
+    this.parent = null;
+    for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
+      lines[i].parent = this;
+      height += lines[i].height;
+    }
+    this.height = height;
+  }
+
+  LeafChunk.prototype = {
+    chunkSize: function() { return this.lines.length; },
+    removeInner: function(at, n) {
+      for (var i = at, e = at + n; i < e; ++i) {
+        var line = this.lines[i];
+        this.height -= line.height;
+        cleanUpLine(line);
+        signalLater(line, "delete");
+      }
+      this.lines.splice(at, n);
+    },
+    collapse: function(lines) {
+      lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
+    },
+    insertInner: function(at, lines, height) {
+      this.height += height;
+      this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
+      for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
+    },
+    iterN: function(at, n, op) {
+      for (var e = at + n; at < e; ++at)
+        if (op(this.lines[at])) return true;
+    }
+  };
+
+  function BranchChunk(children) {
+    this.children = children;
+    var size = 0, height = 0;
+    for (var i = 0, e = children.length; i < e; ++i) {
+      var ch = children[i];
+      size += ch.chunkSize(); height += ch.height;
+      ch.parent = this;
+    }
+    this.size = size;
+    this.height = height;
+    this.parent = null;
+  }
+
+  BranchChunk.prototype = {
+    chunkSize: function() { return this.size; },
+    removeInner: function(at, n) {
+      this.size -= n;
+      for (var i = 0; i < this.children.length; ++i) {
+        var child = this.children[i], sz = child.chunkSize();
+        if (at < sz) {
+          var rm = Math.min(n, sz - at), oldHeight = child.height;
+          child.removeInner(at, rm);
+          this.height -= oldHeight - child.height;
+          if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
+          if ((n -= rm) == 0) break;
+          at = 0;
+        } else at -= sz;
+      }
+      if (this.size - n < 25) {
+        var lines = [];
+        this.collapse(lines);
+        this.children = [new LeafChunk(lines)];
+        this.children[0].parent = this;
+      }
+    },
+    collapse: function(lines) {
+      for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
+    },
+    insertInner: function(at, lines, height) {
+      this.size += lines.length;
+      this.height += height;
+      for (var i = 0, e = this.children.length; i < e; ++i) {
+        var child = this.children[i], sz = child.chunkSize();
+        if (at <= sz) {
+          child.insertInner(at, lines, height);
+          if (child.lines && child.lines.length > 50) {
+            while (child.lines.length > 50) {
+              var spilled = child.lines.splice(child.lines.length - 25, 25);
+              var newleaf = new LeafChunk(spilled);
+              child.height -= newleaf.height;
+              this.children.splice(i + 1, 0, newleaf);
+              newleaf.parent = this;
+            }
+            this.maybeSpill();
+          }
+          break;
+        }
+        at -= sz;
+      }
+    },
+    maybeSpill: function() {
+      if (this.children.length <= 10) return;
+      var me = this;
+      do {
+        var spilled = me.children.splice(me.children.length - 5, 5);
+        var sibling = new BranchChunk(spilled);
+        if (!me.parent) { // Become the parent node
+          var copy = new BranchChunk(me.children);
+          copy.parent = me;
+          me.children = [copy, sibling];
+          me = copy;
+        } else {
+          me.size -= sibling.size;
+          me.height -= sibling.height;
+          var myIndex = indexOf(me.parent.children, me);
+          me.parent.children.splice(myIndex + 1, 0, sibling);
+        }
+        sibling.parent = me.parent;
+      } while (me.children.length > 10);
+      me.parent.maybeSpill();
+    },
+    iterN: function(at, n, op) {
+      for (var i = 0, e = this.children.length; i < e; ++i) {
+        var child = this.children[i], sz = child.chunkSize();
+        if (at < sz) {
+          var used = Math.min(n, sz - at);
+          if (child.iterN(at, used, op)) return true;
+          if ((n -= used) == 0) break;
+          at = 0;
+        } else at -= sz;
+      }
+    }
+  };
+
+  var nextDocId = 0;
+  var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
+    if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
+    if (firstLine == null) firstLine = 0;
+    
+    BranchChunk.call(this, [new LeafChunk([makeLine("", null)])]);
+    this.first = firstLine;
+    this.scrollTop = this.scrollLeft = 0;
+    this.cantEdit = false;
+    this.history = makeHistory();
+    this.frontier = firstLine;
+    var start = Pos(firstLine, 0);
+    this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};
+    this.id = ++nextDocId;
+    this.modeOption = mode;
+
+    if (typeof text == "string") text = splitLines(text);
+    updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start});
+  };
+
+  Doc.prototype = createObj(BranchChunk.prototype, {
+    iter: function(from, to, op) {
+      if (op) this.iterN(from - this.first, to - from, op);
+      else this.iterN(this.first, this.first + this.size, from);
+    },
+
+    insert: function(at, lines) {
+      var height = 0;
+      for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
+      this.insertInner(at - this.first, lines, height);
+    },
+    remove: function(at, n) { this.removeInner(at - this.first, n); },
+
+    getValue: function(lineSep) {
+      var lines = getLines(this, this.first, this.first + this.size);
+      if (lineSep === false) return lines;
+      return lines.join(lineSep || "\n");
+    },
+    setValue: function(code) {
+      var top = Pos(this.first, 0), last = this.first + this.size - 1;
+      makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
+                        text: splitLines(code), origin: "setValue"},
+                 {head: top, anchor: top}, true);
+    },
+    replaceRange: function(code, from, to, origin) {
+      from = clipPos(this, from);
+      to = to ? clipPos(this, to) : from;
+      replaceRange(this, code, from, to, origin);
+    },
+    getRange: function(from, to, lineSep) {
+      var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
+      if (lineSep === false) return lines;
+      return lines.join(lineSep || "\n");
+    },
+
+    getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
+    setLine: function(line, text) {
+      if (isLine(this, line))
+        replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line)));
+    },
+    removeLine: function(line) {
+      if (isLine(this, line))
+        replaceRange(this, "", Pos(line, 0), clipPos(this, Pos(line + 1, 0)));
+    },
+
+    getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
+    getLineNumber: function(line) {return lineNo(line);},
+
+    lineCount: function() {return this.size;},
+    firstLine: function() {return this.first;},
+    lastLine: function() {return this.first + this.size - 1;},
+
+    clipPos: function(pos) {return clipPos(this, pos);},
+
+    getCursor: function(start) {
+      var sel = this.sel, pos;
+      if (start == null || start == "head") pos = sel.head;
+      else if (start == "anchor") pos = sel.anchor;
+      else if (start == "end" || start === false) pos = sel.to;
+      else pos = sel.from;
+      return copyPos(pos);
+    },
+    somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);},
+
+    setCursor: docOperation(function(line, ch, extend) {
+      var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line);
+      if (extend) extendSelection(this, pos);
+      else setSelection(this, pos, pos);
+    }),
+    setSelection: docOperation(function(anchor, head) {
+      setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
+    }),
+    extendSelection: docOperation(function(from, to) {
+      extendSelection(this, clipPos(this, from), to && clipPos(this, to));
+    }),
+
+    getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
+    replaceSelection: function(code, collapse, origin) {
+      makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around");
+    },
+    undo: docOperation(function() {makeChangeFromHistory(this, "undo");}),
+    redo: docOperation(function() {makeChangeFromHistory(this, "redo");}),
+
+    setExtending: function(val) {this.sel.extend = val;},
+
+    historySize: function() {
+      var hist = this.history;
+      return {undo: hist.done.length, redo: hist.undone.length};
+    },
+    clearHistory: function() {this.history = makeHistory();},
+
+    markClean: function() {
+      this.history.dirtyCounter = 0;
+      this.history.lastOp = this.history.lastOrigin = null;
+    },
+    isClean: function () {return this.history.dirtyCounter == 0;},
+      
+    getHistory: function() {
+      return {done: copyHistoryArray(this.history.done),
+              undone: copyHistoryArray(this.history.undone)};
+    },
+    setHistory: function(histData) {
+      var hist = this.history = makeHistory();
+      hist.done = histData.done.slice(0);
+      hist.undone = histData.undone.slice(0);
+    },
+
+    markText: function(from, to, options) {
+      return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
+    },
+    setBookmark: function(pos, options) {
+      var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
+                      insertLeft: options && options.insertLeft};
+      pos = clipPos(this, pos);
+      return markText(this, pos, pos, realOpts, "bookmark");
+    },
+    findMarksAt: function(pos) {
+      pos = clipPos(this, pos);
+      var markers = [], spans = getLine(this, pos.line).markedSpans;
+      if (spans) for (var i = 0; i < spans.length; ++i) {
+        var span = spans[i];
+        if ((span.from == null || span.from <= pos.ch) &&
+            (span.to == null || span.to >= pos.ch))
+          markers.push(span.marker.parent || span.marker);
+      }
+      return markers;
+    },
+    getAllMarks: function() {
+      var markers = [];
+      this.iter(function(line) {
+        var sps = line.markedSpans;
+        if (sps) for (var i = 0; i < sps.length; ++i)
+          if (sps[i].from != null) markers.push(sps[i].marker);
+      });
+      return markers;
+    },
+
+    posFromIndex: function(off) {
+      var ch, lineNo = this.first;
+      this.iter(function(line) {
+        var sz = line.text.length + 1;
+        if (sz > off) { ch = off; return true; }
+        off -= sz;
+        ++lineNo;
+      });
+      return clipPos(this, Pos(lineNo, ch));
+    },
+    indexFromPos: function (coords) {
+      coords = clipPos(this, coords);
+      var index = coords.ch;
+      if (coords.line < this.first || coords.ch < 0) return 0;
+      this.iter(this.first, coords.line, function (line) {
+        index += line.text.length + 1;
+      });
+      return index;
+    },
+
+    copy: function(copyHistory) {
+      var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
+      doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
+      doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor,
+                 shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn};
+      if (copyHistory) {
+        doc.history.undoDepth = this.history.undoDepth;
+        doc.setHistory(this.getHistory());
+      }
+      return doc;
+    },
+
+    linkedDoc: function(options) {
+      if (!options) options = {};
+      var from = this.first, to = this.first + this.size;
+      if (options.from != null && options.from > from) from = options.from;
+      if (options.to != null && options.to < to) to = options.to;
+      var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
+      if (options.sharedHist) copy.history = this.history;
+      (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
+      copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
+      return copy;
+    },
+    unlinkDoc: function(other) {
+      if (other instanceof CodeMirror) other = other.doc;
+      if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
+        var link = this.linked[i];
+        if (link.doc != other) continue;
+        this.linked.splice(i, 1);
+        other.unlinkDoc(this);
+        break;
+      }
+      // If the histories were shared, split them again
+      if (other.history == this.history) {
+        var splitIds = [other.id];
+        linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
+        other.history = makeHistory();
+        other.history.done = copyHistoryArray(this.history.done, splitIds);
+        other.history.undone = copyHistoryArray(this.history.undone, splitIds);
+      }
+    },
+    iterLinkedDocs: function(f) {linkedDocs(this, f);},
+
+    getMode: function() {return this.mode;},
+    getEditor: function() {return this.cm;}
+  });
+
+  Doc.prototype.eachLine = Doc.prototype.iter;
+
+  // The Doc methods that should be available on CodeMirror instances
+  var dontDelegate = "iter insert remove copy getEditor".split(" ");
+  for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
+    CodeMirror.prototype[prop] = (function(method) {
+      return function() {return method.apply(this.doc, arguments);};
+    })(Doc.prototype[prop]);
+
+  function linkedDocs(doc, f, sharedHistOnly) {
+    function propagate(doc, skip, sharedHist) {
+      if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
+        var rel = doc.linked[i];
+        if (rel.doc == skip) continue;
+        var shared = sharedHist && rel.sharedHist;
+        if (sharedHistOnly && !shared) continue;
+        f(rel.doc, shared);
+        propagate(rel.doc, doc, shared);
+      }
+    }
+    propagate(doc, null, true);
+  }
+
+  function attachDoc(cm, doc) {
+    if (doc.cm) throw new Error("This document is already in use.");
+    cm.doc = doc;
+    doc.cm = cm;
+    estimateLineHeights(cm);
+    loadMode(cm);
+    if (!cm.options.lineWrapping) computeMaxLength(cm);
+    cm.options.mode = doc.modeOption;
+    regChange(cm);
+  }
+
+  // LINE UTILITIES
+
+  function getLine(chunk, n) {
+    n -= chunk.first;
+    while (!chunk.lines) {
+      for (var i = 0;; ++i) {
+        var child = chunk.children[i], sz = child.chunkSize();
+        if (n < sz) { chunk = child; break; }
+        n -= sz;
+      }
+    }
+    return chunk.lines[n];
+  }
+
+  function getBetween(doc, start, end) {
+    var out = [], n = start.line;
+    doc.iter(start.line, end.line + 1, function(line) {
+      var text = line.text;
+      if (n == end.line) text = text.slice(0, end.ch);
+      if (n == start.line) text = text.slice(start.ch);
+      out.push(text);
+      ++n;
+    });
+    return out;
+  }
+  function getLines(doc, from, to) {
+    var out = [];
+    doc.iter(from, to, function(line) { out.push(line.text); });
+    return out;
+  }
+
+  function updateLineHeight(line, height) {
+    var diff = height - line.height;
+    for (var n = line; n; n = n.parent) n.height += diff;
+  }
+
+  function lineNo(line) {
+    if (line.parent == null) return null;
+    var cur = line.parent, no = indexOf(cur.lines, line);
+    for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
+      for (var i = 0;; ++i) {
+        if (chunk.children[i] == cur) break;
+        no += chunk.children[i].chunkSize();
+      }
+    }
+    return no + cur.first;
+  }
+
+  function lineAtHeight(chunk, h) {
+    var n = chunk.first;
+    outer: do {
+      for (var i = 0, e = chunk.children.length; i < e; ++i) {
+        var child = chunk.children[i], ch = child.height;
+        if (h < ch) { chunk = child; continue outer; }
+        h -= ch;
+        n += child.chunkSize();
+      }
+      return n;
+    } while (!chunk.lines);
+    for (var i = 0, e = chunk.lines.length; i < e; ++i) {
+      var line = chunk.lines[i], lh = line.height;
+      if (h < lh) break;
+      h -= lh;
+    }
+    return n + i;
+  }
+
+  function heightAtLine(cm, lineObj) {
+    lineObj = visualLine(cm.doc, lineObj);
+
+    var h = 0, chunk = lineObj.parent;
+    for (var i = 0; i < chunk.lines.length; ++i) {
+      var line = chunk.lines[i];
+      if (line == lineObj) break;
+      else h += line.height;
+    }
+    for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
+      for (var i = 0; i < p.children.length; ++i) {
+        var cur = p.children[i];
+        if (cur == chunk) break;
+        else h += cur.height;
+      }
+    }
+    return h;
+  }
+
+  function getOrder(line) {
+    var order = line.order;
+    if (order == null) order = line.order = bidiOrdering(line.text);
+    return order;
+  }
+
+  // HISTORY
+
+  function makeHistory() {
+    return {
+      // Arrays of history events. Doing something adds an event to
+      // done and clears undo. Undoing moves events from done to
+      // undone, redoing moves them in the other direction.
+      done: [], undone: [], undoDepth: Infinity,
+      // Used to track when changes can be merged into a single undo
+      // event
+      lastTime: 0, lastOp: null, lastOrigin: null,
+      // Used by the isClean() method
+      dirtyCounter: 0
+    };
+  }
+
+  function attachLocalSpans(doc, change, from, to) {
+    var existing = change["spans_" + doc.id], n = 0;
+    doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
+      if (line.markedSpans)
+        (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
+      ++n;
+    });
+  }
+
+  function historyChangeFromChange(doc, change) {
+    var histChange = {from: change.from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
+    attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
+    linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
+    return histChange;
+  }
+
+  function addToHistory(doc, change, selAfter, opId) {
+    var hist = doc.history;
+    hist.undone.length = 0;
+    var time = +new Date, cur = lst(hist.done);
+
+    if (cur &&
+        (hist.lastOp == opId ||
+         hist.lastOrigin == change.origin && change.origin &&
+         ((change.origin.charAt(0) == "+" && hist.lastTime > time - 600) || change.origin.charAt(0) == "*"))) {
+      // Merge this change into the last event
+      var last = lst(cur.changes);
+      if (posEq(change.from, change.to) && posEq(change.from, last.to)) {
+        // Optimized case for simple insertion -- don't want to add
+        // new changesets for every character typed
+        last.to = changeEnd(change);
+      } else {
+        // Add new sub-event
+        cur.changes.push(historyChangeFromChange(doc, change));
+      }
+      cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head;
+    } else {
+      // Can not be merged, start a new event.
+      cur = {changes: [historyChangeFromChange(doc, change)],
+             anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
+             anchorAfter: selAfter.anchor, headAfter: selAfter.head};
+      hist.done.push(cur);
+      while (hist.done.length > hist.undoDepth)
+        hist.done.shift();
+      if (hist.dirtyCounter < 0)
+        // The user has made a change after undoing past the last clean state. 
+        // We can never get back to a clean state now until markClean() is called.
+        hist.dirtyCounter = NaN;
+      else
+        hist.dirtyCounter++;
+    }
+    hist.lastTime = time;
+    hist.lastOp = opId;
+    hist.lastOrigin = change.origin;
+  }
+
+  function removeClearedSpans(spans) {
+    if (!spans) return null;
+    for (var i = 0, out; i < spans.length; ++i) {
+      if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
+      else if (out) out.push(spans[i]);
+    }
+    return !out ? spans : out.length ? out : null;
+  }
+
+  function getOldSpans(doc, change) {
+    var found = change["spans_" + doc.id];
+    if (!found) return null;
+    for (var i = 0, nw = []; i < change.text.length; ++i)
+      nw.push(removeClearedSpans(found[i]));
+    return nw;
+  }
+
+  // Used both to provide a JSON-safe object in .getHistory, and, when
+  // detaching a document, to split the history in two
+  function copyHistoryArray(events, newGroup) {
+    for (var i = 0, copy = []; i < events.length; ++i) {
+      var event = events[i], changes = event.changes, newChanges = [];
+      copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore,
+                 anchorAfter: event.anchorAfter, headAfter: event.headAfter});
+      for (var j = 0; j < changes.length; ++j) {
+        var change = changes[j], m;
+        newChanges.push({from: change.from, to: change.to, text: change.text});
+        if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
+          if (indexOf(newGroup, Number(m[1])) > -1) {
+            lst(newChanges)[prop] = change[prop];
+            delete change[prop];
+          }
+        }
+      }
+    }
+    return copy;
+  }
+
+  // Rebasing/resetting history to deal with externally-sourced changes
+
+  function rebaseHistSel(pos, from, to, diff) {
+    if (to < pos.line) {
+      pos.line += diff;
+    } else if (from < pos.line) {
+      pos.line = from;
+      pos.ch = 0;
+    }
+  }
+
+  // Tries to rebase an array of history events given a change in the
+  // document. If the change touches the same lines as the event, the
+  // event, and everything 'behind' it, is discarded. If the change is
+  // before the event, the event's positions are updated. Uses a
+  // copy-on-write scheme for the positions, to avoid having to
+  // reallocate them all on every rebase, but also avoid problems with
+  // shared position objects being unsafely updated.
+  function rebaseHistArray(array, from, to, diff) {
+    for (var i = 0; i < array.length; ++i) {
+      var sub = array[i], ok = true;
+      for (var j = 0; j < sub.changes.length; ++j) {
+        var cur = sub.changes[j];
+        if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); }
+        if (to < cur.from.line) {
+          cur.from.line += diff;
+          cur.to.line += diff;
+        } else if (from <= cur.to.line) {
+          ok = false;
+          break;
+        }
+      }
+      if (!sub.copied) {
+        sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore);
+        sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter);
+        sub.copied = true;
+      }
+      if (!ok) {
+        array.splice(0, i + 1);
+        i = 0;
+      } else {
+        rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore);
+        rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter);
+      }
+    }
+  }
+
+  function rebaseHist(hist, change) {
+    var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
+    rebaseHistArray(hist.done, from, to, diff);
+    rebaseHistArray(hist.undone, from, to, diff);
+  }
+
+  // EVENT OPERATORS
+
+  function stopMethod() {e_stop(this);}
+  // Ensure an event has a stop method.
+  function addStop(event) {
+    if (!event.stop) event.stop = stopMethod;
+    return event;
+  }
+
+  function e_preventDefault(e) {
+    if (e.preventDefault) e.preventDefault();
+    else e.returnValue = false;
+  }
+  function e_stopPropagation(e) {
+    if (e.stopPropagation) e.stopPropagation();
+    else e.cancelBubble = true;
+  }
+  function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
+  CodeMirror.e_stop = e_stop;
+  CodeMirror.e_preventDefault = e_preventDefault;
+  CodeMirror.e_stopPropagation = e_stopPropagation;
+
+  function e_target(e) {return e.target || e.srcElement;}
+  function e_button(e) {
+    var b = e.which;
+    if (b == null) {
+      if (e.button & 1) b = 1;
+      else if (e.button & 2) b = 3;
+      else if (e.button & 4) b = 2;
+    }
+    if (mac && e.ctrlKey && b == 1) b = 3;
+    return b;
+  }
+
+  // EVENT HANDLING
+
+  function on(emitter, type, f) {
+    if (emitter.addEventListener)
+      emitter.addEventListener(type, f, false);
+    else if (emitter.attachEvent)
+      emitter.attachEvent("on" + type, f);
+    else {
+      var map = emitter._handlers || (emitter._handlers = {});
+      var arr = map[type] || (map[type] = []);
+      arr.push(f);
+    }
+  }
+
+  function off(emitter, type, f) {
+    if (emitter.removeEventListener)
+      emitter.removeEventListener(type, f, false);
+    else if (emitter.detachEvent)
+      emitter.detachEvent("on" + type, f);
+    else {
+      var arr = emitter._handlers && emitter._handlers[type];
+      if (!arr) return;
+      for (var i = 0; i < arr.length; ++i)
+        if (arr[i] == f) { arr.splice(i, 1); break; }
+    }
+  }
+
+  function signal(emitter, type /*, values...*/) {
+    var arr = emitter._handlers && emitter._handlers[type];
+    if (!arr) return;
+    var args = Array.prototype.slice.call(arguments, 2);
+    for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
+  }
+
+  var delayedCallbacks, delayedCallbackDepth = 0;
+  function signalLater(emitter, type /*, values...*/) {
+    var arr = emitter._handlers && emitter._handlers[type];
+    if (!arr) return;
+    var args = Array.prototype.slice.call(arguments, 2);
+    if (!delayedCallbacks) {
+      ++delayedCallbackDepth;
+      delayedCallbacks = [];
+      setTimeout(fireDelayed, 0);
+    }
+    function bnd(f) {return function(){f.apply(null, args);};};
+    for (var i = 0; i < arr.length; ++i)
+      delayedCallbacks.push(bnd(arr[i]));
+  }
+
+  function fireDelayed() {
+    --delayedCallbackDepth;
+    var delayed = delayedCallbacks;
+    delayedCallbacks = null;
+    for (var i = 0; i < delayed.length; ++i) delayed[i]();
+  }
+
+  function hasHandler(emitter, type) {
+    var arr = emitter._handlers && emitter._handlers[type];
+    return arr && arr.length > 0;
+  }
+
+  CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
+
+  // MISC UTILITIES
+
+  // Number of pixels added to scroller and sizer to hide scrollbar
+  var scrollerCutOff = 30;
+
+  // Returned or thrown by various protocols to signal 'I'm not
+  // handling this'.
+  var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
+
+  function Delayed() {this.id = null;}
+  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
+
+  // Counts the column offset in a string, taking tabs into account.
+  // Used mostly to find indentation.
+  function countColumn(string, end, tabSize) {
+    if (end == null) {
+      end = string.search(/[^\s\u00a0]/);
+      if (end == -1) end = string.length;
+    }
+    for (var i = 0, n = 0; i < end; ++i) {
+      if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
+      else ++n;
+    }
+    return n;
+  }
+  CodeMirror.countColumn = countColumn;
+
+  var spaceStrs = [""];
+  function spaceStr(n) {
+    while (spaceStrs.length <= n)
+      spaceStrs.push(lst(spaceStrs) + " ");
+    return spaceStrs[n];
+  }
+
+  function lst(arr) { return arr[arr.length-1]; }
+
+  function selectInput(node) {
+    if (ios) { // Mobile Safari apparently has a bug where select() is broken.
+      node.selectionStart = 0;
+      node.selectionEnd = node.value.length;
+    } else node.select();
+  }
+
+  function indexOf(collection, elt) {
+    if (collection.indexOf) return collection.indexOf(elt);
+    for (var i = 0, e = collection.length; i < e; ++i)
+      if (collection[i] == elt) return i;
+    return -1;
+  }
+
+  function createObj(base, props) {
+    function Obj() {}
+    Obj.prototype = base;
+    var inst = new Obj();
+    if (props) copyObj(props, inst);
+    return inst;
+  }
+
+  function copyObj(obj, target) {
+    if (!target) target = {};
+    for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
+    return target;
+  }
+
+  function emptyArray(size) {
+    for (var a = [], i = 0; i < size; ++i) a.push(undefined);
+    return a;
+  }
+
+  function bind(f) {
+    var args = Array.prototype.slice.call(arguments, 1);
+    return function(){return f.apply(null, args);};
+  }
+
+  var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/;
+  function isWordChar(ch) {
+    return /\w/.test(ch) || ch > "\x80" &&
+      (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
+  }
+
+  function isEmpty(obj) {
+    for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
+    return true;
+  }
+
+  var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;
+
+  // DOM UTILITIES
+
+  function elt(tag, content, className, style) {
+    var e = document.createElement(tag);
+    if (className) e.className = className;
+    if (style) e.style.cssText = style;
+    if (typeof content == "string") setTextContent(e, content);
+    else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
+    return e;
+  }
+
+  function removeChildren(e) {
+    // IE will break all parent-child relations in subnodes when setting innerHTML
+    if (!ie) e.innerHTML = "";
+    else while (e.firstChild) e.removeChild(e.firstChild);
+    return e;
+  }
+
+  function removeChildrenAndAdd(parent, e) {
+    return removeChildren(parent).appendChild(e);
+  }
+
+  function setTextContent(e, str) {
+    if (ie_lt9) {
+      e.innerHTML = "";
+      e.appendChild(document.createTextNode(str));
+    } else e.textContent = str;
+  }
+
+  function getRect(node) {
+    return node.getBoundingClientRect();
+  }
+  CodeMirror.replaceGetRect = function(f) { getRect = f; };
+
+  // FEATURE DETECTION
+
+  // Detect drag-and-drop
+  var dragAndDrop = function() {
+    // There is *some* kind of drag-and-drop support in IE6-8, but I
+    // couldn't get it to work yet.
+    if (ie_lt9) return false;
+    var div = elt('div');
+    return "draggable" in div || "dragDrop" in div;
+  }();
+
+  // For a reason I have yet to figure out, some browsers disallow
+  // word wrapping between certain characters *only* if a new inline
+  // element is started between them. This makes it hard to reliably
+  // measure the position of things, since that requires inserting an
+  // extra span. This terribly fragile set of regexps matches the
+  // character combinations that suffer from this phenomenon on the
+  // various browsers.
+  var spanAffectsWrapping = /^$/; // Won't match any two-character string
+  if (gecko) spanAffectsWrapping = /$'/;
+  else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
+  else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/;
+
+  var knownScrollbarWidth;
+  function scrollbarWidth(measure) {
+    if (knownScrollbarWidth != null) return knownScrollbarWidth;
+    var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
+    removeChildrenAndAdd(measure, test);
+    if (test.offsetWidth)
+      knownScrollbarWidth = test.offsetHeight - test.clientHeight;
+    return knownScrollbarWidth || 0;
+  }
+
+  var zwspSupported;
+  function zeroWidthElement(measure) {
+    if (zwspSupported == null) {
+      var test = elt("span", "\u200b");
+      removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
+      if (measure.firstChild.offsetHeight != 0)
+        zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;
+    }
+    if (zwspSupported) return elt("span", "\u200b");
+    else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
+  }
+
+  // See if "".split is the broken IE version, if so, provide an
+  // alternative way to split lines.
+  var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
+    var pos = 0, result = [], l = string.length;
+    while (pos <= l) {
+      var nl = string.indexOf("\n", pos);
+      if (nl == -1) nl = string.length;
+      var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
+      var rt = line.indexOf("\r");
+      if (rt != -1) {
+        result.push(line.slice(0, rt));
+        pos += rt + 1;
+      } else {
+        result.push(line);
+        pos = nl + 1;
+      }
+    }
+    return result;
+  } : function(string){return string.split(/\r\n?|\n/);};
+  CodeMirror.splitLines = splitLines;
+
+  var hasSelection = window.getSelection ? function(te) {
+    try { return te.selectionStart != te.selectionEnd; }
+    catch(e) { return false; }
+  } : function(te) {
+    try {var range = te.ownerDocument.selection.createRange();}
+    catch(e) {}
+    if (!range || range.parentElement() != te) return false;
+    return range.compareEndPoints("StartToEnd", range) != 0;
+  };
+
+  var hasCopyEvent = (function() {
+    var e = elt("div");
+    if ("oncopy" in e) return true;
+    e.setAttribute("oncopy", "return;");
+    return typeof e.oncopy == 'function';
+  })();
+
+  // KEY NAMING
+
+  var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
+                  19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
+                  36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
+                  46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
+                  186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
+                  221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
+                  63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
+  CodeMirror.keyNames = keyNames;
+  (function() {
+    // Number keys
+    for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
+    // Alphabetic keys
+    for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
+    // Function keys
+    for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
+  })();
+
+  // BIDI HELPERS
+
+  function iterateBidiSections(order, from, to, f) {
+    if (!order) return f(from, to, "ltr");
+    for (var i = 0; i < order.length; ++i) {
+      var part = order[i];
+      if (part.from < to && part.to > from || from == to && part.to == from)
+        f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
+    }
+  }
+
+  function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
+  function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
+
+  function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
+  function lineRight(line) {
+    var order = getOrder(line);
+    if (!order) return line.text.length;
+    return bidiRight(lst(order));
+  }
+
+  function lineStart(cm, lineN) {
+    var line = getLine(cm.doc, lineN);
+    var visual = visualLine(cm.doc, line);
+    if (visual != line) lineN = lineNo(visual);
+    var order = getOrder(visual);
+    var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
+    return Pos(lineN, ch);
+  }
+  function lineEnd(cm, lineN) {
+    var merged, line;
+    while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN)))
+      lineN = merged.find().to.line;
+    var order = getOrder(line);
+    var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
+    return Pos(lineN, ch);
+  }
+
+  // This is somewhat involved. It is needed in order to move
+  // 'visually' through bi-directional text -- i.e., pressing left
+  // should make the cursor go left, even when in RTL text. The
+  // tricky part is the 'jumps', where RTL and LTR text touch each
+  // other. This often requires the cursor offset to move more than
+  // one unit, in order to visually move one unit.
+  function moveVisually(line, start, dir, byUnit) {
+    var bidi = getOrder(line);
+    if (!bidi) return moveLogically(line, start, dir, byUnit);
+    var moveOneUnit = byUnit ? function(pos, dir) {
+      do pos += dir;
+      while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
+      return pos;
+    } : function(pos, dir) { return pos + dir; };
+    var linedir = bidi[0].level;
+    for (var i = 0; i < bidi.length; ++i) {
+      var part = bidi[i], sticky = part.level % 2 == linedir;
+      if ((part.from < start && part.to > start) ||
+          (sticky && (part.from == start || part.to == start))) break;
+    }
+    var target = moveOneUnit(start, part.level % 2 ? -dir : dir);
+
+    while (target != null) {
+      if (part.level % 2 == linedir) {
+        if (target < part.from || target > part.to) {
+          part = bidi[i += dir];
+          target = part && (dir > 0 == part.level % 2 ? moveOneUnit(part.to, -1) : moveOneUnit(part.from, 1));
+        } else break;
+      } else {
+        if (target == bidiLeft(part)) {
+          part = bidi[--i];
+          target = part && bidiRight(part);
+        } else if (target == bidiRight(part)) {
+          part = bidi[++i];
+          target = part && bidiLeft(part);
+        } else break;
+      }
+    }
+
+    return target < 0 || target > line.text.length ? null : target;
+  }
+
+  function moveLogically(line, start, dir, byUnit) {
+    var target = start + dir;
+    if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir;
+    return target < 0 || target > line.text.length ? null : target;
+  }
+
+  // Bidirectional ordering algorithm
+  // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
+  // that this (partially) implements.
+
+  // One-char codes used for character types:
+  // L (L):   Left-to-Right
+  // R (R):   Right-to-Left
+  // r (AL):  Right-to-Left Arabic
+  // 1 (EN):  European Number
+  // + (ES):  European Number Separator
+  // % (ET):  European Number Terminator
+  // n (AN):  Arabic Number
+  // , (CS):  Common Number Separator
+  // m (NSM): Non-Spacing Mark
+  // b (BN):  Boundary Neutral
+  // s (B):   Paragraph Separator
+  // t (S):   Segment Separator
+  // w (WS):  Whitespace
+  // N (ON):  Other Neutrals
+
+  // Returns null if characters are ordered as they appear
+  // (left-to-right), or an array of sections ({from, to, level}
+  // objects) in the order in which they occur visually.
+  var bidiOrdering = (function() {
+    // Character types for codepoints 0 to 0xff
+    var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";
+    // Character types for codepoints 0x600 to 0x6ff
+    var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";
+    function charType(code) {
+      if (code <= 0xff) return lowTypes.charAt(code);
+      else if (0x590 <= code && code <= 0x5f4) return "R";
+      else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);
+      else if (0x700 <= code && code <= 0x8ac) return "r";
+      else return "L";
+    }
+
+    var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
+    var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
+    // Browsers seem to always treat the boundaries of block elements as being L.
+    var outerType = "L";
+
+    return function(str) {
+      if (!bidiRE.test(str)) return false;
+      var len = str.length, types = [];
+      for (var i = 0, type; i < len; ++i)
+        types.push(type = charType(str.charCodeAt(i)));
+
+      // W1. Examine each non-spacing mark (NSM) in the level run, and
+      // change the type of the NSM to the type of the previous
+      // character. If the NSM is at the start of the level run, it will
+      // get the type of sor.
+      for (var i = 0, prev = outerType; i < len; ++i) {
+        var type = types[i];
+        if (type == "m") types[i] = prev;
+        else prev = type;
+      }
+
+      // W2. Search backwards from each instance of a European number
+      // until the first strong type (R, L, AL, or sor) is found. If an
+      // AL is found, change the type of the European number to Arabic
+      // number.
+      // W3. Change all ALs to R.
+      for (var i = 0, cur = outerType; i < len; ++i) {
+        var type = types[i];
+        if (type == "1" && cur == "r") types[i] = "n";
+        else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
+      }
+
+      // W4. A single European separator between two European numbers
+      // changes to a European number. A single common separator between
+      // two numbers of the same type changes to that type.
+      for (var i = 1, prev = types[0]; i < len - 1; ++i) {
+        var type = types[i];
+        if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
+        else if (type == "," && prev == types[i+1] &&
+                 (prev == "1" || prev == "n")) types[i] = prev;
+        prev = type;
+      }
+
+      // W5. A sequence of European terminators adjacent to European
+      // numbers changes to all European numbers.
+      // W6. Otherwise, separators and terminators change to Other
+      // Neutral.
+      for (var i = 0; i < len; ++i) {
+        var type = types[i];
+        if (type == ",") types[i] = "N";
+        else if (type == "%") {
+          for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
+          var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N";
+          for (var j = i; j < end; ++j) types[j] = replace;
+          i = end - 1;
+        }
+      }
+
+      // W7. Search backwards from each instance of a European number
+      // until the first strong type (R, L, or sor) is found. If an L is
+      // found, then change the type of the European number to L.
+      for (var i = 0, cur = outerType; i < len; ++i) {
+        var type = types[i];
+        if (cur == "L" && type == "1") types[i] = "L";
+        else if (isStrong.test(type)) cur = type;
+      }
+
+      // N1. A sequence of neutrals takes the direction of the
+      // surrounding strong text if the text on both sides has the same
+      // direction. European and Arabic numbers act as if they were R in
+      // terms of their influence on neutrals. Start-of-level-run (sor)
+      // and end-of-level-run (eor) are used at level run boundaries.
+      // N2. Any remaining neutrals take the embedding direction.
+      for (var i = 0; i < len; ++i) {
+        if (isNeutral.test(types[i])) {
+          for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
+          var before = (i ? types[i-1] : outerType) == "L";
+          var after = (end < len - 1 ? types[end] : outerType) == "L";
+          var replace = before || after ? "L" : "R";
+          for (var j = i; j < end; ++j) types[j] = replace;
+          i = end - 1;
+        }
+      }
+
+      // Here we depart from the documented algorithm, in order to avoid
+      // building up an actual levels array. Since there are only three
+      // levels (0, 1, 2) in an implementation that doesn't take
+      // explicit embedding into account, we can build up the order on
+      // the fly, without following the level-based algorithm.
+      var order = [], m;
+      for (var i = 0; i < len;) {
+        if (countsAsLeft.test(types[i])) {
+          var start = i;
+          for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
+          order.push({from: start, to: i, level: 0});
+        } else {
+          var pos = i, at = order.length;
+          for (++i; i < len && types[i] != "L"; ++i) {}
+          for (var j = pos; j < i;) {
+            if (countsAsNum.test(types[j])) {
+              if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});
+              var nstart = j;
+              for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
+              order.splice(at, 0, {from: nstart, to: j, level: 2});
+              pos = j;
+            } else ++j;
+          }
+          if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});
+        }
+      }
+      if (order[0].level == 1 && (m = str.match(/^\s+/))) {
+        order[0].from = m[0].length;
+        order.unshift({from: 0, to: m[0].length, level: 0});
+      }
+      if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
+        lst(order).to -= m[0].length;
+        order.push({from: len - m[0].length, to: len, level: 0});
+      }
+      if (order[0].level != lst(order).level)
+        order.push({from: len, to: len, level: order[0].level});
+
+      return order;
+    };
+  })();
+
+  // THE END
+
+  CodeMirror.version = "3.1";
+
+  return CodeMirror;
+})();
diff --git a/doc/asset/js/echartsConfig.js b/doc/asset/js/echartsConfig.js
new file mode 100644
index 0000000..f25ce6e
--- /dev/null
+++ b/doc/asset/js/echartsConfig.js
@@ -0,0 +1,331 @@
+/*

+ * echarts默认配置项

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+//define(function() {

+    // 请原谅我这样写,这显然可以直接返回个对象,但那样的话outline就显示不出来了~~

+    var echartsConfig = {

+        // 图例

+        legend: {

+            orient: 'horizontal',      // 布局方式,默认为水平布局,可选为:

+                                       // 'horizontal' ¦ 'vertical'

+            x: 'center',               // 水平安放位置,默认为全图居中,可选为:

+                                       // 'center' ¦ 'left' ¦ 'right'

+                                       // ¦ {number}(x坐标,单位px)

+            y: 'top',                  // 垂直安放位置,默认为全图顶端,可选为:

+                                       // 'top' ¦ 'bottom' ¦ 'center'

+                                       // ¦ {number}(y坐标,单位px)

+            backgroundColor: 'rgba(0,0,0,0)',

+            borderColor: '#ccc',       // 图例边框颜色

+            borderWidth: 0,            // 图例边框线宽,单位px,默认为0(无边框)

+            padding: 5,                // 图例内边距,单位px,默认各方向内边距为5,

+                                       // 接受数组分别设定上右下左边距,同css

+            itemGap: 10,               // 各个item之间的间隔,单位px,默认为10,

+                                       // 横向布局时为水平间隔,纵向布局时为纵向间隔

+            // data: []                // 图例内容(详见legend.data,数组中每一项代表一个item

+            itemWidth: 20,             // 图例图形宽度,非标准参数

+            itemHeight: 14,            // 图例图形高度,非标准参数

+            textStyle: {

+                color: '#333'          // 图例文字颜色

+            }

+        },

+

+        toolbox: {

+            show : false,

+            orient: 'horizontal',      // 布局方式,默认为水平布局,可选为:

+                                       // 'horizontal' ¦ 'vertical'

+            x: 'right',                // 水平安放位置,默认为全图右对齐,可选为:

+                                       // 'center' ¦ 'left' ¦ 'right'

+                                       // ¦ {number}(x坐标,单位px)

+            y: 'top',                  // 垂直安放位置,默认为全图顶端,可选为:

+                                       // 'top' ¦ 'bottom' ¦ 'center'

+                                       // ¦ {number}(y坐标,单位px)

+            color : ['#1e90ff','#22bb22','#4b0082','#d2691e'],

+            backgroundColor: 'rgba(0,0,0,0)', // 工具箱背景颜色

+            borderColor: '#ccc',       // 工具箱边框颜色

+            borderWidth: 0,            // 工具箱边框线宽,单位px,默认为0(无边框)

+            padding: 5,                // 工具箱内边距,单位px,默认各方向内边距为5,

+                                       // 接受数组分别设定上右下左边距,同css

+            itemGap: 10,               // 各个item之间的间隔,单位px,默认为10,

+                                       // 横向布局时为水平间隔,纵向布局时为纵向间隔

+            itemSize: 16,             // 工具箱图形宽度,非标准参数

+            feature : {

+                //mark : false,

+                //refresh : false,

+                //magicType: []

+            }

+        },

+

+        // 提示框

+        tooltip: {

+            show: true,

+            trigger: 'item',           // 触发类型,默认数据触发,见下图,可选为:'item' ¦ 'axis'

+            // formatter: null         // 内容格式器:{string}(Template) ¦ {Function}

+            islandFormatter: '{a} <br/>{b} : {c}',  // 数据孤岛内容格式器,非标准参数

+            backgroundColor: 'rgba(0,0,0,0.7)',     // 提示背景颜色,默认为透明度为0.7的黑色

+            borderColor: '#333',       // 提示边框颜色

+            borderRadius: 4,           // 提示边框圆角,单位px,默认为4

+            borderWidth: 0,            // 提示边框线宽,单位px,默认为0(无边框)

+            padding: 5,                // 提示内边距,单位px,默认各方向内边距为5,

+                                       // 接受数组分别设定上右下左边距,同css

+            textStyle: {

+                color: '#fff'

+            }

+        },

+

+        // 区域缩放控制器

+        dataZoom: {

+            show: false,

+            realtime: false,

+            orient: 'horizontal',          // 布局方式,默认为水平布局,可选为:

+                                           // 'horizontal' ¦ 'vertical'

+            backgroundColor: '#eee',       // 背景颜色

+            dataBackgroundColor: '#ccc',   // 数据背景颜色

+            fillerColor: 'rgba(50,205,50,0.4)',        // 填充颜色

+            handleColor: 'rgba(70,130,180,0.8)'         // 手柄颜色

+

+            // x: {number},            // 水平安放位置,默认为根据grid参数适配,可选为:

+                                       // {number}(x坐标,单位px)

+            // y: {number},            // 垂直安放位置,默认为根据grid参数适配,可选为:

+                                       // {number}(y坐标,单位px)

+            // width: {number},        // 指定宽度,横向布局时默认为根据grid参数适配

+            // height: {number},       // 指定高度,纵向布局时默认为根据grid参数适配

+            // xAxisIndex: [],         // 默认控制所有横向类目

+            // yAxisIndex: [],         // 默认控制所有横向类目

+            // start: 0,               // 默认为0

+            // end: 100,               // 默认为全部 100%

+            // zoomLock: false         // 是否锁定选择区域大小

+        },

+

+        // 网格

+        grid: {

+            x: 80,

+            y: 60,

+            // width: {totalWidth} - (2 * x),

+            // height: {totalHeight} - (2 * y)

+            backgroundColor: '#fff',

+            borderWidth: 1,

+            borderColor: '#ccc'

+        },

+

+        // 类目轴

+        categoryAxis: {

+            position: 'bottom',    // 位置

+            boundaryGap: true,     // 类目起始和结束两端空白策略

+            axisLine: {            // 坐标轴线

+                show: true,        // 默认显示,属性show控制显示与否

+                lineStyle: {       // 属性lineStyle控制线条样式

+                    color: '#48b',

+                    width: 2,

+                    style: 'solid'

+                }

+            },

+            axisTick: {            // 坐标轴小标记

+                show: false,       // 属性show控制显示与否,默认不显示

+                length :4,         // 属性length控制线长

+                lineStyle: {       // 属性lineStyle控制线条样式

+                    color: '#ccc',

+                    width: 1

+                }

+            },

+            axisLabel: {           // 坐标轴文本标签,详见axis.axisLabel

+                show: true,

+                interval: 'auto',

+                rotate: 0,

+                margin:  8,

+                // formatter: null,

+                textStyle: {       // 其余属性默认使用全局文本样式,详见TEXTSTYLE

+                    color: '#333'

+                }

+            },

+            splitLine: {           // 分隔线

+                show: true,        // 默认显示,属性show控制显示与否

+                lineStyle: {       // 属性lineStyle(详见lineStyle)控制线条样式

+                    color: '#ccc',

+                    width: 1,

+                    style: 'solid'

+                }

+            },

+            splitArea: {           // 分隔区域

+                show: false,       // 默认不显示,属性show控制显示与否

+                areaStyle: {       // 属性areaStyle(详见areaStyle)控制区域样式

+                    color: ['rgba(250,250,250,0.3)','rgba(200,200,200,0.3)'],

+                    type: 'default'

+                }

+            }

+        },

+        // 数值型坐标轴默认参数

+        valueAxis: {

+            position: 'left',      // 位置

+            boundaryGap: [0, 0],   // 数值起始和结束两端空白策略

+            // min: null,          // 最小值

+            // max: null,          // 最大值

+            precision: 0,          // 小数精度,默认为0,无小数点

+            power: 100,            // 整数精度,默认为100,个位和百位为0

+            splitNumber: 5,        // 分割段数,默认为5

+            axisLine: {            // 坐标轴线

+                show: true,        // 默认显示,属性show控制显示与否

+                lineStyle: {       // 属性lineStyle控制线条样式

+                    color: '#48b',

+                    width: 2,

+                    style: 'solid'

+                }

+            },

+            axisTick: {            // 坐标轴小标记

+                show: false,       // 属性show控制显示与否,默认不显示

+                length :4,         // 属性length控制线长

+                lineStyle: {       // 属性lineStyle控制线条样式

+                    color: '#ccc',

+                    width: 1

+                }

+            },

+            axisLabel: {           // 坐标轴文本标签,详见axis.axisLabel

+                show: true,

+                rotate: 0,

+                margin: 8,

+                // formatter: null,

+                textStyle: {       // 其余属性默认使用全局文本样式,详见TEXTSTYLE

+                    color: '#333'

+                }

+            },

+            splitLine: {           // 分隔线

+                show: true,        // 默认显示,属性show控制显示与否

+                lineStyle: {       // 属性lineStyle(详见lineStyle)控制线条样式

+                    color: '#ccc',

+                    width: 1,

+                    style: 'solid'

+                }

+            },

+            splitArea: {           // 分隔区域

+                show: false,       // 默认不显示,属性show控制显示与否

+                areaStyle: {       // 属性areaStyle(详见areaStyle)控制区域样式

+                    color: ['rgba(250,250,250,0.3)','rgba(200,200,200,0.3)'],

+                    type: 'default'

+                }

+            }

+        },

+        // 柱形图默认参数

+        bar: {

+            // stack: null

+            xAxisIndex: 0,

+            yAxisIndex: 0,

+            barMinHeight: 20

+            // barWidth: null        // 默认自适应

+        },

+

+        // 折线图默认参数

+        line: {

+            // stack: null

+            xAxisIndex: 0,

+            yAxisIndex: 0,

+            itemStyle: {

+                normal: {

+                        // color: 各异,

+                    lineStyle: {

+                        width: 1,

+                        style: 'solid'

+                    }

+                },

+                emphasis: {

+                        // color: 各异,

+                }

+            },

+            //brokenPoint: null,     // 拐点图形类型,非标准参数

+            brokenPointSize: 4           // 可计算特性参数,空数据拖拽提示图形大小

+        },

+

+        // 饼图默认参数

+        pie: {

+            // center: null,                   // 默认全局居中

+            // radius: [0, min(width,height) - 50],

+            startAngle: 0,

+            minAngle: 5,

+            itemStyle: {

+                normal: {

+                    label: {

+                        show: true,

+                        position: 'outer'

+                        // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE

+                    },

+                    labelLine: {

+                        show: true,

+                        length: 30,

+                        lineStyle: {

+                            // color: 各异,

+                            width: 1,

+                            style: 'solid'

+                        }

+                    }

+                },

+                emphasis: {

+                    label: {

+                        show: false,

+                        position: 'outer'

+                        // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE

+                    },

+                    labelLine: {

+                        show: false,

+                        length: 40,

+                        lineStyle: {

+                            // color: 各异,

+                            width: 1,

+                            style: 'solid'

+                        }

+                    }

+                }

+            }

+        },

+        island: {

+            r: 15,

+            calculateStep: 0.1  // 滚轮可计算步长 0.1 = 10%

+        },

+

+        textStyle: {

+            decoration: 'none',

+            fontFamily: 'Arial, Verdana, sans-serif',

+            fontSize: 12,

+            fontStyle: 'normal',

+            fontWeight: 'normal'

+        },

+

+        // 默认色板

+        color: ['#ff7f50','#87cefa','#da70d6','#32cd32','#6495ed',

+                '#ff69b4','#ba55d3','#cd5c5c','#ffa500','#40e0d0',

+                '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',

+                '#6b8e23','#ff00ff','#3cb371','#b8860b','#30e0e0'],

+        // 可计算特性配置,孤岛,提示颜色

+        calculable: false,              // 默认开启可计算特性

+        calculableColor: 'rgba(255,165,0,0.6)',       // 拖拽提示边框颜色

+        calculableHolderColor: '#ccc', // 可计算占位提示颜色

+        nameConnector: ' & ',

+        valueConnector: ' : ',

+        animation: true,

+        animationDuration: 2000,

+        animationEasing: 'BounceOut',

+

+        // 图表类型

+        CHART_TYPE_LINE: 'line',

+        CHART_TYPE_BAR: 'bar',

+        // CHART_TYPE_SCATTER: 'scatter',

+        CHART_TYPE_PIE: 'pie',

+        // CHART_TYPE_RADAR: 'radar',

+        // CHART_TYPE_ISLAND: 'island',

+        // 事件类型

+        EVENT: {

+            REFRESH: 'refresh',

+            CLICK: 'click',

+            HOVER: 'hover',

+            // -------

+            DATA_CHANGED: 'dataChanged',

+            DATA_ZOOM: 'dataZoom',

+            LEGEND_SELECTED: 'legendSelected',

+            MAGIC_TYPE_CHANGED: 'magicTypeChanged',

+            DATA_VIEW_CHANGED: 'dataViewChanged'

+        }

+    };

+//    return config;

+//});
\ No newline at end of file
diff --git a/doc/asset/js/echartsDoc.js b/doc/asset/js/echartsDoc.js
new file mode 100644
index 0000000..eca8523
--- /dev/null
+++ b/doc/asset/js/echartsDoc.js
@@ -0,0 +1,148 @@
+function JsonTree(jsonData) {
+    function isArray(o) {
+        if (Array.isArray) {
+            return Array.isArray(o);
+        }
+        if (Object.prototype.toString.call(o) === '[object Array]') {
+            return true;
+        }
+        return false;
+    }
+
+    function htmlEncode(str) {
+        var div = document.createElement("div");
+        div.appendChild(document.createTextNode(str));
+        return div.innerHTML;
+    }
+
+    //building the jsonData as dom elements
+    this.getTree = function(domId) {
+        if (this.display === true) {
+            return;
+        } else {
+            this.display = true;
+        }
+        var html = '';
+        var dataType = isArray(jsonData) ? 'arr' : '';
+        var tree = document.createElement('div');
+        tree.id = domId || "tree";
+        tree.className = 'tree';
+        //tree.id = "JsonViewer";
+        tree.innerHTML = buildDom(jsonData, dataType);
+        bindEvents(tree);
+        return tree;
+    }
+    //building doms
+    function buildDom(o, literal) {
+        // null object
+        var type = o === null
+                   ? 'null'
+                   : (isArray(o) ? 'array' : typeof o);
+        var html = '';
+
+        switch(type) {
+            case 'array' :
+                for (var i = 0, len = o.length; i < len; i++) {
+                    html += '<li class = \'tree-close\' title=\''
+                            + literal + '[' + i + ']\'><strong>'
+                            + i + '</strong>:'
+                            + buildDom(o[i], literal + '[' + i + ']')
+                            + ',</li>';
+                }
+                return '<span class="operator">+</span><div class="group">'
+                       + '[<ul class="' + type + '">'
+                       + html.replace(/,<\/li>$/, '<\/li>')
+                       + '</ul>]</div><div class="summary">Array['
+                       + len + ']</div>';
+                break;
+            case 'object':
+                //sort obj
+                //var keys = Object.keys(o);
+                //keys.sort();
+                for (var key in o) {
+                    //quote numeric property
+                    if (/^\d+$/.test(key)) {
+                        html += '<li class = \'tree-close\' title=\'' + literal
+                                + '["' + key + '"]\'><strong>"'
+                                + key + '"</strong>:'
+                                + buildDom(
+                                    o[key], literal + '["' + key + '"]'
+                                  )
+                                + ',</li>';
+                    } else {
+                        html += '<li class = \'tree-close\' title=\''
+                                + key
+                                + '\'><a href=\'#' + (literal == '' ? key : literal).charAt(0).toUpperCase()
+                                + (literal == '' ? key : literal).slice(1)
+                                + '\'><strong>' + key + '</strong></a>:'
+                                + buildDom(o[key], literal == '' ? key : literal)
+                                + ',</li>';
+                    }
+                }
+                //remove last comma
+                return '<span class="operator">+</span><div class="group">'
+                       +'{<ul class="' + type + '">'
+                       + html.replace(/,<\/li>$/, '<\/li>')
+                       + '</ul>}</div><div class="summary">Object</div>';
+                break;
+            case 'string':
+                return '<span class="value ' + type + '">"'
+                        + (/^https?\:(\/\/).*$/i.test(o)
+                          ? '<a href="' + o + '" target="_blank">' + o + '</a>'
+                          : htmlEncode(o) ) + '"</span>';
+                break;
+            default :
+                return '<span class="value ' + type + '">' + o + '</span>';
+        }
+    }
+
+    function bindEvents(tree) {
+        tree.onclick = function(e) {
+            e = e || window.event;
+            var src = e.srcElement || e.target;
+            if (src.className === 'operator') {
+                if (src.parentNode.className == 'tree-close') {
+                    src.parentNode.className = 'open';
+                    src.innerHTML = '-';
+                } else {
+                    src.parentNode.className = 'tree-close';
+                    src.innerHTML = '+';
+                }
+            }
+            _resize();
+        }
+    }
+}
+
+var domConfig = document.getElementById('config');
+var domToc = document.getElementById('toc');
+domConfig.appendChild(new JsonTree(echartsConfig).getTree());
+function _resize() {
+    var viewHeight = document.documentElement.clientHeight;
+    var scrollHeight = document.documentElement.scrollTop
+                       || document.body.scrollTop;
+    var offsetHeight = document.body.offsetHeight;
+    var maxHeight;
+    var footHole = offsetHeight - scrollHeight - viewHeight;
+    if (footHole > 60) {
+        // 未见footer,60 top、bottom, 40 per one
+        maxHeight = viewHeight - 100 - 40 * 2;
+    }
+    else {
+        // 见footer
+        maxHeight = viewHeight - 200 - 40 * 2;
+    }
+    if (domConfig.scrollHeight > maxHeight) {
+        domConfig.style.height = maxHeight + 'px';
+    } else {
+        domConfig.style.height = 'auto';
+    }
+    if (domToc.scrollHeight > maxHeight) {
+        domToc.style.height = maxHeight + 'px';
+    } else {
+        domToc.style.height = 'auto';
+    }
+}
+$(window).on('scroll', _resize);
+$(window).on('resize', _resize);
+_resize();
diff --git a/doc/asset/js/echartsExample.js b/doc/asset/js/echartsExample.js
new file mode 100644
index 0000000..3f2e324
--- /dev/null
+++ b/doc/asset/js/echartsExample.js
@@ -0,0 +1,84 @@
+var myChart;
+var domCode = document.getElementById('sidebar-code');
+var domGraphic = document.getElementById('graphic');
+var domMain = document.getElementById('main');
+var domMessage = document.getElementById('wrong-message');
+var iconResize = document.getElementById('icon-resize');
+var needRefresh = false;
+
+function autoResize() {
+    if (iconResize.className == 'icon-resize-full') {
+        focusCode();
+        iconResize.className = 'icon-resize-small';
+    }
+    else {
+        focusGraphic();
+        iconResize.className = 'icon-resize-full';
+    }
+}
+
+function focusCode() {
+    domCode.className = 'span8 ani';
+    domGraphic.className = 'span4 ani';
+}
+
+function focusGraphic() {
+    domCode.className = 'span4 ani';
+    domGraphic.className = 'span8 ani';
+    if (needRefresh) {
+        myChart.showLoading();
+        setTimeout(refresh, 1000);
+    }
+}
+
+var editor = CodeMirror.fromTextArea(
+    document.getElementById("code"),
+    { lineNumbers: true }
+);
+editor.setOption("theme", 'monokai');
+
+
+editor.on('change', function(){needRefresh = true;});
+
+function refresh(isBtnRefresh){
+    if (isBtnRefresh) {
+        needRefresh = true;
+        focusGraphic();
+        return;
+    }
+    needRefresh = false;
+    (new Function(editor.doc.getValue()))();
+    myChart.setOption(option, true);
+    domMessage.innerHTML = '';
+}
+
+require.config({
+    paths: {
+        'js': '../asset/js/esl/js'
+    },
+    packages: [
+        {
+            name: 'echarts',
+            location: '../../src',
+            main: 'echarts'
+        },
+        {
+            name: 'zrender',
+            location: '../../../zrender/src',
+            main: 'zrender'
+        }
+    ]
+});
+
+var echarts;
+require(
+    ['echarts/echarts'],
+    function(ec) {
+        echarts = ec;
+        if (myChart && myChart.dispose) {
+            myChart.dispose();
+        }
+        myChart = echarts.init(domMain);
+        refresh();
+    }
+)
\ No newline at end of file
diff --git a/doc/asset/js/esl/css.js b/doc/asset/js/esl/css.js
new file mode 100644
index 0000000..09fc6e3
--- /dev/null
+++ b/doc/asset/js/esl/css.js
@@ -0,0 +1,26 @@
+/**
+ * ESL (Enterprise Standard Loader)
+ * Copyright 2013 Baidu Inc. All rights reserved.
+ * 
+ * @file CSS Loader-Plugin
+ * @author errorrik(errorrik@gmail.com)
+ */
+
+// 构建环境暂不支持分析,为了能合并该plugin到loader里,
+// 只能暂时使用具名id
+define( 'css', {
+    load: function ( resourceId, req, load, config ) {
+        var link = document.createElement( 'link' );
+        link.setAttribute( 'rel', 'stylesheet' );
+        link.setAttribute( 'type', 'text/css' );
+        link.setAttribute( 'href', req.toUrl( resourceId ) );
+
+        var parent = document.getElementsByTagName( 'head' )[ 0 ] || document.body;
+        parent.appendChild( link );
+
+        parent = null;
+        link = null;
+
+        load( true );
+    }
+} );
diff --git a/doc/asset/js/esl/esl.js b/doc/asset/js/esl/esl.js
new file mode 100644
index 0000000..c28cac5
--- /dev/null
+++ b/doc/asset/js/esl/esl.js
@@ -0,0 +1,1416 @@
+/**

+ * ESL (Enterprise Standard Loader)

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @file Browser端标准加载器,符合AMD规范

+ * @author errorrik(errorrik@gmail.com)

+ */

+

+var define;

+var require;

+

+(function ( global ) {

+    // "mod"开头的变量或函数为内部模块管理函数

+    // 为提高压缩率,不使用function或object包装

+    var require = createLocalRequire( '' );

+

+    /**

+     * 定义模块

+     *

+     * @param {string=} id 模块标识

+     * @param {Array=} dependencies 依赖模块列表

+     * @param {Function=} factory 创建模块的工厂方法

+     */

+    function define() {

+        var argsLen = arguments.length;

+        if ( !argsLen ) {

+            return;

+        }

+

+        var id;

+        var dependencies;

+        var factory = arguments[ --argsLen ];

+

+        while ( argsLen-- ) {

+            var arg = arguments[ argsLen ];

+

+            if ( typeof arg === 'string' ) {

+                id = arg;

+            }

+            else if ( isArray( arg ) ) {

+                dependencies = arg;

+            }

+        }

+

+        // 出现window不是疏忽

+        // esl设计是做为browser端的loader

+        // 闭包的global更多意义在于:

+        //     define和require方法可以被挂到用户自定义对象中

+        var opera = window.opera;

+

+        // IE下通过current script的data-require-id获取当前id

+        if (

+            !id

+            && document.attachEvent

+            && (!(opera && opera.toString() === '[object Opera]'))

+        ) {

+            var currentScript = getCurrentScript();

+            id = currentScript && currentScript.getAttribute('data-require-id');

+        }

+

+        // 处理依赖声明

+        // 默认为['require', 'exports', 'module']

+        dependencies = dependencies || ['require', 'exports', 'module'];

+        if ( id ) {

+            modPreDefine( id, dependencies, factory );

+        }

+        else {

+            // 纪录到共享变量中,在load或readystatechange中处理

+            wait4PreDefines.push( {

+                deps    : dependencies,

+                factory : factory

+            } );

+        }

+    }

+

+    define.amd = {};

+

+    /**

+     * 模块容器

+     *

+     * @inner

+     * @type {Object}

+     */

+    var modModules = {};

+

+    var MODULE_STATE_PRE_DEFINED = 1;

+    var MODULE_STATE_PRE_ANALYZED = 2;

+    var MODULE_STATE_ANALYZED = 3;

+    var MODULE_STATE_LOADED = 4;

+    var MODULE_STATE_DEFINED = 5;

+

+    /**

+     * 获取相应状态的模块列表

+     *

+     * @inner

+     * @param {number} state 状态码

+     * @return {Array}

+     */

+    function modGetByState( state ) {

+        var modules = [];

+        for ( var key in modModules ) {

+            var module = modModules[ key ];

+            if ( module.state == state ) {

+                modules.push( module );

+            }

+        }

+

+        return modules;

+    }

+

+    /**

+     * 预定义模块

+     *

+     * @inner

+     * @param {string} id 模块标识

+     * @param {Array.<string>} dependencies 显式声明的依赖模块列表

+     * @param {*} factory 模块定义函数或模块对象

+     */

+    function modPreDefine( id, dependencies, factory ) {

+        if ( modExists( id ) ) {

+            return;

+        }

+

+        var module = {

+            id       : id,

+            deps     : dependencies,

+            factory  : factory,

+            exports  : {},

+            hardDeps : [],

+            softDeps : [],

+            state    : MODULE_STATE_PRE_DEFINED

+        };

+

+        // 将模块预存入defining集合中

+        modModules[ id ] = module;

+    }

+

+    /**

+     * 预分析模块

+     *

+     * 首先,完成对factory中声明依赖的分析提取

+     * 然后,尝试加载"资源加载所需模块"

+     *

+     * 需要先加载模块的原因是:如果模块不存在,无法进行resourceId normalize化

+     * modAnalyse完成后续的依赖分析处理,并进行依赖模块的加载

+     *

+     * @inner

+     * @param {Object} modules 模块对象

+     */

+    function modPreAnalyse() {

+        var pluginModuleIds = [];

+        var modules = modGetByState( MODULE_STATE_PRE_DEFINED );

+

+        each(

+            modules,

+            function ( module ) {

+                // 处理实际需要加载的依赖

+                var realDepends = module.deps.slice( 0 );

+                module.realDeps = realDepends;

+

+                // 分析function body中的require

+                // 如果包含显式依赖声明,为性能考虑,可以不分析factoryBody

+                // AMD规范的说明是`SHOULD NOT`,所以这里还是分析了

+                var factory = module.factory;

+                var requireRule = /require\(\s*(['"'])([^'"]+)\1\s*\)/g;

+                var commentRule = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg;

+                if ( typeof factory == 'function' ) {

+                    factory.toString()

+                        .replace( commentRule, '' )

+                        .replace( requireRule, function ( $0, $1, $2 ) {

+                            realDepends.push( $2 );

+                        });

+                }

+

+                // 分析resource加载的plugin module id

+                each(

+                    realDepends,

+                    function ( dependId ) {

+                        var idInfo = parseId( dependId );

+                        if ( idInfo.resource ) {

+                            pluginModuleIds.push(

+                                normalize( idInfo.module, module.id )

+                            );

+                        }

+                    }

+                );

+

+                module.state = MODULE_STATE_PRE_ANALYZED;

+            }

+        );

+

+        nativeRequire( pluginModuleIds, function () {

+            modAnalyse( modules );

+        } );

+    }

+

+    /**

+     * 分析模块

+     * 对所有依赖id进行normalize化,完成分析,并尝试加载其依赖的模块

+     *

+     * @inner

+     * @param {Array} modules 模块对象列表

+     */

+    function modAnalyse( modules ) {

+        var requireModules = [];

+

+        each(

+            modules,

+            function ( module ) {

+                var id = module.id;

+                var realDepends = module.realDeps;

+                var hardDepends = module.hardDeps;

+                var softDepends = module.softDeps;

+

+                // 对参数中声明的依赖进行normalize

+                // 并且处理参数中声明依赖的循环依赖

+                var hardDependsMap = {};

+                var depends = module.deps;

+                each(

+                    depends,

+                    function ( dependId, index ) {

+                        dependId = normalize( dependId, id );

+                        depends[ index ] = dependId;

+                        if ( !hardDependsMap[ dependId ]

+                             && !isInDependencyChain( id, dependId, 'hardDeps' )

+                        ) {

+                            hardDepends.push( dependId );

+                            hardDependsMap[ dependId ] = 1;

+                        }

+                    }

+                );

+

+                // 依赖模块id normalize化,并去除必要的依赖。去除的依赖模块有:

+                // 1. 内部模块:require/exports/module

+                // 2. 重复模块:dependencies参数和内部require可能重复

+                // 3. 空模块:dependencies中使用者可能写空

+                var len = realDepends.length;

+                var existsDepend = {};

+

+                while ( len-- ) {

+                    // 此处和上部分循环存在重复normalize,因为deps和realDeps是重复的

+                    // 为保持逻辑分界清晰,就不做优化了先

+                    var dependId = normalize( realDepends[ len ], id );

+                    if ( !dependId

+                         || dependId in existsDepend

+                         || dependId in BUILDIN_MODULE

+                    ) {

+                        realDepends.splice( len, 1 );

+                    }

+                    else {

+                        existsDepend[ dependId ] = 1;

+                        realDepends[ len ] = dependId;

+                        if ( !hardDependsMap[ dependId ] ) {

+                            softDepends.unshift( dependId );

+                        }

+

+                        // 将实际依赖压入加载序列中,后续统一进行require

+                        requireModules.push( dependId );

+                    }

+                }

+

+                module.state = MODULE_STATE_ANALYZED;

+                modWaitDependenciesLoaded( module );

+            }

+        );

+

+        nativeRequire( requireModules );

+    }

+

+    /**

+     * 等待模块依赖加载完成

+     * 加载完成后尝试调用factory完成模块定义

+     *

+     * @inner

+     * @param {Object} module 模块对象

+     */

+    function modWaitDependenciesLoaded( module ) {

+        var id = module.id;

+

+        // 内建模块

+        var buildinModule = {

+            require : createLocalRequire( id ),

+            exports : module.exports,

+            module  : module

+        };

+

+        modAddDefinedListener( invokeFactory );

+        invokeFactory();

+

+        /**

+         * 判断依赖加载完成

+         *

+         * @inner

+         * @return {boolean}

+         */

+        function isInvokeReady() {

+            var isReady = 1;

+

+            each(

+                module.hardDeps,

+                function ( depId ) {

+                    isReady = depId in BUILDIN_MODULE

+                        || modIsDefined( depId );

+                    return !!isReady;

+                }

+            );

+

+            isReady && each(

+                module.softDeps,

+                function ( depId ) {

+                    isReady = depId in BUILDIN_MODULE

+                        || modIsDefined( depId )

+                        || isInDependencyChain( id, depId );

+                    return !!isReady;

+                }

+            );

+

+            isReady && ( module.state = MODULE_STATE_LOADED );

+            return isReady;

+        }

+

+        /**

+         * 初始化模块

+         *

+         * @inner

+         */

+        function invokeFactory() {

+            if ( modIsDefined( id ) || !isInvokeReady() ) {

+                return;

+            }

+

+            // 构造factory参数

+            var args = [];

+            each(

+                module.deps,

+                function ( moduleId, index ) {

+                    args[ index ] =

+                        buildinModule[ moduleId ]

+                        || modGetModuleExports( moduleId );

+                }

+            );

+

+            // 调用factory函数初始化module

+            try {

+                var factory = module.factory;

+                var exports = typeof factory == 'function'

+                    ? factory.apply( global, args )

+                    : factory;

+

+                if ( typeof exports != 'undefined' ) {

+                    module.exports = exports;

+                }

+            }

+            catch ( ex ) {

+                if ( ex.message.indexOf( '[MODULE_MISS]' ) === 0 ) {

+                    return;

+                }

+

+                throw ex;

+            }

+

+            module.state = MODULE_STATE_DEFINED;

+            modRemoveDefinedListener( invokeFactory );

+

+            modFireDefined( id );

+        }

+    }

+

+    /**

+     * 模块定义完成的事件监听器

+     *

+     * @inner

+     * @type {Array}

+     */

+    var modDefinedListener = [];

+

+    /**

+     * 模块定义完成事件监听器的移除索引

+     *

+     * @inner

+     * @type {Array}

+     */

+    var modRemoveListenerIndex = [];

+

+    /**

+     * 模块定义完成事件fire层级

+     *

+     * @inner

+     * @type {number}

+     */

+    var modFireLevel = 0;

+

+    /**

+     * 派发模块定义完成事件

+     *

+     * @inner

+     * @param {string} id 模块标识

+     */

+    function modFireDefined( id ) {

+        modFireLevel++;

+        each(

+            modDefinedListener,

+            function ( listener ) {

+                listener && listener( id );

+            }

+        );

+        modFireLevel--;

+

+        modSweepDefinedListener();

+    }

+

+    /**

+     * 清理模块定义完成事件监听器

+     * modRemoveDefinedListener时只做标记

+     * 在modFireDefined执行清除动作

+     *

+     * @inner

+     * @param {Function} listener 模块定义监听器

+     */

+    function modSweepDefinedListener() {

+        if ( modFireLevel < 1 ) {

+            modRemoveListenerIndex.sort(

+                function ( a, b ) { return b - a; }

+            );

+

+            each(

+                modRemoveListenerIndex,

+                function ( index ) {

+                    modDefinedListener.splice( index, 1 );

+                }

+            );

+

+            modRemoveListenerIndex = [];

+        }

+    }

+

+    /**

+     * 移除模块定义监听器

+     *

+     * @inner

+     * @param {Function} listener 模块定义监听器

+     */

+    function modRemoveDefinedListener( listener ) {

+        each(

+            modDefinedListener,

+            function ( item, index ) {

+                if ( listener == item ) {

+                    modRemoveListenerIndex.push( index );

+                }

+            }

+        );

+    }

+

+    /**

+     * 添加模块定义监听器

+     *

+     * @inner

+     * @param {Function} listener 模块定义监听器

+     */

+    function modAddDefinedListener( listener ) {

+        modDefinedListener.push( listener );

+    }

+

+    /**

+     * 判断模块是否存在

+     *

+     * @inner

+     * @param {string} id 模块标识

+     * @return {boolean}

+     */

+    function modExists( id ) {

+        return id in modModules;

+    }

+

+    /**

+     * 判断模块是否已定义完成

+     *

+     * @inner

+     * @param {string} id 模块标识

+     * @return {boolean}

+     */

+    function modIsDefined( id ) {

+        return modExists( id )

+            && modModules[ id ].state == MODULE_STATE_DEFINED;

+    }

+

+    /**

+     * 获取模块的exports

+     *

+     * @inner

+     * @param {string} id 模块标识

+     * @return {*}

+     */

+    function modGetModuleExports( id ) {

+        if ( modExists( id ) ) {

+            return modModules[ id ].exports;

+        }

+

+        return null;

+    }

+

+    /**

+     * 获取模块

+     *

+     * @inner

+     * @param {string} id 模块标识

+     * @return {Object}

+     */

+    function modGetModule( id ) {

+        return modModules[ id ];

+    }

+

+    /**

+     * 添加资源

+     *

+     * @inner

+     * @param {string} resourceId 资源标识

+     * @param {*} value 资源对象

+     */

+    function modAddResource( resourceId, value ) {

+        modModules[ resourceId ] = {

+            exports: value || true,

+            state: MODULE_STATE_DEFINED

+        };

+

+        modFireDefined( resourceId );

+    }

+

+    /**

+     * 内建module名称集合

+     *

+     * @inner

+     * @type {Object}

+     */

+    var BUILDIN_MODULE = {

+        require : require,

+        exports : 1,

+        module  : 1

+    };

+

+    /**

+     * 未预定义的模块集合

+     * 主要存储匿名方式define的模块

+     *

+     * @inner

+     * @type {Array}

+     */

+    var wait4PreDefines = [];

+

+    /**

+     * 完成模块预定义

+     *

+     * @inner

+     */

+    function completePreDefine( currentId ) {

+        var preDefines = wait4PreDefines.slice( 0 );

+

+        wait4PreDefines.length = 0;

+        wait4PreDefines = [];

+

+        // 预定义模块:

+        // 此时处理的模块都是匿名define的模块

+        each(

+            preDefines,

+            function ( module ) {

+                var id = module.id || currentId;

+                modPreDefine( id, module.deps, module.factory );

+            }

+        );

+

+        modPreAnalyse();

+    }

+

+    /**

+     * 判断source是否处于target的依赖链中

+     *

+     * @inner

+     * @return {boolean}

+     */

+    function isInDependencyChain( source, target, depLevel, meet ) {

+        depLevel = depLevel || 'realDeps';

+        var module = modGetModule( target );

+        var depends = module && module[ depLevel ];

+

+        meet = meet || {};

+        if ( meet[ target ] ) {

+            return 0;

+        }

+        meet[ target ] = 1;

+

+        if ( depends ) {

+            var len = depends.length;

+

+            while ( len-- ) {

+                var dependId = depends[ len ];

+

+                if ( source == dependId

+                     || isInDependencyChain( source, dependId, depLevel, meet )

+                ) {

+                    return 1;

+                }

+            }

+        }

+

+        return 0;

+    }

+

+    /**

+     * 获取模块

+     *

+     * @param {string|Array} ids 模块名称或模块名称列表

+     * @param {Function=} callback 获取模块完成时的回调函数

+     * @return {Object}

+     */

+    function nativeRequire( ids, callback, baseId ) {

+        callback = callback || new Function();

+        baseId = baseId || '';

+

+        // 根据 https://github.com/amdjs/amdjs-api/wiki/require

+        // It MUST throw an error if the module has not

+        // already been loaded and evaluated.

+        if ( typeof ids == 'string' ) {

+            if ( !modIsDefined( ids ) ) {

+                throw new Error( '[MODULE_MISS]' + ids + ' is not exists!' );

+            }

+

+            return modGetModuleExports( ids );

+        }

+

+        if ( !isArray( ids ) ) {

+            return;

+        }

+

+        if ( ids.length === 0 ) {

+            callback();

+            return;

+        }

+

+        var isCallbackCalled = 0;

+        modAddDefinedListener( tryFinishRequire );

+        each(

+            ids,

+            function ( id ) {

+                if ( id in BUILDIN_MODULE ) {

+                    return;

+                }

+

+                ( id.indexOf( '!' ) > 0

+                    ? loadResource

+                    : loadModule

+                )( id, baseId );

+            }

+        );

+

+        tryFinishRequire();

+

+        /**

+         * 尝试完成require,调用callback

+         * 在模块与其依赖模块都加载完时调用

+         *

+         * @inner

+         */

+        function tryFinishRequire() {

+            if ( isCallbackCalled ) {

+                return;

+            }

+

+            var visitedModule = {};

+

+            /**

+             * 判断是否所有模块都已经加载完成,包括其依赖的模块

+             *

+             * @inner

+             * @param {Array} modules 直接模块标识列表

+             * @return {boolean}

+             */

+            function isAllInited( modules ) {

+                var allInited = 1;

+                each(

+                    modules,

+                    function ( id ) {

+                        if ( visitedModule[ id ] ) {

+                            return;

+                        }

+                        visitedModule[ id ] = 1;

+

+                        if ( BUILDIN_MODULE[ id ] ) {

+                            return;

+                        }

+

+                        if (

+                            !modIsDefined( id )

+                            || !isAllInited( modGetModule( id ).realDeps )

+                        ) {

+                            allInited = 0;

+                            return false;

+                        }

+                    }

+                );

+

+                return allInited;

+            }

+

+            // 检测并调用callback

+            if ( isAllInited( ids ) ) {

+                isCallbackCalled = 1;

+                modRemoveDefinedListener( tryFinishRequire );

+

+                var args = [];

+                each(

+                    ids,

+                    function ( id ) {

+                        args.push(

+                            BUILDIN_MODULE[ id ]

+                            || modGetModuleExports( id )

+                        );

+                    }

+                );

+

+                callback.apply( global, args );

+            }

+        }

+    }

+

+    /**

+     * 正在加载的模块列表

+     *

+     * @inner

+     * @type {Object}

+     */

+    var loadingModules = {};

+

+    /**

+     * 加载模块

+     *

+     * @inner

+     * @param {string} moduleId 模块标识

+     */

+    function loadModule( moduleId ) {

+        if (

+            modExists( moduleId )

+            || loadingModules[ moduleId ]

+        ) {

+            return;

+        }

+

+        loadingModules[ moduleId ] = 1;

+

+        // 创建script标签

+        var script = document.createElement( 'script' );

+        script.setAttribute( 'data-require-id', moduleId );

+        script.src = toUrl( moduleId ) + '.js';

+        script.async = true;

+        if ( script.readyState ) {

+            script.onreadystatechange = loadedListener;

+        }

+        else {

+            script.onload = loadedListener;

+        }

+        // TODO: onerror

+        appendScript( script );

+

+        /**

+         * script标签加载完成的事件处理函数

+         *

+         * @inner

+         */

+        function loadedListener() {

+            var readyState = script.readyState;

+            if (

+                typeof readyState == 'undefined'

+                || /^(loaded|complete)$/.test( readyState )

+            ) {

+                script.onload = script.onreadystatechange = null;

+

+                completePreDefine( moduleId );

+                delete loadingModules[ moduleId ];

+                script = null;

+            }

+        }

+    }

+

+    /**

+     * 加载资源

+     *

+     * @inner

+     * @param {string} pluginAndResource 插件与资源标识

+     * @param {string} baseId 当前环境的模块标识

+     */

+    function loadResource( pluginAndResource, baseId ) {

+        var idInfo = parseId( pluginAndResource );

+        var pluginId = idInfo.module;

+        var resourceId = idInfo.resource;

+

+        /**

+         * plugin加载完成的回调函数

+         *

+         * @inner

+         * @param {*} value resource的值

+         */

+        function pluginOnload( value ) {

+            modAddResource( pluginAndResource, value );

+        }

+

+        /**

+         * 该方法允许plugin使用加载的资源声明模块

+         *

+         * @param {string} name 模块id

+         * @param {string} body 模块声明字符串

+         */

+        pluginOnload.fromText = function ( id, text ) {

+            new Function( text )();

+            completePreDefine( id );

+        };

+

+        /**

+         * 加载资源

+         *

+         * @inner

+         * @param {Object} plugin 用于加载资源的插件模块

+         */

+        function load( plugin ) {

+            if ( !modIsDefined( pluginAndResource ) ) {

+                plugin.load(

+                    resourceId,

+                    createLocalRequire( baseId ),

+                    pluginOnload,

+                    {}

+                );

+            }

+        }

+

+        if ( !modIsDefined( pluginId ) ) {

+            nativeRequire( [ pluginId ], load );

+        }

+        else {

+            load( modGetModuleExports( pluginId ) );

+        }

+    }

+

+    /**

+     * require配置

+     *

+     * @inner

+     * @type {Object}

+     */

+    var requireConf = {

+        baseUrl  : './',

+        paths    : {},

+        config   : {},

+        map      : {},

+        packages : []

+    };

+

+    /**

+     * 混合当前配置项与用户传入的配置项

+     *

+     * @inner

+     * @param {string} name 配置项名称

+     * @param {Any} value 用户传入配置项的值

+     */

+    function mixConfig( name, value ) {

+        var originValue = requireConf[ name ];

+        if ( typeof originValue == 'string' ) {

+            requireConf[ name ] = value;

+        }

+        else if ( isArray( originValue ) ) {

+            each( value, function ( item ) {

+                originValue.push( item );

+            } );

+        }

+        else {

+            for ( var key in value ) {

+                originValue[ key ] = value[ key ];

+            }

+        }

+    }

+

+    /**

+     * 配置require

+     *

+     * @param {Object} conf 配置对象

+     */

+    require.config = function ( conf ) {

+        // 简单的多处配置还是需要支持

+        // 所以实现更改为二级mix

+        for ( var key in requireConf ) {

+            if ( conf.hasOwnProperty( key ) ) {

+                mixConfig( key, conf[ key ] );

+            }

+        }

+

+        createConfIndex();

+    };

+

+    // 初始化时需要创建配置索引

+    createConfIndex();

+

+    /**

+     * 创建配置信息内部索引

+     *

+     * @inner

+     */

+    function createConfIndex() {

+        requireConf.baseUrl = requireConf.baseUrl.replace( /\/$/, '' ) + '/';

+        createPathsIndex();

+        createMappingIdIndex();

+        createPackagesIndex();

+    }

+

+    /**

+     * packages内部索引

+     *

+     * @inner

+     * @type {Array}

+     */

+    var packagesIndex;

+

+    /**

+     * 创建packages内部索引

+     *

+     * @inner

+     */

+    function createPackagesIndex() {

+        packagesIndex = [];

+        each(

+            requireConf.packages,

+            function ( packageConf ) {

+                var pkg = packageConf;

+                if ( typeof packageConf == 'string' ) {

+                    pkg = {

+                        name: packageConf.split('/')[ 0 ],

+                        location: packageConf,

+                        main: 'main'

+                    };

+                }

+

+                pkg.location = pkg.location || pkg.name;

+                pkg.main = (pkg.main || 'main').replace(/\.js$/i, '');

+                packagesIndex.push( pkg );

+            }

+        );

+

+        packagesIndex.sort( createDescSorter( 'name' ) );

+    }

+

+    /**

+     * paths内部索引

+     *

+     * @inner

+     * @type {Array}

+     */

+    var pathsIndex;

+

+    /**

+     * 创建paths内部索引

+     *

+     * @inner

+     */

+    function createPathsIndex() {

+        pathsIndex = kv2List( requireConf.paths );

+        pathsIndex.sort( createDescSorter() );

+    }

+

+    /**

+     * mapping内部索引

+     *

+     * @inner

+     * @type {Array}

+     */

+    var mappingIdIndex;

+

+    /**

+     * 创建mapping内部索引

+     *

+     * @inner

+     */

+    function createMappingIdIndex() {

+        mappingIdIndex = [];

+

+        mappingIdIndex = kv2List( requireConf.map );

+        mappingIdIndex.sort( createDescSorter() );

+

+        each(

+            mappingIdIndex,

+            function ( item ) {

+                var key = item.k;

+                item.v = kv2List( item.v );

+                item.v.sort( createDescSorter() );

+                item.reg = key == '*'

+                    ? /^/

+                    : createPrefixRegexp( key );

+            }

+        );

+    }

+

+    /**

+     * 将模块标识转换成相对baseUrl的url

+     *

+     * @inner

+     * @param {string} id 模块标识

+     * @return {string}

+     */

+    function toUrl( id ) {

+        if ( !MODULE_ID_REG.test( id ) ) {

+            return id;

+        }

+

+        var url = id;

+        var isPathMap = 0;

+

+        each( pathsIndex, function ( item ) {

+            var key = item.k;

+            if ( createPrefixRegexp( key ).test( url ) ) {

+                url = url.replace( key, item.v );

+                isPathMap = 1;

+                return false;

+            }

+        } );

+

+        if ( !isPathMap ) {

+            each(

+                packagesIndex,

+                function ( packageConf ) {

+                    var name = packageConf.name;

+                    if ( createPrefixRegexp( name ).test( id ) ) {

+                        url = url.replace( name, packageConf.location );

+                        return false;

+                    }

+                }

+            );

+        }

+

+        if ( !/^([a-z]{2,10}:\/)?\//i.test( url ) ) {

+            url = requireConf.baseUrl + url;

+        }

+

+        return url;

+    }

+

+    /**

+     * 创建local require函数

+     *

+     * @inner

+     * @param {number} baseId 当前module id

+     * @return {Function}

+     */

+    function createLocalRequire( baseId ) {

+        var requiredCache = {};

+        function req( requireId, callback ) {

+            if ( typeof requireId == 'string' ) {

+                var requiredModule;

+                if ( !( requiredModule = requiredCache[ requireId ] ) ) {

+                    requiredModule = nativeRequire(

+                        normalize( requireId, baseId ),

+                        callback,

+                        baseId

+                    );

+                    requiredCache[ requireId ] = requiredModule;

+                }

+

+                return requiredModule;

+            }

+            else if ( isArray( requireId ) ) {

+                // 分析是否有resource使用的plugin没加载

+                var unloadedPluginModules = [];

+                each(

+                    requireId,

+                    function ( id ) {

+                        var idInfo = parseId( id );

+                        var pluginId = normalize( idInfo.module, baseId );

+                        if ( idInfo.resource && !modIsDefined( pluginId ) ) {

+                            unloadedPluginModules.push( pluginId );

+                        }

+                    }

+                );

+

+                // 加载模块

+                nativeRequire(

+                    unloadedPluginModules,

+                    function () {

+                        var ids = [];

+                        each(

+                            requireId,

+                            function ( id ) {

+                                ids.push( normalize( id, baseId ) );

+                            }

+                        );

+                        nativeRequire( ids, callback, baseId );

+                    },

+                    baseId

+                );

+            }

+        }

+

+        /**

+         * 将[module ID] + '.extension'格式的字符串转换成url

+         *

+         * @inner

+         * @param {string} source 符合描述格式的源字符串

+         * @return {string}

+         */

+        req.toUrl = function ( id ) {

+            return toUrl( normalize( id, baseId ) );

+        };

+

+        return req;

+    }

+

+

+

+    /**

+     * id normalize化

+     *

+     * @inner

+     * @param {string} id 需要normalize的模块标识

+     * @param {string} baseId 当前环境的模块标识

+     * @return {string}

+     */

+    function normalize( id, baseId ) {

+        if ( !id ) {

+            return '';

+        }

+

+        var idInfo = parseId( id );

+        if ( !idInfo ) {

+            return id;

+        }

+

+        var resourceId = idInfo.resource;

+        var moduleId = relative2absolute( idInfo.module, baseId );

+

+        each(

+            packagesIndex,

+            function ( packageConf ) {

+                var name = packageConf.name;

+                var main = name + '/' + packageConf.main;

+                if ( name == moduleId

+                ) {

+                    moduleId = moduleId.replace( name, main );

+                    return false;

+                }

+            }

+        );

+

+        moduleId = mappingId( moduleId, baseId );

+

+        if ( resourceId ) {

+            var module = modGetModuleExports( moduleId );

+            resourceId = module.normalize

+                ? module.normalize(

+                    resourceId,

+                    function ( resId ) {

+                        return normalize( resId, baseId );

+                    }

+                  )

+                : normalize( resourceId, baseId );

+

+            return moduleId + '!' + resourceId;

+        }

+

+        return moduleId;

+    }

+

+    /**

+     * 相对id转换成绝对id

+     *

+     * @inner

+     * @param {string} id 要转换的id

+     * @param {string} baseId 当前所在环境id

+     * @return {string}

+     */

+    function relative2absolute( id, baseId ) {

+        if ( /^\.{1,2}/.test( id ) ) {

+            var basePath = baseId.split( '/' );

+            var namePath = id.split( '/' );

+            var baseLen = basePath.length - 1;

+            var nameLen = namePath.length;

+            var cutBaseTerms = 0;

+            var cutNameTerms = 0;

+

+            pathLoop: for ( var i = 0; i < nameLen; i++ ) {

+                var term = namePath[ i ];

+                switch ( term ) {

+                    case '..':

+                        if ( cutBaseTerms < baseLen ) {

+                            cutBaseTerms++;

+                            cutNameTerms++;

+                        }

+                        else {

+                            break pathLoop;

+                        }

+                        break;

+                    case '.':

+                        cutNameTerms++;

+                        break;

+                    default:

+                        break pathLoop;

+                }

+            }

+

+            basePath.length = baseLen - cutBaseTerms;

+            namePath = namePath.slice( cutNameTerms );

+

+            basePath.push.apply( basePath, namePath );

+            return basePath.join( '/' );

+        }

+

+        return id;

+    }

+

+    /**

+     * 模块id正则

+     *

+     * @const

+     * @inner

+     * @type {RegExp}

+     */

+    var MODULE_ID_REG = /^[-_a-z0-9\.]+(\/[-_a-z0-9\.]+)*$/i;

+

+    /**

+     * 解析id,返回带有module和resource属性的Object

+     *

+     * @inner

+     * @param {string} id 标识

+     * @return {Object}

+     */

+    function parseId( id ) {

+        var segs = id.split( '!' );

+

+        if ( MODULE_ID_REG.test( segs[ 0 ] ) ) {

+            return {

+                module   : segs[ 0 ],

+                resource : segs[ 1 ] || ''

+            };

+        }

+

+        return null;

+    }

+

+    /**

+     * 基于map配置项的id映射

+     *

+     * @inner

+     * @param {string} id 模块id

+     * @param {string} baseId 当前环境的模块id

+     * @return {string}

+     */

+    function mappingId( id, baseId ) {

+        each(

+            mappingIdIndex,

+            function ( item ) {

+                if ( item.reg.test( baseId ) ) {

+

+                    each( item.v, function ( mapData ) {

+                        var key = mapData.k;

+                        var rule = createPrefixRegexp( key );

+

+                        if ( rule.test( id ) ) {

+                            id = id.replace( key, mapData.v );

+                            return false;

+                        }

+                    } );

+

+                    return false;

+                }

+            }

+        );

+

+        return id;

+    }

+

+    /**

+     * 将对象数据转换成数组,数组每项是带有k和v的Object

+     *

+     * @inner

+     * @param {Object} source 对象数据

+     * @return {Array.<Object>}

+     */

+    function kv2List( source ) {

+        var list = [];

+        for ( var key in source ) {

+            if ( source.hasOwnProperty( key ) ) {

+                list.push( {

+                    k: key,

+                    v: source[ key ]

+                } );

+            }

+        }

+

+        return list;

+    }

+

+    // 感谢requirejs,通过currentlyAddingScript兼容老旧ie

+    //

+    // For some cache cases in IE 6-8, the script executes before the end

+    // of the appendChild execution, so to tie an anonymous define

+    // call to the module name (which is stored on the node), hold on

+    // to a reference to this node, but clear after the DOM insertion.

+    var currentlyAddingScript;

+    var interactiveScript;

+

+    /**

+     * 获取当前script标签

+     * 用于ie下define未指定module id时获取id

+     *

+     * @inner

+     * @return {HTMLDocument}

+     */

+    function getCurrentScript() {

+        if ( currentlyAddingScript ) {

+            return currentlyAddingScript;

+        }

+        else if (

+            interactiveScript

+            && interactiveScript.readyState == 'interactive'

+        ) {

+            return interactiveScript;

+        }

+        else {

+            var scripts = document.getElementsByTagName( 'script' );

+            var scriptLen = scripts.length;

+            while ( scriptLen-- ) {

+                var script = scripts[ scriptLen ];

+                if ( script.readyState == 'interactive' ) {

+                    interactiveScript = script;

+                    return script;

+                }

+            }

+        }

+    }

+

+    /**

+     * 向页面中插入script标签

+     *

+     * @inner

+     * @param {HTMLScriptElement} script script标签

+     */

+    function appendScript( script ) {

+        currentlyAddingScript = script;

+

+        var doc = document;

+        (doc.getElementsByTagName('head')[0] || doc.body).appendChild( script );

+

+        currentlyAddingScript = null;

+    }

+

+    /**

+     * 创建id前缀匹配的正则对象

+     *

+     * @inner

+     * @param {string} prefix id前缀

+     * @return {RegExp}

+     */

+    function createPrefixRegexp( prefix ) {

+        return new RegExp( '^' + prefix + '(/|$)' );

+    }

+

+    /**

+     * 判断对象是否数组类型

+     *

+     * @inner

+     * @param {*} obj 要判断的对象

+     * @return {boolean}

+     */

+    function isArray( obj ) {

+        return obj instanceof Array;

+    }

+

+    /**

+     * 循环遍历数组集合

+     *

+     * @inner

+     * @param {Array} source 数组源

+     * @param {function(Array,Number):boolean} iterator 遍历函数

+     */

+    function each( source, iterator ) {

+        if ( isArray( source ) ) {

+            for ( var i = 0, len = source.length; i < len; i++ ) {

+                if ( iterator( source[ i ], i ) === false ) {

+                    break;

+                }

+            }

+        }

+    }

+

+    /**

+     * 创建数组字符数逆序排序函数

+     *

+     * @inner

+     * @param {string} property 数组项对象名

+     * @return {Function}

+     */

+    function createDescSorter( property ) {

+        property = property || 'k';

+

+        return function ( a, b ) {

+            var aValue = a[ property ];

+            var bValue = b[ property ];

+

+            if ( bValue == '*' ) {

+                return -1;

+            }

+

+            if ( aValue == '*' ) {

+                return 1;

+            }

+

+            return bValue.length - aValue.length;

+        };

+    }

+

+    // 暴露全局对象

+    global.define = define;

+    global.require = require;

+})( this );
\ No newline at end of file
diff --git a/doc/asset/js/esl/js.js b/doc/asset/js/esl/js.js
new file mode 100644
index 0000000..fe57400
--- /dev/null
+++ b/doc/asset/js/esl/js.js
@@ -0,0 +1,38 @@
+/**
+ * ESL (Enterprise Standard Loader)
+ * Copyright 2013 Baidu Inc. All rights reserved.
+ * 
+ * @file JS Loader-Plugin
+ * @author errorrik(errorrik@gmail.com)
+ */
+
+// 构建环境暂不支持分析,为了能合并该plugin到loader里,
+// 只能暂时使用具名id
+define( 'js', {
+    load: function ( resourceId, req, load, config ) {
+        var script = document.createElement( 'script' );
+        script.src = req.toUrl( resourceId );
+        script.async = true;
+        if ( script.readyState ) {
+            script.onreadystatechange = onload;
+        }
+        else {
+            script.onload = onload;
+        }
+
+        var parent = document.getElementsByTagName( 'head' )[ 0 ] || document.body;
+        parent.appendChild( script ) && ( parent = null );
+        
+        function onload() {
+            var readyState = script.readyState;
+            if ( 
+                typeof readyState == 'undefined'
+                || /^(loaded|complete)$/.test( readyState )
+            ) {
+                script.onload = script.onreadystatechange = null;
+                script = null;
+                load( true );
+            }
+        }
+    }
+} );
diff --git a/doc/asset/js/html5shiv.js b/doc/asset/js/html5shiv.js
new file mode 100644
index 0000000..784f221
--- /dev/null
+++ b/doc/asset/js/html5shiv.js
@@ -0,0 +1,8 @@
+/*
+ HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
+*/
+(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
+a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}</style>";
+c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
+"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",version:"3.6.2pre",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment();
+for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);
diff --git a/doc/asset/js/javascript.js b/doc/asset/js/javascript.js
new file mode 100644
index 0000000..d41536f
--- /dev/null
+++ b/doc/asset/js/javascript.js
@@ -0,0 +1,426 @@
+// TODO actually recognize syntax of TypeScript constructs
+
+CodeMirror.defineMode("javascript", function(config, parserConfig) {
+  var indentUnit = config.indentUnit;
+  var jsonMode = parserConfig.json;
+  var isTS = parserConfig.typescript;
+
+  // Tokenizer
+
+  var keywords = function(){
+    function kw(type) {return {type: type, style: "keyword"};}
+    var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
+    var operator = kw("operator"), atom = {type: "atom", style: "atom"};
+    
+    var jsKeywords = {
+      "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
+      "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
+      "var": kw("var"), "const": kw("var"), "let": kw("var"),
+      "function": kw("function"), "catch": kw("catch"),
+      "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
+      "in": operator, "typeof": operator, "instanceof": operator,
+      "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
+    };
+
+    // Extend the 'normal' keywords with the TypeScript language extensions
+    if (isTS) {
+      var type = {type: "variable", style: "variable-3"};
+      var tsKeywords = {
+        // object-like things
+        "interface": kw("interface"),
+        "class": kw("class"),
+        "extends": kw("extends"),
+        "constructor": kw("constructor"),
+
+        // scope modifiers
+        "public": kw("public"),
+        "private": kw("private"),
+        "protected": kw("protected"),
+        "static": kw("static"),
+
+        "super": kw("super"),
+
+        // types
+        "string": type, "number": type, "bool": type, "any": type
+      };
+
+      for (var attr in tsKeywords) {
+        jsKeywords[attr] = tsKeywords[attr];
+      }
+    }
+
+    return jsKeywords;
+  }();
+
+  var isOperatorChar = /[+\-*&%=<>!?|]/;
+
+  function chain(stream, state, f) {
+    state.tokenize = f;
+    return f(stream, state);
+  }
+
+  function nextUntilUnescaped(stream, end) {
+    var escaped = false, next;
+    while ((next = stream.next()) != null) {
+      if (next == end && !escaped)
+        return false;
+      escaped = !escaped && next == "\\";
+    }
+    return escaped;
+  }
+
+  // Used as scratch variables to communicate multiple values without
+  // consing up tons of objects.
+  var type, content;
+  function ret(tp, style, cont) {
+    type = tp; content = cont;
+    return style;
+  }
+
+  function jsTokenBase(stream, state) {
+    var ch = stream.next();
+    if (ch == '"' || ch == "'")
+      return chain(stream, state, jsTokenString(ch));
+    else if (/[\[\]{}\(\),;\:\.]/.test(ch))
+      return ret(ch);
+    else if (ch == "0" && stream.eat(/x/i)) {
+      stream.eatWhile(/[\da-f]/i);
+      return ret("number", "number");
+    }      
+    else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
+      stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
+      return ret("number", "number");
+    }
+    else if (ch == "/") {
+      if (stream.eat("*")) {
+        return chain(stream, state, jsTokenComment);
+      }
+      else if (stream.eat("/")) {
+        stream.skipToEnd();
+        return ret("comment", "comment");
+      }
+      else if (state.lastType == "operator" || state.lastType == "keyword c" ||
+               /^[\[{}\(,;:]$/.test(state.lastType)) {
+        nextUntilUnescaped(stream, "/");
+        stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
+        return ret("regexp", "string-2");
+      }
+      else {
+        stream.eatWhile(isOperatorChar);
+        return ret("operator", null, stream.current());
+      }
+    }
+    else if (ch == "#") {
+      stream.skipToEnd();
+      return ret("error", "error");
+    }
+    else if (isOperatorChar.test(ch)) {
+      stream.eatWhile(isOperatorChar);
+      return ret("operator", null, stream.current());
+    }
+    else {
+      stream.eatWhile(/[\w\$_]/);
+      var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
+      return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
+                     ret("variable", "variable", word);
+    }
+  }
+
+  function jsTokenString(quote) {
+    return function(stream, state) {
+      if (!nextUntilUnescaped(stream, quote))
+        state.tokenize = jsTokenBase;
+      return ret("string", "string");
+    };
+  }
+
+  function jsTokenComment(stream, state) {
+    var maybeEnd = false, ch;
+    while (ch = stream.next()) {
+      if (ch == "/" && maybeEnd) {
+        state.tokenize = jsTokenBase;
+        break;
+      }
+      maybeEnd = (ch == "*");
+    }
+    return ret("comment", "comment");
+  }
+
+  // Parser
+
+  var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
+
+  function JSLexical(indented, column, type, align, prev, info) {
+    this.indented = indented;
+    this.column = column;
+    this.type = type;
+    this.prev = prev;
+    this.info = info;
+    if (align != null) this.align = align;
+  }
+
+  function inScope(state, varname) {
+    for (var v = state.localVars; v; v = v.next)
+      if (v.name == varname) return true;
+  }
+
+  function parseJS(state, style, type, content, stream) {
+    var cc = state.cc;
+    // Communicate our context to the combinators.
+    // (Less wasteful than consing up a hundred closures on every call.)
+    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
+  
+    if (!state.lexical.hasOwnProperty("align"))
+      state.lexical.align = true;
+
+    while(true) {
+      var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
+      if (combinator(type, content)) {
+        while(cc.length && cc[cc.length - 1].lex)
+          cc.pop()();
+        if (cx.marked) return cx.marked;
+        if (type == "variable" && inScope(state, content)) return "variable-2";
+        return style;
+      }
+    }
+  }
+
+  // Combinator utils
+
+  var cx = {state: null, column: null, marked: null, cc: null};
+  function pass() {
+    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
+  }
+  function cont() {
+    pass.apply(null, arguments);
+    return true;
+  }
+  function register(varname) {
+    function inList(list) {
+      for (var v = list; v; v = v.next)
+        if (v.name == varname) return true;
+      return false;
+    }
+    var state = cx.state;
+    if (state.context) {
+      cx.marked = "def";
+      if (inList(state.localVars)) return;
+      state.localVars = {name: varname, next: state.localVars};
+    } else {
+      if (inList(state.globalVars)) return;
+      state.globalVars = {name: varname, next: state.globalVars};
+    }
+  }
+
+  // Combinators
+
+  var defaultVars = {name: "this", next: {name: "arguments"}};
+  function pushcontext() {
+    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
+    cx.state.localVars = defaultVars;
+  }
+  function popcontext() {
+    cx.state.localVars = cx.state.context.vars;
+    cx.state.context = cx.state.context.prev;
+  }
+  function pushlex(type, info) {
+    var result = function() {
+      var state = cx.state;
+      state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info);
+    };
+    result.lex = true;
+    return result;
+  }
+  function poplex() {
+    var state = cx.state;
+    if (state.lexical.prev) {
+      if (state.lexical.type == ")")
+        state.indented = state.lexical.indented;
+      state.lexical = state.lexical.prev;
+    }
+  }
+  poplex.lex = true;
+
+  function expect(wanted) {
+    return function(type) {
+      if (type == wanted) return cont();
+      else if (wanted == ";") return pass();
+      else return cont(arguments.callee);
+    };
+  }
+
+  function statement(type) {
+    if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
+    if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
+    if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
+    if (type == "{") return cont(pushlex("}"), block, poplex);
+    if (type == ";") return cont();
+    if (type == "function") return cont(functiondef);
+    if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
+                                      poplex, statement, poplex);
+    if (type == "variable") return cont(pushlex("stat"), maybelabel);
+    if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
+                                         block, poplex, poplex);
+    if (type == "case") return cont(expression, expect(":"));
+    if (type == "default") return cont(expect(":"));
+    if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
+                                        statement, poplex, popcontext);
+    return pass(pushlex("stat"), expression, expect(";"), poplex);
+  }
+  function expression(type) {
+    if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
+    if (type == "function") return cont(functiondef);
+    if (type == "keyword c") return cont(maybeexpression);
+    if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator);
+    if (type == "operator") return cont(expression);
+    if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
+    if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
+    return cont();
+  }
+  function maybeexpression(type) {
+    if (type.match(/[;\}\)\],]/)) return pass();
+    return pass(expression);
+  }
+    
+  function maybeoperator(type, value) {
+    if (type == "operator") {
+      if (/\+\+|--/.test(value)) return cont(maybeoperator);
+      if (value == "?") return cont(expression, expect(":"), expression);
+      return cont(expression);
+    }
+    if (type == ";") return;
+    if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
+    if (type == ".") return cont(property, maybeoperator);
+    if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
+  }
+  function maybelabel(type) {
+    if (type == ":") return cont(poplex, statement);
+    return pass(maybeoperator, expect(";"), poplex);
+  }
+  function property(type) {
+    if (type == "variable") {cx.marked = "property"; return cont();}
+  }
+  function objprop(type) {
+    if (type == "variable") cx.marked = "property";
+    else if (type == "number" || type == "string") cx.marked = type + " property";
+    if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
+  }
+  function commasep(what, end) {
+    function proceed(type) {
+      if (type == ",") return cont(what, proceed);
+      if (type == end) return cont();
+      return cont(expect(end));
+    }
+    return function(type) {
+      if (type == end) return cont();
+      else return pass(what, proceed);
+    };
+  }
+  function block(type) {
+    if (type == "}") return cont();
+    return pass(statement, block);
+  }
+  function maybetype(type) {
+    if (type == ":") return cont(typedef);
+    return pass();
+  }
+  function typedef(type) {
+    if (type == "variable"){cx.marked = "variable-3"; return cont();}
+    return pass();
+  }
+  function vardef1(type, value) {
+    if (type == "variable") {
+      register(value);
+      return isTS ? cont(maybetype, vardef2) : cont(vardef2);
+    }
+    return pass();
+  }
+  function vardef2(type, value) {
+    if (value == "=") return cont(expression, vardef2);
+    if (type == ",") return cont(vardef1);
+  }
+  function forspec1(type) {
+    if (type == "var") return cont(vardef1, expect(";"), forspec2);
+    if (type == ";") return cont(forspec2);
+    if (type == "variable") return cont(formaybein);
+    return cont(forspec2);
+  }
+  function formaybein(_type, value) {
+    if (value == "in") return cont(expression);
+    return cont(maybeoperator, forspec2);
+  }
+  function forspec2(type, value) {
+    if (type == ";") return cont(forspec3);
+    if (value == "in") return cont(expression);
+    return cont(expression, expect(";"), forspec3);
+  }
+  function forspec3(type) {
+    if (type != ")") cont(expression);
+  }
+  function functiondef(type, value) {
+    if (type == "variable") {register(value); return cont(functiondef);}
+    if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext);
+  }
+  function funarg(type, value) {
+    if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();}
+  }
+
+  // Interface
+
+  return {
+    startState: function(basecolumn) {
+      return {
+        tokenize: jsTokenBase,
+        lastType: null,
+        cc: [],
+        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
+        localVars: parserConfig.localVars,
+        globalVars: parserConfig.globalVars,
+        context: parserConfig.localVars && {vars: parserConfig.localVars},
+        indented: 0
+      };
+    },
+
+    token: function(stream, state) {
+      if (stream.sol()) {
+        if (!state.lexical.hasOwnProperty("align"))
+          state.lexical.align = false;
+        state.indented = stream.indentation();
+      }
+      if (stream.eatSpace()) return null;
+      var style = state.tokenize(stream, state);
+      if (type == "comment") return style;
+      state.lastType = type;
+      return parseJS(state, style, type, content, stream);
+    },
+
+    indent: function(state, textAfter) {
+      if (state.tokenize == jsTokenComment) return CodeMirror.Pass;
+      if (state.tokenize != jsTokenBase) return 0;
+      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
+      if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
+      var type = lexical.type, closing = firstChar == type;
+      if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0);
+      else if (type == "form" && firstChar == "{") return lexical.indented;
+      else if (type == "form") return lexical.indented + indentUnit;
+      else if (type == "stat")
+        return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? indentUnit : 0);
+      else if (lexical.info == "switch" && !closing)
+        return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
+      else if (lexical.align) return lexical.column + (closing ? 0 : 1);
+      else return lexical.indented + (closing ? 0 : indentUnit);
+    },
+
+    electricChars: ":{}",
+
+    jsonMode: jsonMode
+  };
+});
+
+CodeMirror.defineMIME("text/javascript", "javascript");
+CodeMirror.defineMIME("text/ecmascript", "javascript");
+CodeMirror.defineMIME("application/javascript", "javascript");
+CodeMirror.defineMIME("application/ecmascript", "javascript");
+CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
+CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
+CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
diff --git a/doc/asset/js/jquery.js b/doc/asset/js/jquery.js
new file mode 100644
index 0000000..006e953
--- /dev/null
+++ b/doc/asset/js/jquery.js
@@ -0,0 +1,5 @@
+/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
+//@ sourceMappingURL=jquery.min.map
+*/(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;
+return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="<a name='"+x+"'></a><div name='"+x+"'></div>",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&&gt(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Nt=/^(?:checkbox|radio)$/i,Ct=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._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++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.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)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
+}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);
\ No newline at end of file
diff --git a/doc/doc.html b/doc/doc.html
new file mode 100644
index 0000000..d25927d
--- /dev/null
+++ b/doc/doc.html
@@ -0,0 +1,1725 @@
+<!DOCTYPE html>

+<html lang="en">

+<head>

+    <meta charset="utf-8">

+    <title>ECharts</title>

+    <meta name="viewport" content="width=device-width, initial-scale=1.0">

+    <meta name="description" content="ECharts">

+    <meta name="author" content="linzhifeng@baidu.com">

+

+    <!-- Le styles -->

+    <link href="asset/css/bootstrap.css" rel="stylesheet">

+    <link href="asset/css/bootstrap-responsive.css" rel="stylesheet">

+    <link href="asset/css/echartsHome.css" rel="stylesheet">

+

+    <!-- Fav and touch icons -->

+    <link rel="shortcut icon" href="asset/ico/favicon.png">

+</head>

+

+<body>

+    <!-- NAVBAR

+    ================================================== -->

+    <div class="navbar navbar-inverse navbar-fixed-top">

+      <div class="navbar-inner">

+        <div class="container">

+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">

+            <span class="icon-bar"></span>

+            <span class="icon-bar"></span>

+            <span class="icon-bar"></span>

+          </button>

+          <a class="brand" href="../index.html">ECharts</a>

+          <div class="nav-collapse collapse">

+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>

+              <ul class="nav">

+                <li><a href="../index.html"><i class="icon-home icon-white"></i> Home</a></li>

+                <li><a href="example.html" class="active">Example</a></li>

+                <li class="active"><a href="doc.html">API &amp; Doc</a></li>

+                <li class="dropdown">

+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>

+                  <ul class="dropdown-menu">

+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>

+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>

+                  </ul>

+                </li>

+                <li class="dropdown">

+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>

+                  <ul class="dropdown-menu">

+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>

+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>

+                    <li class="divider"></li>

+                    <!--li class="nav-header">Library</li-->

+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>

+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>

+                  </ul>

+                </li>

+              </ul>

+           </div><!--/.nav-collapse -->

+        </div><!-- /.container -->

+      </div><!-- /.navbar-inner -->

+    </div><!-- /.navbar-wrapper -->

+

+    <div class="container-fluid">

+        <div class="row-fluid">

+            <div class="span3">

+                <div class="affix accordion span3" id="accordion">

+                  <div class="accordion-group">

+                    <div class="accordion-heading">

+                      <div class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse-description">

+                        <strong>描述</strong>

+                      </div>

+                    </div>

+                    <div id="collapse-description" class="accordion-body collapse in">

+                      <div class="accordion-inner">

+                        <div id="toc">

+                        <ul>

+                            <li><a href="#简介">简介</a></li>

+                            <li><a href="#名词解析">名词解析</a></li>

+                            <li><a href="#图表类型">图表类型</a></li>

+                            <ul>

+                                <li><a href="#Line">line</a></li>

+                                <li><a href="#Bar">bar</a></li>

+                                <li><a href="#Scatter">scatter</a></li>

+                                <li><a href="#Pie">pie</a></li>

+                                <li><a href="#Radar">radar</a></li>

+                            </ul>

+                            <li><a href="#初始化">初始化</a></li>

+                            <li><a href="#方法">方法</a></li>

+                            <li><a href="#选项">选项</a></li>

+                            <ul>

+                                <li><a href="#Option">option</a></li>

+                                <li><a href="#Legend">legend</a></li>

+                                <li><a href="#Toolbox">toolbox</a></li>

+                                <li><a href="#Tooltip">tooltip</a></li>

+                                <li><a href="#DataZoom">dataZoom</a></li>

+                                <li><a href="#Grid">grid</a></li>

+                                <li><a href="#Xaxis">xAxis</a></li>

+                                <li><a href="#Yaxis">yAxis</a></li>

+                                <li><a href="#Axis">axis</a></li>

+                                <ul>

+                                    <li><a href="#AxisAxisline">axisLine</a></li>

+                                    <li><a href="#AxisAxistick">axisTick</a></li>

+                                    <li><a href="#AxisAxislabel">axisLabel</a></li>

+                                    <li><a href="#AxisSplitline">splitLine</a></li>

+                                    <li><a href="#AxisSplitarea">splitArea</a></li>

+                                    <li><a href="#AxisData">data</a></li>

+                                </ul>

+                                <li><a href="#Series">series</a></li>

+                                <ul>

+                                    <li><a href="#SeriesData">data</a></li>

+                                </ul>

+                                <li><a href="#ItemStyle">itemStyle</a></li>

+                                <li><a href="#LineStyle">lineStyle</a></li>

+                                <li><a href="#AreaStyle">areaStyle</a></li>

+                                <li><a href="#TextStyle">textStyle</a></li>

+                                <li><a href="#Loadingoption">loadingOption</a></li>

+                                <li><a href="#Color">color</a></li>

+                                <li><a href="#Calculable">calculable</a></li>

+                                <li><a href="#CalculableColor">calculableColor</a></li>

+                                <li><a href="#CalculableHolderColor">calculableHolderColor</a></li>

+                                <li><a href="#NameConnector">nameConnector</a></li>

+                                <li><a href="#ValueConnector">valueConnector</a></li>

+                                <li><a href="#Animation">animation</a></li>

+                                <li><a href="#AnimationDuration">animationDuration</a></li>

+                                <li><a href="#AnimationEasing">animationEasing</a></li>

+                            </ul>

+                            <li><a href="#多级控制设计">多级控制设计</a></li>

+                            <li><a href="#附录一个直观的事例">附录:一个直观的事例</a></li>

+                        </ul>

+                        </div>

+                      </div>

+                    </div>

+                  </div>

+                  <div class="accordion-group">

+                    <div class="accordion-heading">

+                      <div class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse-config">

+                        <strong>默认选项</strong>

+                      </div>

+                    </div>

+                    <div id="collapse-config" class="accordion-body collapse">

+                      <div class="accordion-inner">

+                        <div id="config"></div>

+                      </div>

+                    </div>

+                  </div>

+              </div><!--/.well -->

+            </div>

+            <div class="span9">

+                <p style="margin:10px 0 -30px 0">

+                    <a href="mailto:kener.linfeng@gmail.com">Any feedback or question ? »</a>

+                </p>

+                <div id="doc">

+                    <h3>简介<a name="简介"> </a></h3>

+                    <p>ECharts,纯Javascript图表库,基于Canvas,底层依赖<a href="http://ecomfe.github.io/zrender/" target="_blank">ZRender</a>,商业产品常用图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。创新的拖拽重计算、数据视图等特性大大增强了用户体验,赋予了用户对数据进行挖掘、整合的能力。图表类型支持折线图(区域图)、柱状图(条状图)、饼图(环形图),同时支持任意维度的堆积和多图表混合展现。</P>

+                    <img src="asset/img/architecture.png" />

+                    <h3>名词解析<a name="名词解析"> </a></h3>

+                    <p>基本名词</p>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 名词 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> chart </td>

+                            <td> 是指一个完整的图表,如折线图,饼图等“基本”图表类型或由基本图表组合而成的“混搭”图表,可能包括坐标轴、图例等 </td>

+                        </tr>

+                        <tr>

+                            <td> axis </td>

+                            <td> 直角坐标系中的一个坐标轴,坐标轴可分为类目轴和数值轴 </td>

+                        </tr>

+                        <tr>

+                            <td> xAxis </td>

+                            <td> 直角坐标系中的横轴,通常并默认为类目轴 </td>

+                        </tr>

+                        <tr>

+                            <td> yAxis </td>

+                            <td> 直角坐标系中的纵轴,通常并默认为数值轴 </td>

+                        </tr>

+                        <tr>

+                            <td> grid </td>

+                            <td> 直角坐标系中除坐标轴外的绘图网格 </td>

+                        </tr>

+                        <tr>

+                            <td> legend </td>

+                            <td> 图例 </td>

+                        </tr>

+                        <tr>

+                            <td> toolbox </td>

+                            <td> 辅助工具箱</td>

+                        </tr>

+                        <tr>

+                            <td> tooltip </td>

+                            <td> 气泡提示框,用于展现更详细的数据 </td>

+                        </tr>

+                        <tr>

+                            <td> dataZoom </td>

+                            <td> 数据区域缩放,常用于展现大数据时选择可视范围 </td>

+                        </tr>

+                        <tr>

+                            <td> series </td>

+                            <td> 数据系列 </td>

+                        </tr>

+                    </table>

+                    <P> 图表名词</P>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 名词 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> line </td>

+                            <td> 折线图,堆积折线图,区域图,堆积区域图 </td>

+                        </tr>

+                        <tr>

+                            <td> bar </td>

+                            <td> 柱形图(纵向),堆积柱形图,条形图(横向),堆积条形图 </td>

+                        </tr>

+                        <tr>

+                            <td> scatter </td>

+                            <td> 散点图,气泡图(暂不支持) </td>

+                        </tr>

+                        <tr>

+                            <td> pie </td>

+                            <td> 饼图,圆环图 </td>

+                        </tr>

+                        <tr>

+                            <td> radar </td>

+                            <td> 雷达图,填充雷达图(暂不支持) </td>

+                        </tr>

+                    </table>

+                    <h3>图表类型<a name="图表类型"> </a></h3>

+                    <P> 图表库标准包含单图表类型的标准图表以及多图表类型混合的混搭图表:</P>

+                    <p><img src="./asset/img/doc/charts.jpg" title="标准图表类型" alt="标准图表类型"/></P>

+

+                    <h4>单图表类型:line<a name="Line"> </a></h4>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 折线图 </th>

+                            <th> 堆积折线图 </th>

+                            <th> 区域图 </th>

+                            <th> 堆积区域图 </th>

+                        </tr>

+                        <tr>

+                            <td><img src="./asset/img/example/line1.png" title="" alt="折线图"/></td>

+                            <td><img src="./asset/img/example/line2.png" title="" alt="堆积折线图"/></td>

+                            <td><img src="./asset/img/example/line3.png" title="" alt="区域图"/></td>

+                            <td><img src="./asset/img/example/line4.png" title="" alt="堆积区域图"/></td>

+                        </tr>

+                    </table>

+

+                    <h4>单图表类型:bar<a name="Bar"> </a></h4>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 柱形图 </th>

+                            <th> 堆积柱形图 </th>

+                            <th> 条形图 </th>

+                            <th> 堆积条形图 </th>

+                        </tr>

+                        <tr>

+                            <td><img src="./asset/img/example/bar1.png" title="" alt="柱形图"/></td>

+                            <td><img src="./asset/img/example/bar2.png" title="" alt="堆积柱形图"/></td>

+                            <td><img src="./asset/img/example/bar3.png" title="" alt="条形图"/></td>

+                            <td><img src="./asset/img/example/bar4.png" title="" alt="堆积条形图"/></td>

+                        </tr>

+                    </table>

+

+                    <h4>单图表类型:scatter(暂不支持)<a name="Scatter"> </a></h4>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 散点图 </th>

+                            <th> 气泡图 </th>

+                        </tr>

+                        <tr>

+                            <td><img src="./asset/img/example/scatter1.jpg" title="" alt="散点图"/></td>

+                            <td><img src="./asset/img/example/scatter2.jpg" title="" alt="气泡图"/></td>

+                        </tr>

+                    </table>

+

+                    <h4>单图表类型:pie<a name="Pie"> </a></h4>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 饼图 </th>

+                            <th> 圆环图 </th>

+                        </tr>

+                        <tr>

+                            <td><img src="./asset/img/example/pie1.png" title="" alt="饼图"/></td>

+                            <td><img src="./asset/img/example/pie2.png" title="" alt="圆环图"/></td>

+                        </tr>

+                    </table>

+

+                    <h4>单图表类型:radar(暂不支持)<a name="Radar"> </a></h4>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 雷达图 </th>

+                            <th> 填充雷达图 </th>

+                        </tr>

+                        <tr>

+                            <td><img src="./asset/img/example/radar1.jpg" title="" alt="雷达图"/></td>

+                            <td><img src="./asset/img/example/radar2.jpg" title="" alt="填充雷达图"/></td>

+                        </tr>

+                    </table>

+                    <h3>初始化<a name="初始化"> </a></h3>

+                    <P> 图表库实现为多实例的,实例选项在新建时传入,同时也可在实例新建后通过实例方法setOption(见<a href="#方法" title="">方法</a>)传入,两种初始化方式最终产出效果是等价的,即如下两组代码产出效果相同。</P>

+                    <div class="code">

+                        <pre>//初始化实例时传入选项

+var myChart = new echarts(option);

+

+//初始化实例选项为空,通过实例方法传入选项

+var myChart = new echarts();

+myChart.setOption(option);

+</pre>

+</div>                        <P> 同时,在实例中任何个性化选项不会影响其他已存在或未来生成的实例。</P>

+

+                    <h3>方法<a name="方法"> </a></h3>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 参数 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td>{void} setOption</td>

+                            <td>{Object} option, {boolean=} notMerge</td>

+                            <td>万能接口,配置图表实例任何可配置选项(详见<a href="#Option" title="">option</a>),多次调用时option选项是默认是合并(merge)的,<br/>如果不需求,可以通过notMerger参数为true阻止与上次option的合并。 </td>

+                        </tr>

+                        <tr>

+                            <td>{void} setSeries</td>

+                            <td>{Array} series, {boolean=} notMerge</td>

+                            <td>数据接口,驱动图表生成的数据内容(详见<a href="#Series" title="">series</a>),效果等同调用setOption({series:{...}}) </td>

+                        </tr>

+                        <tr>

+                            <td>{void} on</td>

+                            <td>{string} eventName, {Function} eventListener</td>

+                            <td>事件绑定,支持事件有:<br/>REFRESH,CLICK,HOVER,<br/>DATA_CHANGED,DATA_ZOOM,LEGEND_SELECTED,MAGIC_TYPE_CHANGED </td>

+                        </tr>

+                        <tr>

+                            <td>{void} un</td>

+                            <td>{string} eventName, {Function} eventListener</td>

+                            <td>事件解绑定 </td>

+                        </tr>

+                        <tr>

+                            <td>{void} showLoading</td>

+                            <td>{Object} loadingOption</td>

+                            <td> 过渡控制(详见<a href="#Loadingoption" title="">loadingOption</a>),显示loading(读取中) </td>

+                        </tr>

+                        <tr>

+                            <td>{void} hideLoading</td>

+                            <td>{void}</td>

+                            <td>过渡控制,隐藏loading(读取中) </td>

+                        </tr>

+                        <tr>

+                            <td>{void} clear</td>

+                            <td>{void}</td>

+                            <td>清空绘画内容,清空后实例可用 </td>

+                        </tr>

+                        <tr>

+                            <td>{void} dispose( {void} ) </td>

+                            <td>{void}</td>

+                            <td>释放图表实例,释放后实例不再可用 </td>

+                        </tr>

+                    </table>

+                    <h3>选项<a name="选项"> </a></h3>

+

+                    <h4>option<a name="Option"> </a></h4>

+                    <P> 图表选项,包含图表实例任何可配置选项</P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {Array} color </td>

+                            <td> 数值系列的颜色列表,默认为null则采用内置颜色,可配数组,eg:['#87cefa', 'rgba(123,123,123,0.5)','...'],当系列数量个数比颜色列表长度大时将循环选取 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} legend </td>

+                            <td> 图例(详见<a href="#Legend" title="">legend</a>),每个图表最多仅有一个图例,混搭图表共享 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} toolbox </td>

+                            <td> 工具箱(详见<a href="#Toolbox" title="">toolbox</a>),每个图表最多仅有一个工具箱 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} tooltip </td>

+                            <td> 提示框(详见<a href="#Tooltip" title="">tooltip</a>),鼠标悬浮交互时的信息提示 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} dataZoom </td>

+                            <td> 数据区域缩放(详见<a href="#DataZoom" title="">dataZoom</a>),数据展现范围选择 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} grid </td>

+                            <td> 直角坐标系内绘图网格(详见<a href="#Grid" title="">grid</a>) </td>

+                        </tr>

+                        <tr>

+                            <td> {Array | Object} xAxis </td>

+                            <td> 直角坐标系中横轴数组(详见<a href="#Xaxis" title="">xAxis</a>),数组中每一项代表一条横轴坐标轴,标准(1.0)中规定最多同时存在2条横轴 </td>

+                        </tr>

+                        <tr>

+                            <td> {Array | Object} yAxis </td>

+                            <td> 直角坐标系中纵轴数组(详见<a href="#Yaxis" title="">yAxis</a>),数组中每一项代表一条纵轴坐标轴,标准(1.0)中规定最多同时存在2条纵轴 </td>

+                        </tr>

+                        <tr>

+                            <td> {Array} series </td>

+                            <td> 驱动图表生成的数据内容(详见<a href="#Series" title="">series</a>),数组中每一项代表一个系列的特殊选项及数据 </td>

+                        </tr>

+                    </table>

+

+                    <h4>legend<a name="Legend"> </a></h4>

+                    <P> 图例,每个图表最多仅有一个图例。<a href="example/legend.html" target="_blank">try this »</a></P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {string} orient </td>

+                            <td> 'horizontal' </td>

+                            <td> 布局方式,默认为水平布局,可选为:'horizontal' | 'vertical' </td>

+                        </tr>

+                        <tr>

+                            <td> {string | number} x </td>

+                            <td> 'center' </td>

+                            <td> 水平安放位置,默认为全图居中,可选为:'center' | 'left' | 'right' | {number}(x坐标,单位px) </td>

+                        </tr>

+                        <tr>

+                            <td> {string | number} y </td>

+                            <td> 'top' </td>

+                            <td> 垂直安放位置,默认为全图顶端,可选为:'top' | 'bottom' | 'center' | {number}(y坐标,单位px) </td>

+                        </tr>

+                        <tr>

+                            <td> {color} backgroundColor </td>

+                            <td> 'rgba(0,0,0,0)' </td>

+                            <td> 图例背景颜色,默认透明 </td>

+                        </tr>

+                        <tr>

+                            <td> {string} borderColor </td>

+                            <td> '#ccc' </td>

+                            <td> 图例边框颜色 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} borderWidth </td>

+                            <td> 0 </td>

+                            <td> 图例边框线宽,单位px,默认为0(无边框) </td>

+                        </tr>

+                        <tr>

+                            <td> {number | Array} padding </td>

+                            <td> 5 </td>

+                            <td> 图例内边距,单位px,默认各方向内边距为5,接受数组分别设定上右下左边距,同css,见下图 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} itemGap </td>

+                            <td> 10 </td>

+                            <td> 各个item之间的间隔,单位px,默认为10,横向布局时为水平间隔,纵向布局时为纵向间隔,见下图 </td>

+                        </tr>

+                        <!--

+                        <tr>

+                            <td> {number} itemWidth </td>

+                            <td> 20 </td>

+                            <td> 图例图形宽度 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} itemHeight </td>

+                            <td> 14 </td>

+                            <td> 图例图形高度 </td>

+                        </tr>

+                        -->

+                        <tr>

+                            <td> {Object} textStyle </td>

+                            <td> {color: '#333'} </td>

+                            <td> 默认只设定了图例文字颜色(详见<a href="#TextStyle" title="">textStyle</a>) </td>

+                        </tr>

+                        <tr>

+                            <td> {Array &lt;string&gt;} data </td>

+                            <td> [ ] </td>

+                            <td> 图例内容数组,数组项为{string},每一项代表一个系列的name。<br/>使用根据该值索引<a href="#Series" title="">series</a>中同名系列所用的图表类型和itemStyle,如果索引不到,该item将不显示。</td>

+                        </tr>

+                    </table>

+                    <p><img src="./asset/img/doc/legend.png" title="" alt="图例"/></P>

+

+                    <h4>toolbox<a name="Toolbox"> </a></h4>

+                    <P> 工具箱,每个图表最多仅有一个工具箱。</P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {boolean} show </td>

+                            <td> false </td>

+                            <td> 显示策略,可选为:true(显示) | false(隐藏) </td>

+                        </tr>

+                        <tr>

+                            <td> {string} orient </td>

+                            <td> 'horizontal' </td>

+                            <td> 布局方式,默认为水平布局,可选为:'horizontal' | 'vertical' </td>

+                        </tr>

+                        <tr>

+                            <td> {string | number} x </td>

+                            <td> 'center' </td>

+                            <td> 水平安放位置,默认为全图居中,可选为:'center' | 'left' | 'right' | {number}(x坐标,单位px) </td>

+                        </tr>

+                        <tr>

+                            <td> {string | number} y </td>

+                            <td> 'top' </td>

+                            <td> 垂直安放位置,默认为全图顶端,可选为:'top' | 'bottom' | 'center' | {number}(y坐标,单位px) </td>

+                        </tr>

+                        <tr>

+                            <td> {color} backgroundColor </td>

+                            <td> 'rgba(0,0,0,0)' </td>

+                            <td> 工具箱背景颜色,默认透明 </td>

+                        </tr>

+                        <tr>

+                            <td> {string} borderColor </td>

+                            <td> '#ccc' </td>

+                            <td> 工具箱边框颜色 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} borderWidth </td>

+                            <td> 0 </td>

+                            <td> 工具箱边框线宽,单位px,默认为0(无边框) </td>

+                        </tr>

+                        <tr>

+                            <td> {number | Array} padding </td>

+                            <td> 5 </td>

+                            <td> 工具箱内边距,单位px,默认各方向内边距为5,接受数组分别设定上右下左边距,同css,见下图 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} itemGap </td>

+                            <td> 10 </td>

+                            <td> 各个item之间的间隔,单位px,默认为10,横向布局时为水平间隔,纵向布局时为纵向间隔,见下图 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} itemSize </td>

+                            <td> 16 </td>

+                            <td> 工具箱icon大小,单位(px)</td>

+                        </tr>

+                        <tr>

+                            <td> {Array &lt;color&gt;} color </td>

+                            <td> ['#1e90ff','#22bb22','#4b0082','#d2691e'] </td>

+                            <td> 工具箱icon颜色序列,循环使用 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} feature </td>

+                            <td> {} </td>

+                            <td> 启用功能,目前支持feature见下</td>

+                        </tr>

+                    </table>

+                    <p><img src="./asset/img/doc/toolbox.png" title="" alt="工具箱"/></P>

+                    <div class="code">

+                    <pre>

+feature : {

+    mark : true,                    // 辅助线标志

+    dataView : true,                // 数据视图

+    magicType:['line', 'bar'],      // 图表类型切换,当前仅支持直角系下的折线图、柱状图转换

+    refresh : true                  // 刷新,复位原始图表

+}

+                    </pre>

+                    </div>

+                    <p>feature选项</p>

+                    <ul>

+                        <li>

+                            mark,辅助线标志

+                            <ul>

+                                <li>简单传入true启动辅助线标志功能</li>

+                                <li>传入lineStyle(详见<a href="#LineStyle" title="">lineStyle</a>)控制线条样式</li>

+                            </ul>

+                        </li>

+                        <li>

+                            dataView,数据视图

+                            <ul>

+                                <li>简单传入true启动数据视图</li>

+                                <li>传入{Object}设置更多属性</li>

+                                <ul>

+                                    <li>{boolean=} readOnly 默认数据视图为只读,可指定readOnly为false打开编辑功能</li>

+                                    <li>{Function=} optionToContent 自主编排数据视图的显示内容</li>

+                                    <li>{Function=} contentToOption 当数据视图readOnly为false时,会出现刷新按钮,如果是自主编排的显示内容,如何翻转也请自理</li>

+                                    <li>{Array=} lang 数据视图上有三个话术,默认是['Data View', 'close', 'refresh'],如需改写,可自定义</li>

+                                </ul>

+                            </ul>

+                        </li>

+                        <li>

+                            magicType,图表类型切换,当前仅支持直角系下的折线图、柱状图转换

+                            <ul>

+                                <li>['line', 'bar']</li>

+                            </ul>

+                        </li>

+                    </ul>

+

+                    <h4>tooltip<a name="Tooltip"> </a></h4>

+                    <P> 提示框,鼠标悬浮交互时的信息提示。<a href="example/tooltip.html" target="_blank">try this »</a></P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {string} trigger </td>

+                            <td> 'item' </td>

+                            <td> 触发类型,默认数据触发,见下图,可选为:'item' | 'axis' </td>

+                        </tr>

+                        <tr>

+                            <td> {boolean} show </td>

+                            <td> true </td>

+                            <td> 显示策略,可选为:true(显示) | false(隐藏) </td>

+                        </tr>

+                        <tr>

+                            <td> {string | Function} formatter </td>

+                            <td> null </td>

+                            <td> 内容格式器:{string}(Template) | {Function},支持异步回调见表格下方</td>

+                        </tr>

+                        <tr>

+                            <td> {string | Function} islandFormatter </td>

+                            <td> '{a} &lt; br/&gt;{b} : {c}' </td>

+                            <td> 拖拽重计算独有,数据孤岛内容格式器:{string}(Template) | {Function},见表格下方</td>

+                        </tr>

+                        <tr>

+                            <td> {color} backgroundColor </td>

+                            <td> 'rgba(0,0,0,0.7)' </td>

+                            <td> 提示背景颜色,默认为透明度为0.7的黑色 </td>

+                        </tr>

+                        <tr>

+                            <td> {string} borderColor </td>

+                            <td> '#333' </td>

+                            <td> 提示边框颜色 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} borderRadius </td>

+                            <td> 4 </td>

+                            <td> 提示边框圆角,单位px,默认为4 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} borderWidth </td>

+                            <td> 0 </td>

+                            <td> 提示边框线宽,单位px,默认为0(无边框) </td>

+                        </tr>

+                        <tr>

+                            <td> {number | Array} padding </td>

+                            <td> 5 </td>

+                            <td> 提示内边距,单位px,默认各方向内边距为5,接受数组分别设定上右下左边距,同css </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} textStyle </td>

+                            <td> { color:'#fff' } </td>

+                            <td> 文本样式,默认为白色字体(详见<a href="#TextStyle" title="">textStyle</a>) </td>

+                        </tr>

+                    </table>

+                    <P> 内容格式器formatter:</P>

+                    <ul>

+                        <li>

+                            {string},模板(Template),其变量为:

+                            <ul>

+                                <li>{a} | {a0}</li>

+                                <li>{b} | {b0}</li>

+                                <li>{c} | {c0}</li>

+                                <li>{d} | {d0} (部分图表类型无此项)</li>

+                                <li> 多值下则存在多套{a1}, {b1}, {c1}, {d1}, {a2}, {b2}, {c2}, {d2}, ...</li>

+                                <li> 其中变量a、b、c在不同图表类型下代表数据含义为:

+                                    <ul>

+                                        <li>折线(区域)图、柱状(条形)图、散点图 : a(系列名称),b(类目值),c(数值), d(无)</li>

+                                        <li>气泡图 : a(系列名称),b(横轴值),c(纵轴值), d(数值)</li>

+                                        <li>饼图、雷达图 : a(系列名称),b(数据项名称),c(数值), d(百分比)</li>

+                                    </ul>

+                                </li>

+                            </ul>

+                        </li>

+                        <li>

+                            {Function},传递参数列表如下:

+                            <ul>

+                                <li>&lt;Array&gt; params : 数组内容同模板变量,[[a, b, c, d], [a1, b1, c1, d1], ...]</li>

+                                <li>&lt;String&gt; ticket : 异步回调标识</li>

+                                <li>&lt;Function&gt; callback : 异步回调,回调时需要两个参数,第一个为前面提到的ticket,第二个为填充内容html</li>

+                            </ul>

+                        </li>

+                    </ul>

+                    <P> 触发类型:</P>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> item触发 </th>

+                            <th> axis触发 </th>

+                        </tr>

+                        <tr>

+                            <td><img src="./asset/img/doc/tooltip1.jpg" title="" alt="item触发"/></td>

+                            <td><img src="./asset/img/doc/tooltip2.jpg" title="" alt="axis触发"/></td>

+                        </tr>

+                    </table>

+

+                    <h4>dataZoom<a name="DataZoom"> </a></h4>

+                    <P> 数据区域缩放。仅对直角坐标系图表有效。<a href="example/dataZoom.html" target="_blank">try this »</a></P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {boolean} show </td>

+                            <td> false </td>

+                            <td> 是否显示,当show为true时则接管使用指定类目轴的全部系列数据,如不指定则接管全部直角坐标系数据。 </td>

+                        </tr>

+                        <tr>

+                            <td> {boolean} realtime </td>

+                            <td> false </td>

+                            <td> 缩放变化是否实时显示,建议性能较低的浏览器或数据量巨大时不启动实时效果。 </td>

+                        </tr>

+                        <tr>

+                            <td> {string} orient </td>

+                            <td> 'horizontal' </td>

+                            <td> 布局方式,默认为水平布局,可选为:'horizontal' | 'vertical' </td>

+                        </tr>

+                        <tr>

+                            <td> {number} x </td>

+                            <td> 自适应 </td>

+                            <td> 水平安放位置,默认为根据grid参数适配,纵向布局默认左侧,可指定 {number}(左上角x坐标,单位px) </td>

+                        </tr>

+                        <tr>

+                            <td> {number} y </td>

+                            <td> 自适应 </td>

+                            <td> 垂直安放位置,默认为根据grid参数适配,纵向布局默认下方,可指定 {number}(左上角y坐标,单位px) </td>

+                        </tr>

+                        <tr>

+                            <td> {number} width </td>

+                            <td> 自适应 | 30</td>

+                            <td> 指定宽度,横向布局时默认为根据grid参数适配,纵向布局是默认为30,可指定 {number}(宽度,单位px) </td>

+                        </tr>

+                        <tr>

+                            <td> {number} height </td>

+                            <td> 自适应  | 30</td>

+                            <td> 指定高度,纵向布局时默认为根据grid参数适配,横向布局是默认为30,可指定 {number}(高度,单位px) </td>

+                        </tr>

+                        <tr>

+                            <td> {color} backgroundColor </td>

+                            <td> '#eee' </td>

+                            <td> 背景颜色 </td>

+                        </tr>

+                        <tr>

+                            <td> {color} dataBackgroundColor </td>

+                            <td> '#ccc' </td>

+                            <td> 数据缩略背景颜色 </td>

+                        </tr>

+                        <tr>

+                            <td> {color} fillerColor </td>

+                            <td> 'rgba(50,205,50,0.4)' </td>

+                            <td> 选择区域填充颜色 </td>

+                        </tr>

+                        <tr>

+                            <td> {color} handleColor </td>

+                            <td> 'rgba(70,130,180,0.8)' </td>

+                            <td> 控制手柄颜色  </td>

+                        </tr>

+                        <tr>

+                            <td> {(Array | number)} xAxisIndex </td>

+                            <td> null </td>

+                            <td> 当不指定时默认控制所有横向类目,可通过数组指定多个需要控制的横向类目坐标轴Index,仅一个时可直接为数字 </td>

+                        </tr>

+                        <tr>

+                            <td> {(Array | number)} yAxisIndex </td>

+                            <td> null </td>

+                            <td> 当不指定时默认控制所有纵向类目,可通过数组指定多个需要控制的纵向类目坐标轴Index,仅一个时可直接为数字 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} start </td>

+                            <td> 0 </td>

+                            <td> 数据缩放,选择起始比例,默认为0,从首个数据起选择。</td>

+                        </tr>

+                        <tr>

+                            <td> {number} end </td>

+                            <td> 100 </td>

+                            <td> 数据缩放,选择结束比例,默认为100(%),到最后一个数据选择结束。 </td>

+                        </tr>

+                        <tr>

+                            <td> {boolean} zoomLock </td>

+                            <td> false </td>

+                            <td> 数据缩放锁,默认为false,当设置为true时选择区域不能伸缩,即(end - start)值保持不变,仅能做数据漫游。</td>

+                        </tr>

+                    </table>

+

+                    <h4>grid<a name="Grid"> </a></h4>

+                    <P> 直角坐标系内绘图网格</P>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {number} x </td>

+                            <td> 80 </td>

+                            <td> 直角坐标系内绘图网格起始横坐标,数值单位px </td>

+                        </tr>

+                        <tr>

+                            <td> {number} y </td>

+                            <td> 60 </td>

+                            <td> 直角坐标系内绘图网格起始纵坐标,数值单位px </td>

+                        </tr>

+                        <tr>

+                            <td> {number} width </td>

+                            <td> 自适应 </td>

+                            <td> 直角坐标系内绘图网格(不含坐标轴)宽度,默认为总宽度 - 2 * x,数值单位px,见下图。 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} height </td>

+                            <td> 自适应 </td>

+                            <td> 直角坐标系内绘图网格(不含坐标轴)高度,默认为总宽度 - 2 * y,数值单位px,见下图。 </td>

+                        </tr>

+                        <tr>

+                            <td> {color} backgroundColor </td>

+                            <td> '#fff' </td>

+                            <td> 背景颜色。 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} borderWidth </td>

+                            <td> 1 </td>

+                            <td> 边框线宽 </td

+                        </tr>

+                        <tr>

+                            <td> {color} borderColor </td>

+                            <td> '#ccc' </td>

+                            <td> 边框颜色。 </td>

+                        </tr>

+                    </table>

+                    <p><img src="./asset/img/doc/grid.jpg" title="" alt="绘图网格"/></P>

+

+                    <h4>xAxis<a name="Xaxis"> </a></h4>

+                    <P>直角坐标系中横轴数组,数组中每一项代表一条横轴坐标轴,仅有一条时可省略数值。最多同时存在2条横轴,单条横轴时可指定安放于<a href="#Grid" title="">grid</a>的底部(默认)或顶部,2条同时存在时位置互斥,默认第一条安放于底部,第二条安放于顶部。</p>

+                    <p>坐标轴有两种类型,类目型和数值型(区别详见<a href="#Axis" title="">axis</a>),横轴通常为类目型,但条形图时则横轴为数值型,散点图时则横纵均为数值型,具体参数详见<a href="#Axis" title="">axis</a>。</P>

+

+                    <h4>yAxis<a name="Yaxis"> </a></h4>

+                    <P>直角坐标系中纵轴数组,数组中每一项代表一条纵轴坐标轴,仅有一条时可省略数值。最多同时存在2条纵轴,单条纵轴时可指定安放于<a href="#Grid" title="">grid</a>的左侧(默认)或右侧,2条同时存在时位置互斥,默认第一条安放于左侧,第二条安放于右侧。</p>

+                    <p>坐标轴有两种类型,类目型和数值型(区别详见<a href="#Axis" title="">axis</a>),纵轴通常为数值型,但条形图时则纵轴为类目型,具体参数详见<a href="#Axis" title="">axis</a>。</P>

+

+                    <h4>axis<a name="Axis"> </a><a name="CategoryAxis"> </a><a name="ValueAxis"> </a></h4>

+                    <P> 坐标轴有两种类型,类目型和数值型,他们的区别在于:</P>

+                    <ul>

+                        <li>类目型:需要指定类目列表,坐标轴内有且仅有这些指定类目坐标</li>

+                        <li>数值型:需要指定数值区间,坐标轴内包含数值区间内容全部坐标</li>

+                    </ul>

+                    <P> 下面是坐标轴的全部选项,其中个别选项仅在类目型或数值型时有效,请注意适用类型。<a href="example/axis.html" target="_blank">try this »</a></P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 适用类型 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {string} type </td>

+                            <td> 'category' | 'value' </td>

+                            <td> 通用 </td>

+                            <td> 坐标轴类型,横轴默认为类目型'category',纵轴默认为数值型'value' </td>

+                        </tr>

+                        <tr>

+                            <td> {string} position </td>

+                            <td> 'bottom' | 'left' </td>

+                            <td> 通用 </td>

+                            <td> 坐标轴类型,横轴默认为类目型'bottom',纵轴默认为数值型'left',可选为:'bottom' | 'top' | 'left' | 'right' </td>

+                        </tr>

+                        <tr>

+                            <td> {boolean} boundaryGap </td>

+                            <td> true </td>

+                            <td> 类目型 </td>

+                            <td> 类目起始和结束两端空白策略,见下图,默认为true留空,false则顶头 </td>

+                        </tr>

+                        <tr>

+                            <td> {Array} boundaryGap </td>

+                            <td> [0, 0] </td>

+                            <td> 数值型 </td>

+                            <td> 数值轴两端空白策略,数组内数值代表百分比,[原始数据最小值与最终最小值之间的差额,原始数据最大值与最终最大值之间的差额] </td>

+                        </tr>

+                        <tr>

+                            <td> {number} min </td>

+                            <td> null </td>

+                            <td> 数值型 </td>

+                            <td> 指定的最小值,eg: 0,默认无,会自动根据具体数值调整,指定后将忽略boundaryGap[0] </td>

+                        </tr>

+                        <tr>

+                            <td> {number} max </td>

+                            <td> null </td>

+                            <td> 数值型 </td>

+                            <td> 指定的最大值,eg: 100,默认无,会自动根据具体数值调整,指定后将忽略boundaryGap[1] </td>

+                        </tr>

+                        <tr>

+                            <td> {number} precision </td>

+                            <td> 0 </td>

+                            <td> 数值型 </td>

+                            <td> 小数精度,默认为0,无小数点 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} power </td>

+                            <td> 100 </td>

+                            <td> 数值型 </td>

+                            <td> 整数精度,默认为100,个位和百位为0 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} splitNumber </td>

+                            <td> 5 </td>

+                            <td> 数值型 </td>

+                            <td> 分割段数,默认为5 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} axisLine </td>

+                            <td> {show : true} </td>

+                            <td> 通用 </td>

+                            <td> 坐标轴线,默认显示,属性show控制显示与否,属性lineStyle(详见<a href="#LineStyle" title="">lineStyle</a>)控制线条样式 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} axisTick </td>

+                            <td> {show : false} </td>

+                            <td> 通用 </td>

+                            <td> 坐标轴小标记,默认不显示,属性show控制显示与否,属性length控制线长,属性lineStyle(详见<a href="#LineStyle" title="">lineStyle</a>)控制线条样式 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} axisLabel </td>

+                            <td> {show : true} </td>

+                            <td> 通用 </td>

+                            <td> 坐标轴文本标签,详见<a href="#AxisAxislabel" title="">axis.axisLabel</a></td>

+                        </tr>

+                        <tr>

+                            <td> {Object} splitLine </td>

+                            <td> {show : true} </td>

+                            <td> 通用 </td>

+                            <td> 分隔线,默认显示,属性show控制显示与否,属性lineStyle(详见<a href="#LineStyle" title="">lineStyle</a>)控制线条样式 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} splitArea </td>

+                            <td> {show : false} </td>

+                            <td> 通用 </td>

+                            <td> 分隔区域,默认不显示,属性show控制显示与否,属性areaStyle(详见<a href="#AreaStyle" title="">areaStyle</a>)控制区域样式 </td>

+                        </tr>

+                        <tr>

+                            <td> {Array} data </td>

+                            <td> [] </td>

+                            <td> 类目型 </td>

+                            <td> 类目列表,同时也是label内容,详见<a href="#AxisData" title="">axis.data</a></td>

+                        </tr>

+                    </table>

+                    <P> boundaryGap端空白策略</P>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 设置 </th>

+                            <th> 效果 </th>

+                        </tr>

+                        <tr>

+                            <td> boundaryGap: true </td>

+                            <td><img src="./asset/img/doc/axisBoundaryGap1.jpg" title="" alt="axisBoundaryGap1"/></td>

+                        </tr>

+                        <tr>

+                            <td> boundaryGap: false </td>

+                            <td><img src="./asset/img/doc/axisBoundaryGap.png" title="" alt="axisBoundaryGap"/></td>

+                        </tr>

+                    </table>

+                    <P> axis属性说明</P>

+                    <p><img src="./asset/img/doc/axisDetail.png" title="" alt="axisDetail"/></P>

+

+                    <h5>axis.axisLine<a name="AxisAxisline"> </a></h5>

+                    <P> 坐标轴线,默认显示且带如下样式:</P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 适用类型 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {boolean} show </td>

+                            <td> true </td>

+                            <td> 通用 </td>

+                            <td> 是否显示,默认为true,设为false后下面都没意义了 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} lineStyle </td>

+                            <td> {color: '#48b', width: 2, style: 'solid'} </td>

+                            <td> 通用 </td>

+                            <td> 属性lineStyle控制线条样式,(详见<a href="#LineStyle" title="">lineStyle</a>) </td>

+                        </tr>

+                    </table>

+

+                    <h5>axis.axisTick<a name="AxisAxistick"> </a></h5>

+                    <P> 坐标轴小标记,默认不显示,默认样式见下:</P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 适用类型 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {boolean} show </td>

+                            <td> false </td>

+                            <td> 通用 </td>

+                            <td> 是否显示,默认为false,设为true后下面为默认样式 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} length </td>

+                            <td> 4 </td>

+                            <td> 通用 </td>

+                            <td> 属性length控制线长 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} lineStyle </td>

+                            <td> {color: '#ccc', width: 1, style: 'solid'} </td>

+                            <td> 通用 </td>

+                            <td> 属性lineStyle控制线条样式,(详见<a href="#LineStyle" title="">lineStyle</a>) </td>

+                        </tr>

+                    </table>

+

+                    <h5>axis.axisLabel<a name="AxisAxislabel"> </a></h5>

+                    <P> 坐标轴文本标签选项</P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 适用类型 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {boolean} show </td>

+                            <td> true </td>

+                            <td> 通用 </td>

+                            <td> 是否显示,默认为true,设为false后下面都没意义了 </td>

+                        </tr>

+                        <tr>

+                            <td> {string | number} interval </td>

+                            <td> 'auto' </td>

+                            <td> 类目型 </td>

+                            <td> 标签显示挑选间隔,默认为'auto',可选为:'auto'(自动隐藏显示不下的) | 0(全部显示) | {number}(用户指定选择间隔) </td>

+                        </tr>

+                        <tr>

+                            <td> {number} rotate </td>

+                            <td> 0 </td>

+                            <td> 通用 </td>

+                            <td> 标签旋转角度,默认为0,不旋转,正直为逆时针,负值为顺时针,可选为:-90 ~ 90 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} margin </td>

+                            <td> 8 </td>

+                            <td> 通用 </td>

+                            <td> 坐标轴文本标签与坐标轴的间距,默认为8,单位px </td>

+                        </tr>

+                        <tr>

+                            <td> {string | Function} formatter </td>

+                            <td> null </td>

+                            <td> 通用 </td>

+                            <td> 间隔名称格式器:{string}(Template) | {Function} </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} textStyle </td>

+                            <td> {color: '#333'} </td>

+                            <td> 通用 </td>

+                            <td> 文本样式(详见<a href="#TextStyle" title="">textStyle</a>) </td>

+                        </tr>

+                    </table>

+                    <P> 间隔名称格式器formatter:</P>

+                    <ul>

+                        <li>

+                            {string},模板(Template),其变量为:

+                            <ul>

+                                <li>

+                                    {value}: 内容或值

+                                </li>

+                            </ul>

+

+                        </li>

+

+                        <li>

+                            {Function},传递参数同模板变量:

+                            <ul>

+                                <li>

+                                    eg:function(value){return "星期" + "日一二三四五六".charAt(value);'}

+                                </li>

+                            </ul>

+

+                        </li>

+                    </ul>

+

+                    <h5>axis.splitLine<a name="AxisSplitline"> </a></h5>

+                    <P> 分隔线,默认显示且带如下样式:</P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 适用类型 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {boolean} show </td>

+                            <td> true </td>

+                            <td> 通用 </td>

+                            <td> 是否显示,默认为true,设为false后下面都没意义了 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} lineStyle </td>

+                            <td> {color: '#ccc', width: 1, style: 'solid'} </td>

+                            <td> 通用 </td>

+                            <td> 属性lineStyle控制线条样式,(详见<a href="#LineStyle" title="">lineStyle</a>) </td>

+                        </tr>

+                    </table>

+

+                    <h5>axis.splitArea<a name="AxisSplitarea"> </a></h5>

+                    <P> 分隔区域,默认不显示:</P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 适用类型 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {boolean} show </td>

+                            <td> false </td>

+                            <td> 通用 </td>

+                            <td> 是否显示,默认为false,设为true后带如下默认样式 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} areaStyle </td>

+                            <td> {color: ['rgba(250,250,250,0.3)','rgba(200,200,200,0.3)']} </td>

+                            <td> 通用 </td>

+                            <td> 属性areaStyle(详见<a href="#AreaStyle" title="">areaStyle</a>)控制区域样式,颜色数组实现间隔变换。 </td>

+                        </tr>

+                    </table>

+

+                    <h5>axis.data<a name="AxisData"> </a></h5>

+                    <P> 类目型坐标轴文本标签数组,指定label内容。

+                        数组项通常为文本,如:</P>

+                    <div class="code">

+                        <pre>[&#39;Jan&#39;, &#39;Feb&#39;, &#39;Mar&#39;, &#39;Apr&#39;, &#39;May&#39;, &#39;Jun&#39;, ..., &#39;Dec&#39;]

+</pre>

+</div>                        <P> 当需要对个别标签进行个性化定义时,数组项可用对象,接受textStyle设置个性化标签,如:</P>

+                    <div class="code">

+                        <pre>[

+    &#39;Jav&#39;, &#39;Feb&#39;, &#39;Mar&#39;,

+     {

+        value:&#39;Apr&#39;,            //文本内容,如指定间隔名称格式器formatter,则这个值将被作为模板变量值或参数传入

+        textStyle:{             //详见textStyle

+            color : &#39;red&#39;

+            ...

+        }

+     },

+    &#39;May&#39;, &#39;...&#39;

+]

+</pre>

+</div>

+

+                    <h4>series<a name="Series"> </a></h4>

+                    <P> 驱动图表生成的数据内容数组,数组中每一项为一个系列的选项及数据,其中个别选项仅在部分图表类型中有效,请注意适用类型:</P>

+                    <table cellspacing="0" class="ADoc_table full">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 适用类型 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {string} name </td>

+                            <td> null </td>

+                            <td> 通用 </td>

+                            <td> 系列名称,如启用legend,该值将被legend.data索引相关 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} tooltip </td>

+                            <td> null </td>

+                            <td> 通用 </td>

+                            <td> 提示框样式,仅对本系列有效,如不设则用option.tooltip(详见<a href="#Tooltip" title="">tooltip</a>),鼠标悬浮交互时的信息提示 </td>

+                        </tr>

+                        <tr>

+                            <td> {string} type </td>

+                            <td> null </td>

+                            <td> 通用 </td>

+                            <td> 图表类型,必要参数!如为空或不支持类型,则该系列数据不被显示。<br/>可选为:'line'(折线图) | 'bar'(柱状图) | 'pie'(饼图) | 'scatter'(散点图,暂不支持) | 'radar'(雷达图,暂不支持) </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} itemStyle </td>

+                            <td> null </td>

+                            <td> 通用 </td>

+                            <td> 图形样式(详见<a href="#ItemStyle" title="">itemStyle</a>) </td>

+                        </tr>

+                        <tr>

+                            <td> {string} stack </td>

+                            <td> null </td>

+                            <td> 折线图,柱状图 </td>

+                            <td> 组合名称,多组数据的堆积图时使用,eg:stack:'group1',则series数组中stack值等于'group1'的数据做堆积计算 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} xAxisIndex </td>

+                            <td> 0 </td>

+                            <td> 折线图,柱状图,散点图 </td>

+                            <td><a href="#Xaxis" title="">xAxis</a>坐标轴数组的索引,指定该系列数据所用的横坐标轴 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} yAxisIndex </td>

+                            <td> 0 </td>

+                            <td> 折线图,柱状图,散点图 </td>

+                            <td><a href="#Yaxis" title="">yAxis</a>坐标轴数组的索引,指定该系列数据所用的纵坐标轴 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} barMinHeight </td>

+                            <td> 20 </td>

+                            <td> 柱状图 </td>

+                            <td> 柱条最小高度,防止某item的值过小而影响交互 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} barWidth </td>

+                            <td> 自适应 </td>

+                            <td> 柱状图 </td>

+                            <td> 柱条宽度,不设时自适应 </td>

+                        </tr>

+                        <tr>

+                            <td> {string} brokenPoint </td>

+                            <td> null </td>

+                            <td> 折线图 </td>

+                            <td> 拐点图形类型,默认自动选择(8种类型循环使用),支持类型有:<br/>'circle' | 'rectangle' | 'triangle' | 'diamond' |<br/>'emptyCircle' | 'emptyRectangle' | 'emptyTriangle' | 'emptyDiamond'</td>

+                        </tr>

+                        <tr>

+                            <td> {number} brokenPointSize </td>

+                            <td> 4 </td>

+                            <td> 折线图 </td>

+                            <td> 拐点图形大小,可计算特性启用情况建议增大以提高交互体验。</td>

+                        </tr>

+                        <tr>

+                            <td> {Array} center </td>

+                            <td> null </td>

+                            <td> 饼图 </td>

+                            <td> 圆心坐标,默认为[width / 2, height / 2]自适应居中 </td>

+                        </tr>

+                        <tr>

+                            <td> {number | Array} radius </td>

+                            <td> 自适应 </td>

+                            <td> 饼图 </td>

+                            <td> 半径,默认为Min(width, height) / 2 - 50, 传数组实现环形图,[内半径,外半径] </td>

+                        </tr>

+                        <tr>

+                            <td> {number} startAngle </td>

+                            <td> 0 </td>

+                            <td> 饼图 </td>

+                            <td> 开始角度, 有效输入范围:[-180,180]</td>

+                        </tr>

+                        <tr>

+                            <td> {number} minAngle </td>

+                            <td> 5 </td>

+                            <td> 饼图 </td>

+                            <td> 最小角度,防止某item的值过小而影响交互 </td>

+                        </tr>

+                        <tr>

+                            <td> {Array} data </td>

+                            <td> [] </td>

+                            <td> 通用 </td>

+                            <td> 数据(详见<a href="#SeriesData" title="">series.data</a>) </td>

+                        </tr>

+                    </table><h5>series.data<a name="SeriesData"> </a></h5>

+                    <P> 系列中的数据内容数组,折线图以及柱状图时数组长度等于所使用类目轴文本标签数组<a href="#AxisData" title="">axis.data</a>的长度,并且他们间是一一对应的。数组项通常为数值,如:</P>

+                    <div class="code">

+                        <pre>[12, 34, 56, ..., 10, 23]

+</pre>

+</div>                        <P> 当某类目对应数据不存在时(ps:'不存在' 不代表值为 0),可用'-'表示,无数据在折线图中表现为折线在该点断开,在柱状图中表现为该点无柱形,如:</P>

+                    <div class="code">

+                        <pre>[12, &#39;-&#39;, 56, ..., 10, 23]

+</pre>

+</div>                        <P> 当需要对个别内容进行个性化定义时,数组项可用对象,如:</P>

+                    <div class="code">

+                        <pre>[

+    12, 34,

+    {

+        value : 56,

+        tooltip:{},             //自定义特殊tooltip,仅对该item有效,详见tooltip

+        itemStyle:{}            //自定义特殊itemStyle,仅对该item有效,详见itemStyle

+    },

+    ..., 10, 23

+]

+</pre>

+</div>                        <P> 当图表类型为scatter(散点图或气泡图)时,其数值设置比较特殊,他的横纵坐标轴都可能为数值型,并且气泡图时需要指定气泡大小,所以scatter型图表设置为:</P>

+                    <div class="code">

+                        <pre>[

+    {

+        value : [10, 25, 5]     //[xValue, yValue, rValue],数组内依次为横值,纵值,大小

+    },

+    ...,

+    {

+        value : [30, 128, 15],  //同上

+        tooltip:{},             //自定义特殊tooltip,仅对该item有效,详见tooltip

+        itemStyle:{}            //自定义特殊itemStyle,仅对该item有效,详见itemStyle

+    }

+]

+</pre>

+</div>                        <P> 当图表类型为饼图时,需要说明每部分数据的名称name,所以设置为:</P>

+                    <div class="code">

+                        <pre>[

+    {

+        value : 12,

+        name : &#39;apple&#39;          //每部分数据的名称

+    },

+    ...,

+    {

+        value : 23,             //同上

+        name : &#39;orange&#39;         //同上

+        tooltip:{},             //自定义特殊tooltip,仅对该item有效,详见tooltip

+        itemStyle:{}            //自定义特殊itemStyle,仅对该item有效,详见itemStyle

+    }

+]

+</pre>

+</div>

+

+                    <h4>itemStyle<a name="ItemStyle"> </a></h4>

+                    <P> 图形样式,可设置图表内图形的默认样式和强调样式(悬浮时样式):</P>

+                    <div class="code">

+                        <pre>itemStyle: {

+    normal: {

+        ...

+    },

+    emphasis: {

+        ...

+    }

+}

+</pre>

+</div>                        <P> 其中normal和emphasis属性为对象,其包含:</P>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 适用类型 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {color} color </td>

+                            <td> 图表各异 </td>

+                            <td> 通用 </td>

+                            <td> 颜色 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} lineStyle </td>

+                            <td> 图表各异 </td>

+                            <td> 折线图 </td>

+                            <td> 线条样式,详见<a href="#LineStyle" title="">lineStyle</a></td>

+                        </tr>

+                        <tr>

+                            <td> {Object} areaStyle </td>

+                            <td> 图表各异 </td>

+                            <td> 堆积折线图,填充雷达图</td>

+                            <td> 区域样式,详见<a href="#AreaStyle" title="">areaStyle</a></td>

+                        </tr>

+                        <tr>

+                            <td> {Object} label </td>

+                            <td> {show: true,  position:'outer'} </td>

+                            <td> 饼图 </td>

+                            <td> 饼图标签,默认显示在外部,离饼图距离由labelLine.length决定 </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} labelLine </td>

+                            <td> {show: true} </td>

+                            <td> 饼图 </td>

+                            <td> 饼图标签视觉引导线,默认显示 </td>

+                        </tr>

+                    </table>

+                    <P> 其中饼图标签label属性为对象,其包含:</P>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {boolean} show </td>

+                            <td> true </td>

+                            <td> 标签显示策略,可选为:true(显示) | false(隐藏) </td>

+                        </tr>

+                        <tr>

+                            <td> {string} position </td>

+                            <td> 'outer' </td>

+                            <td> 标签显示位置,可选为:'outer'(外部) | 'inner'(内部) </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} textStyle </td>

+                            <td> null </td>

+                            <td> 标签的文本样式(详见<a href="#TextStyle" title="">textStyle</a>) </td>

+                        </tr>

+                    </table>

+                    <P> 其中饼图标签视觉引导线labelLine属性为对象,其包含:</P>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {boolean} show </td>

+                            <td> true </td>

+                            <td> 饼图标签视觉引导线显示策略,可选为:true(显示) | false(隐藏) </td>

+                        </tr>

+                        <tr>

+                            <td> {number} length </td>

+                            <td> 40 </td>

+                            <td> 线长 ,从外圆边缘起计算,可为负值</td>

+                        </tr>

+                        <tr>

+                            <td> {Object} lineStyle </td>

+                            <td> 各异 </td>

+                            <td> 线条样式,详见<a href="#LineStyle" title="">lineStyle</a></td>

+                        </tr>

+                    </table>

+                    <P> 通过有效设置itemStyle的normal和emphasis选项可实现个性化的显示策略,比如希望饼图文字标签默认隐藏,并在鼠标悬浮时通过一条红色的视觉引导线显示在饼图外部区域,可以如下设置:</P>

+                    <div class="code">

+                        <pre>itemStyle: {

+    normal: {

+        label: {

+            show: false

+        }

+        labelLine: {

+            show: false

+        }

+    } ,

+    emphasis: {

+        label: {

+            show: true,

+            position: &#39;outer&#39;

+        }

+        labelLine: {

+            show: true,

+            lineStyle: {

+                color: &#39;red&#39;

+            }

+        }

+    }

+}

+</pre>

+                    </div>

+                    <p>高度个性化:</p>

+                    <ul>

+                        <li>折线图 <a href="example/line.html" target="_blank">try this »</a></li>

+                        <li>柱状图 <a href="example/bar.html" target="_blank">try this »</a></li>

+                        <li>饼图 <a href="example/pie.html" target="_blank">try this »</a></li>

+                    </ul>

+

+                    <h4>lineStyle<a name="LineStyle"> </a></h4>

+                    <P> 线条(线段)样式</P>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {color} color</td>

+                            <td> 各异 </td>

+                            <td> 颜色 </td>

+                        </tr>

+                        <tr>

+                            <td> {string} type </td>

+                            <td> 'solid' </td>

+                            <td> 线条样式,可选为:'solid' | 'dotted' | 'dashed' </td>

+                        </tr>

+                        <tr>

+                            <td> {number} width </td>

+                            <td> 各异 </td>

+                            <td> 线宽 </td>

+                        </tr>

+                    </table>

+

+                    <h4>areaStyle<a name="AreaStyle"> </a></h4>

+                    <P> 区域填充样式</P>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {color} color</td>

+                            <td> 各异 </td>

+                            <td> 颜色 </td>

+                        </tr>

+                        <tr>

+                            <td> {string} type </td>

+                            <td> 'default' </td>

+                            <td> 填充样式,目前仅支持'default'(实填充) </td>

+                        </tr>

+                    </table>

+

+                    <h4>textStyle<a name="TextStyle"> </a></h4>

+                    <P> 文字样式</P>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {color} color</td>

+                            <td> 各异 </td>

+                            <td> 颜色 </td>

+                        </tr>

+                        <tr>

+                            <td> {string} decoration </td>

+                            <td> 'none' </td>

+                            <td> 修饰,仅对tooltip.textStyle生效 </td>

+                        </tr>

+                        <tr>

+                            <td> {string} align </td>

+                            <td> 各异 </td>

+                            <td> 水平对齐方式,可选为:'left' | 'right' | 'center' </td>

+                        </tr>

+                        <tr>

+                            <td> {string} baseline </td>

+                            <td> 各异 </td>

+                            <td> 垂直对齐方式,可选为:'top' | 'bottom' | 'middle' </td>

+                        </tr>

+                        <tr>

+                            <td> {string} fontFamily </td>

+                            <td> 'Arial, Verdana, sans-serif'</td>

+                            <td> 字体系列 </td>

+                        </tr>

+                        <tr>

+                            <td> {number} fontSize </td>

+                            <td> 12</td>

+                            <td> 字号 ,单位px</td>

+                        </tr>

+                        <tr>

+                            <td> {string} fontStyle </td>

+                            <td> 'normal'</td>

+                            <td> 样式,可选为:'normal' | 'italic' | 'oblique' </td>

+                        </tr>

+                        <tr>

+                            <td> {string | number} fontWeight </td>

+                            <td> 'normal'</td>

+                            <td> 粗细,可选为:'normal' | 'bold' | 'bolder' | 'lighter' | 100 | 200 |... | 900 </td>

+                        </tr>

+                    </table>

+

+                    <h4>loadingOption<a name="Loadingoption"> </a></h4>

+                    <P> 过渡显示,loading(读取中)的选项。<a href="example/loading.html" target="_blank">try this »</a></P>

+                    <table cellspacing="0" class="ADoc_table">

+                        <tr>

+                            <th> 名称 </th>

+                            <th> 默认值 </th>

+                            <th> 描述 </th>

+                        </tr>

+                        <tr>

+                            <td> {string} text </td>

+                            <td> 'Loading...' </td>

+                            <td> 显示话术 </td>

+                        </tr>

+                        <tr>

+                            <td> {string | number} x </td>

+                            <td> 'center' </td>

+                            <td> 水平安放位置,默认为全图居中,可选为:'center' | 'left' | 'right' | {number}(x坐标,单位px) </td>

+                        </tr>

+                        <tr>

+                            <td> {string | number} y </td>

+                            <td> 'center' </td>

+                            <td> 垂直安放位置,默认为全图居中,可选为:'center' | 'bottom' | 'top' | {number}(y坐标,单位px) </td>

+                        </tr>

+                        <tr>

+                            <td> {Object} textStyle </td>

+                            <td> null </td>

+                            <td> 显示话术的文本样式(详见<a href="#TextStyle" title="">textStyle</a>) </td>

+                        </tr>

+                        <tr>

+                            <td> {string} effect </td>

+                            <td> 'spin' </td>

+                            <td> loading效果,可选为:'spin' | 'bar' | 'ring' | 'whirling' | 'dynamicLine' | 'bubble'</td>

+                        </tr>

+                        <tr>

+                            <td> {object} effectOption </td>

+                            <td> null </td>

+                            <td> loading效果选项,详见zrender</td>

+                        </tr>

+                        <tr>

+                            <td> {number} progress </td>

+                            <td> null </td>

+                            <td> 指定当前进度[0~1],个别效果有效。</td>

+                        </tr>

+                    </table>

+

+                    <h4>color<a name="Color"> </a></h4>

+                    <P> {Array}<br/>

+                        ['#ff7f50','#87cefa','#da70d6','#32cd32','#6495ed','#ff69b4','#ba55d3','#cd5c5c','#ffa500','#40e0d0',<br/>

+                        '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700','#6b8e23','#ff00ff','#3cb371','#b8860b','#30e0e0']

+                        <br/>,默认颜色序列</P>

+

+                    <h4>calculable<a name="Calculable"> </a></h4>

+                    <P> {boolean} false,是否启用拖拽重计算特性,默认关闭</P>

+

+                    <h4>calculableColor<a name="CalculableColor"> </a></h4>

+                    <P> {color} 'rgba(255,165,0,0.6)',拖拽重计算提示边框颜色</P>

+

+                    <h4>calculableHolderColor<a name="CalculableHolderColor"> </a></h4>

+                    <P> {color} '#ccc',可计算占位提示颜色</P>

+

+                    <h4>nameConnector<a name="NameConnector"> </a></h4>

+                    <P> {string} ' &amp; ',数据合并名字间连接符</P>

+

+                    <h4>valueConnector<a name="ValueConnector"> </a></h4>

+                    <P> {string} ' : ',数据合并名字与数值间连接符</P>

+

+                    <h4>animation<a name="Animation"> </a></h4>

+                    <P> {boolean} true,是否启用图表初始化动画,默认开启,建议IE8-关闭</P>

+

+                    <h4>animationDuration<a name="AnimationDuration"> </a></h4>

+                    <P> {number} 2000,动画时长,单位ms,支持多级控制</P>

+

+                    <h4>animationEasing<a name="AnimationEasing"> </a></h4>

+                    <P> {string} 'BounceOut',主元素的缓动效果,支持多级控制,详见<a href="http://ecomfe.github.io/zrender/doc/doc.html#animation.easing" target="_blank">zrender.animation.easing</a>,可选有:<br/>

+                        'Linear',<br/>

+                        'QuadraticIn', 'QuadraticOut', 'QuadraticInOut',<br/>

+                        'CubicIn', 'CubicOut', 'CubicInOut',<br/>

+                        'QuarticIn', 'QuarticOut', 'QuarticInOut',<br/>

+                        'QuinticIn', 'QuinticOut', 'QuinticInOut',<br/>

+                        'SinusoidalIn', 'SinusoidalOut', 'SinusoidalInOut',<br/>

+                        'ExponentialIn', 'ExponentialOut', 'ExponentialInOut',<br/>

+                        'CircularIn', 'CircularOut', 'CircularInOut',<br/>

+                        'ElasticIn', 'ElasticOut', 'ElasticInOut',<br/>

+                        'BackIn', 'BackOut', 'BackInOut',<br/>

+                        'BounceIn', 'BounceOut', 'BounceInOut'<br/>

+                    </P>

+

+                    <h4>多级控制设计<a name="多级控制设计"> </a></h4>

+                    <P> 简单的说,你可以通过这三级满足不同level的定制和个性化需求:</P>

+                    <ul>

+                        <li>通过 option.* 设置全局统一配置;</li>

+                        <li>通过 option.series.* 设置特定系列特殊配置,其优先级高于 option 内的同名配置;</li>

+                        <li>通过 option.series.data.* 设置特定数据项的特殊配置,最高优先级;</li>

+                    </ul>

+                    <p><img src="./asset/img/doc/multiControl.jpg" title="" alt="多级控制"/></P>

+

+                    <h3>附录:一个直观的事例<a name="附录一个直观的事例"> </a></h3>

+                    <p>查看更多实例 <a href="example.html" target="_blank">example</a></p>

+                    <div class="code">

+                        <pre>// 图表实例化------------------

+var echarts = require('echarts/echarts');

+var myChart = echarts.init(document.getElementById('main'));

+

+// ajax getting data...............

+

+// 过渡---------------------

+myChart.showLoading({

+    text: &#39;正在努力的读取数据中...&#39;,    //loading话术

+});

+

+// ajax return

+myChart.hideLoading();

+

+// 图表使用-------------------

+var option = {

+    legend: {                                   // 图例配置

+        padding: 5,                             // 图例内边距,单位px,默认上下左右内边距为5

+        itemGap: 10,                            // Legend各个item之间的间隔,横向布局时为水平间隔,纵向布局时为纵向间隔

+        data: ['ios', 'android']

+    },

+    tooltip: {                                  // 气泡提示配置

+        trigger: 'item',                        // 触发类型,默认数据触发,可选为:'axis'

+    },

+    xAxis: [                                    // 直角坐标系中横轴数组

+        {

+            type: 'category',                   // 坐标轴类型,横轴默认为类目轴,数值轴则参考yAxis说明

+            data: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

+        }

+    ],

+    yAxis: [                                    // 直角坐标系中纵轴数组

+        {

+            type: 'value',                      // 坐标轴类型,纵轴默认为数值轴,类目轴则参考xAxis说明

+            boundaryGap: [0.1, 0.1],            // 坐标轴两端空白策略,数组内数值代表百分比

+            splitNumber: 4                      // 数值轴用,分割段数,默认为5

+        }

+    ],

+    series: [

+        {

+            name: 'ios',                        // 系列名称

+            type: 'line',                       // 图表类型,折线图line、散点图scatter、柱状图bar、饼图pie、雷达图radar

+            data: [112, 23, 45, 56, 233, 343, 454, 89, 343, 123, 45, 123]

+        },

+        {

+            name: 'android',                    // 系列名称

+            type: 'line',                       // 图表类型,折线图line、散点图scatter、柱状图bar、饼图pie、雷达图radar

+            data: [45, 123, 145, 526, 233, 343, 44, 829, 33, 123, 45, 13]

+        }

+    ]

+};

+myChart.setOption(option);

+

+...

+

+// 增加些数据------------------

+option.legend.data.push('win&#39);

+option.series.push({

+        name: 'win',                            // 系列名称

+        type: 'line',                           // 图表类型,折线图line、散点图scatter、柱状图bar、饼图pie、雷达图radar

+        data: [112, 23, 45, 56, 233, 343, 454, 89, 343, 123, 45, 123]

+});

+myChart.setOption(option);

+

+...

+

+// 图表清空-------------------

+myChart.clear();

+

+// 图表释放-------------------

+myChart.dispose();

+</pre>

+</div>                        </div>

+                    </div>

+        </div>

+        <hr>

+        <!-- FOOTER -->

+        <footer>

+          <p class="pull-right"><a href="#">Back to top</a></p>

+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>

+        </footer>

+    </div><!--/.fluid-container-->

+

+    <script src="asset/js/jquery.js"></script>

+    <script src="asset/js/bootstrap-transition.js"></script>

+    <script src="asset/js/bootstrap-alert.js"></script>

+    <script src="asset/js/bootstrap-modal.js"></script>

+    <script src="asset/js/bootstrap-dropdown.js"></script>

+    <script src="asset/js/bootstrap-scrollspy.js"></script>

+    <script src="asset/js/bootstrap-tab.js"></script>

+    <script src="asset/js/bootstrap-tooltip.js"></script>

+    <script src="asset/js/bootstrap-popover.js"></script>

+    <script src="asset/js/bootstrap-button.js"></script>

+    <script src="asset/js/bootstrap-collapse.js"></script>

+    <script src="asset/js/bootstrap-carousel.js"></script>

+    <script src="asset/js/bootstrap-typeahead.js"></script>

+    <script src="asset/js/echartsConfig.js"></script>

+    <script src="asset/js/echartsDoc.js"></script>

+</body>

+</html>
\ No newline at end of file
diff --git a/doc/example.html b/doc/example.html
new file mode 100644
index 0000000..a29d095
--- /dev/null
+++ b/doc/example.html
@@ -0,0 +1,260 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="asset/js/esl/esl.js"></script>
+
+    <!-- Le styles -->
+    <link href="asset/css/bootstrap.css" rel="stylesheet">
+    <link href="asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="asset/css/echartsHome.css" rel="stylesheet">
+
+    <!-- Fav and touch icons -->
+    <link rel="shortcut icon" href="asset/ico/favicon.png">
+  </head>
+
+  <body>
+
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="example.html" class="active">Example</a></li>
+                <li><a href="doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container">
+        <h1>折线图</h1>
+        <div class="row-fluid">
+            <div class="span12">
+                <div class="span4">
+                  <a href="example/line1.html"><img src="asset/img/example/line1.png" ></a>
+                  <p>标准折线图。</p>
+                  <p><a class="btn" href="example/line1.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/line2.html"><img src="asset/img/example/line2.png"></a>
+                  <p>堆积折线图,支持任意系列堆积。</p>
+                  <p><a class="btn" href="example/line2.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/line5.html"><img src="asset/img/example/line5.png"></a>
+                  <p>标准折线图,横纵坐标轴互换。</p>
+                  <p><a class="btn" href="example/line5.html">View details &raquo;</a></p>
+                </div><!--/span-->
+            </div>
+        </div>
+        <div class="row-fluid">
+            <div class="span12">
+                <div class="span4">
+                  <a href="example/line3.html"><img src="asset/img/example/line3.png"></a>
+                  <p>标准面积图。</p>
+                  <p><a class="btn" href="example/line3.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/line4.html"><img src="asset/img/example/line4.png"></a>
+                  <p>堆积面积图,支持任意系列堆积。</p>
+                  <p><a class="btn" href="example/line4.html">View details &raquo;</a></p>
+                </div><!--/span-->
+
+            </div>
+        </div>
+        <hr>
+        <h1>柱状图</h1>
+        <div class="row-fluid">
+            <div class="span12">
+                <div class="span4">
+                  <a href="example/bar1.html"><img src="asset/img/example/bar1.png"></a>
+                  <p>标准柱状图。</p>
+                  <p><a class="btn" href="example/bar1.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                   <a href="example/bar2.html"><img src="asset/img/example/bar2.png"></a>
+                  <p>堆积柱状图,支持任意系列堆积。</p>
+                  <p><a class="btn" href="example/bar2.html">View details &raquo;</a></p>
+                </div><!--/span-->
+            </div>
+        </div>
+        <div class="row-fluid">
+            <div class="span12">
+                <div class="span4">
+                  <a href="example/bar3.html"><img src="asset/img/example/bar3.png"></a>
+                  <p>标准条状图。</p>
+                  <p><a class="btn" href="example/bar3.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/bar4.html"><img src="asset/img/example/bar4.png"></a>
+                  <p>堆积条状图,支持任意系列堆积。</p>
+                  <p><a class="btn" href="example/bar4.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/bar5.html"><img src="asset/img/example/bar5.png"></a>
+                  <p>标准条状图,正负值混合。</p>
+                  <p><a class="btn" href="example/bar5.html">View details &raquo;</a></p>
+                </div><!--/span-->
+            </div>
+        </div>
+        <hr>
+        <h1>饼图</h1>
+        <div class="row-fluid">
+            <div class="span12">
+                <div class="span4">
+                  <a href="example/pie1.html"><img src="asset/img/example/pie1.png"></a>
+                  <p>标准饼图。</p>
+                  <p><a class="btn" href="example/pie1.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/pie2.html"><img src="asset/img/example/pie2.png"></a>
+                  <p>标准环形图。</p>
+                  <p><a class="btn" href="example/pie2.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/pie3.html"><img src="asset/img/example/pie3.png"></a>
+                  <p>嵌套饼图。</p>
+                  <p><a class="btn" href="example/pie3.html">View details &raquo;</a></p>
+                </div><!--/span-->
+            </div>
+        </div>
+        <hr>
+        <h1>混合</h1>
+        <div class="row-fluid">
+            <div class="span12">
+                <div class="span4">
+                  <a href="example/mix1.html"><img src="asset/img/example/mix1.png"></a>
+                  <p>折线图与柱状图混合,双数值轴。</p>
+                  <p><a class="btn" href="example/mix1.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/mix2.html"><img src="asset/img/example/mix2.png"></a>
+                  <p>柱状图与饼图混合。</p>
+                  <p><a class="btn" href="example/mix2.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/lasagna.html"><img src="asset/img/example/lasagna.png"></a>
+                  <p>多层嵌套环形图。</p>
+                  <p><a class="btn" href="example/lasagna.html">View details &raquo;</a></p>
+                </div><!--/span-->
+            </div>
+        </div>
+        <hr>
+        <h1>其他</h1>
+        <div class="row-fluid">
+            <div class="span12">
+                <div class="span4">
+                  <a href="example/dataZoom1.html"><img src="asset/img/example/datazoom1.png"></a>
+                  <p>数据区域缩放</p>
+                  <p><a class="btn" href="example/dataZoom1.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/loading.html"><img src="asset/img/example/loading.png"></a>
+                  <p>加载中(Loading)</p>
+                  <p><a class="btn" href="example/loading.html">View details &raquo;</a></p>
+                </div><!--/span-->
+            </div>
+        </div>
+        <hr>
+        <h1>个性化</h1>
+        <div class="row-fluid">
+            <div class="span12">
+                <div class="span4">
+                  <a href="example/line.html"><img src="asset/img/example/line.png"></a>
+                  <p>折线图:个性化填充、线条、拐点样式等~</p>
+                  <p><a class="btn" href="example/line.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/bar.html"><img src="asset/img/example/bar.png"></a>
+                  <p>柱状图:个性化柱形宽度,填充、高亮样式等~</p>
+                  <p><a class="btn" href="example/bar.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/pie.html"><img src="asset/img/example/pie.png"></a>
+                  <p>饼图:个性化填充、标签文本、视觉引导线样式等~</p>
+                  <p><a class="btn" href="example/pie.html">View details &raquo;</a></p>
+                </div><!--/span-->
+            </div>
+        </div>
+        <div class="row-fluid">
+            <div class="span12">
+                <div class="span4">
+                  <a href="example/axis.html"><img src="asset/img/example/axis.png"></a>
+                  <p>坐标系:个性化标签文字、间隔线、间隔区域样式等~</p>
+                  <p><a class="btn" href="example/axis.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/dataZoom.html"><img src="asset/img/example/datazoom.png"></a>
+                  <p>数据区域缩放:个性化数据阴影、背景、拖拽手柄样式等~</p>
+                  <p><a class="btn" href="example/dataZoom.html">View details &raquo;</a></p>
+                </div><!--/span-->
+                <div class="span4">
+                  <a href="example/tooltip.html"><img src="asset/img/example/tooltip.png"></a>
+                  <p>提示框:个性化文字样式、边框、背景、格式器等~</p>
+                  <p><a class="btn" href="example/tooltip.html">View details &raquo;</a></p>
+                </div><!--/span-->
+            </div>
+        </div>
+
+      <hr>
+      <footer>
+        <p class="pull-right"><a href="#">Back to top</a></p>
+        <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+      </footer>
+
+    </div> <!-- /container -->
+
+    <!-- Le javascript
+    ================================================== -->
+    <!-- Placed at the end of the document so the pages load faster -->
+    <script src="asset/js/jquery.js"></script>
+    <script src="asset/js/bootstrap-transition.js"></script>
+    <script src="asset/js/bootstrap-alert.js"></script>
+    <script src="asset/js/bootstrap-modal.js"></script>
+    <script src="asset/js/bootstrap-dropdown.js"></script>
+    <script src="asset/js/bootstrap-scrollspy.js"></script>
+    <script src="asset/js/bootstrap-tab.js"></script>
+    <script src="asset/js/bootstrap-tooltip.js"></script>
+    <script src="asset/js/bootstrap-popover.js"></script>
+    <script src="asset/js/bootstrap-button.js"></script>
+    <script src="asset/js/bootstrap-collapse.js"></script>
+    <script src="asset/js/bootstrap-carousel.js"></script>
+    <script src="asset/js/bootstrap-typeahead.js"></script>
+
+  </body>
+</html>
diff --git a/doc/example/axis.html b/doc/example/axis.html
new file mode 100644
index 0000000..733692e
--- /dev/null
+++ b/doc/example/axis.html
@@ -0,0 +1,288 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['蒸发量','降水量','最低气温','最高气温']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : true,
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    xAxis : [
+        {
+            type : 'category',
+            position: 'bottom',
+            boundaryGap: true,
+            axisLine : {    // 轴线
+                show: true,
+                lineStyle: {
+                    color: 'green',
+                    type: 'solid',
+                    width: 2
+                }
+            },
+            axisTick : {    // 轴标记
+                show:true,
+                length: 10,
+                lineStyle: {
+                    color: 'red',
+                    type: 'solid',
+                    width: 2
+                }
+            },
+            axisLabel : {
+                show:true,
+                interval: 'auto',    // {number}
+                rotate: 45,
+                margin: 8,
+                formatter: '{value}月',
+                textStyle: {
+                    color: 'blue',
+                    decoration: 'none',
+                    fontFamily: 'sans-serif',
+                    fontSize: 15,
+                    fontStyle: 'italic',
+                    fontWeight: 'bold'
+                }
+            },
+            splitLine : {
+                show:true,
+                lineStyle: {
+                    color: '#483d8b',
+                    type: 'dashed',
+                    width: 1
+                }
+            },
+            splitArea : {
+                show: true,
+                areaStyle:{
+                    color:['rgba(144,238,144,0.3)','rgba(135,200,250,0.3)']
+                }
+            },
+            data : [
+                '1','2','3','4','5',
+                {
+                    value:'6',
+                    textStyle: {
+                        color: 'red',
+                        fontSize: 30,
+                        fontStyle: 'normal',
+                        fontWeight: 'bold'
+                    }
+                },
+                '7','8','9','10','11','12'
+            ]
+        },
+        {
+            type : 'category',
+            data : ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            position: 'left',
+            //min: 0,
+            //max: 300,
+            //precision: 1,
+            //power: 10,
+            splitNumber: 5,
+            boundaryGap: [0,0.1],
+            axisLine : {    // 轴线
+                show: true,
+                lineStyle: {
+                    color: 'red',
+                    type: 'dashed',
+                    width: 2
+                }
+            },
+            axisTick : {    // 轴标记
+                show:true,
+                length: 10,
+                lineStyle: {
+                    color: 'green',
+                    type: 'solid',
+                    width: 2
+                }
+            },
+            axisLabel : {
+                show:true,
+                interval: 'auto',    // {number}
+                rotate: -45,
+                margin: 18,
+                formatter: '{value} ml',    // Template formatter!
+                textStyle: {
+                    color: '#1e90ff',
+                    decoration: 'none',
+                    fontFamily: 'verdana',
+                    fontSize: 10,
+                    fontStyle: 'normal',
+                    fontWeight: 'bold'
+                }
+            },
+            splitLine : {
+                show:true,
+                lineStyle: {
+                    color: '#483d8b',
+                    type: 'dotted',
+                    width: 2
+                }
+            },
+            splitArea : {
+                show: true,
+                areaStyle:{
+                    color:['rgba(205,92,92,0.3)','rgba(255,215,0,0.3)']
+                }
+            }
+        },
+        {
+            type : 'value',
+            precision: 1,
+            splitNumber: 10,
+            axisLabel : {
+                formatter: function(value) {
+                    // Function formatter
+                    return value + ' °C'
+                }
+            },
+            splitLine : {
+                show: false
+            }
+        }
+    ],
+    series : [
+        {
+            name: '蒸发量',
+            type: 'bar',
+            data:[2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
+        },
+        {
+            name: '降水量',
+            type: 'bar',
+            data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
+        },
+        {
+            name:'最低气温',
+            type: 'line',
+            yAxisIndex: 1,
+            data: [2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2]
+        },
+        {
+            name:'最高气温',
+            type: 'line',
+            xAxisIndex: 1,
+            yAxisIndex: 1,
+            data: [12.0, 12.2, 13.3, 14.5, 16.3, 18.2, 28.3, 33.4, 31.0, 24.5, 18.0, 16.2]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/bar.html b/doc/example/bar.html
new file mode 100644
index 0000000..d5cdbb7
--- /dev/null
+++ b/doc/example/bar.html
@@ -0,0 +1,214 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        show: true,
+        trigger: 'item'
+    },
+    legend: {
+        data:['邮件营销','联盟广告','直接访问','搜索引擎']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : [
+        {
+            type : 'category',
+            data : ['周一','周二','周三','周四','周五','周六','周日']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            splitArea : {show : true}
+        }
+    ],
+    series : [
+        {
+            name:'邮件营销',
+            type:'bar',
+            itemStyle: {        // 系列级个性化样式,纵向渐变填充
+                normal: {
+                    color : (function(){
+                        var zrColor = require('zrender/tool/color');
+                        return zrColor.getLinearGradient(
+                            0, 400, 0, 300,
+                            [[0, 'green'],[1, 'yellow']]
+                        )
+                    })()
+                },
+                emphasis: {
+                    color: (function(){
+                        var zrColor = require('zrender/tool/color');
+                        return zrColor.getLinearGradient(
+                            0, 400, 0, 300,
+                            [[0, 'red'],[1, 'orange']]
+                        )
+                    })()
+                }
+            },
+            data:[220, 232, 101, 234, 190, 330, 210]
+        },
+        {
+            name:'联盟广告',
+            type:'bar',
+            stack: '总量',
+            data:[120, '-', 451, 134, 190, 230, 110]
+        },
+        {
+            name:'直接访问',
+            type:'bar',
+            stack: '总量',
+            itemStyle: {                // 系列级个性化
+                normal: {
+                    color: 'red'
+                },
+                emphasis: {
+                    color: 'blue'
+                }
+            },
+            data:[
+                320, 332, '-', 334,
+                {
+                    value: 390,
+                    brokenPointSize : 10,   // 数据级个性化
+                    itemStyle: {
+                        normal: {
+                            color :'lime'
+                        },
+                        emphasis: {
+                            color: 'skyBlue'
+                        }
+                    }
+                },
+                330, 320
+            ]
+        },
+        {
+            name:'搜索引擎',
+            type:'bar',
+            barWidth: 40,                   // 系列级个性化,柱形宽度
+            itemStyle: {
+                normal: {                   // 系列级个性化,横向渐变填充
+                    color : (function(){
+                        var zrColor = require('zrender/tool/color');
+                        return zrColor.getLinearGradient(
+                            0, 0, 1000, 0,
+                            [[0, 'rgba(30,144,255,0.8)'],[1, 'rgba(138,43,226,0.8)']]
+                        )
+                    })()
+                }
+            },
+            data:[620, 732, 701, 734, 890, 930, 820]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/bar1.html b/doc/example/bar1.html
new file mode 100644
index 0000000..a32a28a
--- /dev/null
+++ b/doc/example/bar1.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['蒸发量','降水量']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : [
+        {
+            type : 'category',
+            data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            splitArea : {show : true}
+        }
+    ],
+    series : [
+        {
+            name:'蒸发量',
+            type:'bar',
+            data:[2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
+        },
+        {
+            name:'降水量',
+            type:'bar',
+            data:[2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/bar2.html b/doc/example/bar2.html
new file mode 100644
index 0000000..455d9d2
--- /dev/null
+++ b/doc/example/bar2.html
@@ -0,0 +1,192 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎','百度','谷歌','必应','其他']
+    },
+    toolbox: {
+        show : true,
+        orient: 'vertical',
+        x: 'right',
+        y: 'center',
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : [
+        {
+            type : 'category',
+            data : ['周一','周二','周三','周四','周五','周六','周日']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            splitArea : {show : true}
+        }
+    ],
+    series : [
+        {
+            name:'直接访问',
+            type:'bar',
+            data:[320, 332, 301, 334, 390, 330, 320]
+        },
+        {
+            name:'邮件营销',
+            type:'bar',
+            stack: '广告',
+            data:[120, 132, 101, 134, 90, 230, 210]
+        },
+        {
+            name:'联盟广告',
+            type:'bar',
+            stack: '广告',
+            data:[220, 182, 191, 234, 290, 330, 310]
+        },
+        {
+            name:'视频广告',
+            type:'bar',
+            stack: '广告',
+            data:[150, 232, 201, 154, 190, 330, 410]
+        },
+        {
+            name:'搜索引擎',
+            type:'bar',
+            data:[862, 1018, 964, 1026, 1679, 1600, 1570]
+        },
+        {
+            name:'百度',
+            type:'bar',
+            barWidth : 5,
+            stack: '搜索引擎',
+            data:[620, 732, 701, 734, 1090, 1130, 1120]
+        },
+        {
+            name:'谷歌',
+            type:'bar',
+            stack: '搜索引擎',
+            data:[120, 132, 101, 134, 290, 230, 220]
+        },
+        {
+            name:'必应',
+            type:'bar',
+            stack: '搜索引擎',
+            data:[60, 72, 71, 74, 190, 130, 110]
+        },
+        {
+            name:'其他',
+            type:'bar',
+            stack: '搜索引擎',
+            data:[62, 82, 91, 84, 109, 110, 120]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/bar3.html b/doc/example/bar3.html
new file mode 100644
index 0000000..2d968ca
--- /dev/null
+++ b/doc/example/bar3.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['2011年', '2012年']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : [
+        {
+            type : 'value',
+            boundaryGap : [0, 0.01]
+        }
+    ],
+    yAxis : [
+        {
+            type : 'category',
+            data : ['巴西','印尼','美国','印度','中国','世界人口(万)']
+        }
+    ],
+    series : [
+        {
+            name:'2011年',
+            type:'bar',
+            data:[18203, 23489, 29034, 104970, 131744, 630230]
+        },
+        {
+            name:'2012年',
+            type:'bar',
+            data:[19325, 23438, 31000, 121594, 134141, 681807]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/bar4.html b/doc/example/bar4.html
new file mode 100644
index 0000000..6a47558
--- /dev/null
+++ b/doc/example/bar4.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['直接访问', '邮件营销','联盟广告','视频广告','搜索引擎']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : [
+        {
+            type : 'value'
+        }
+    ],
+    yAxis : [
+        {
+            type : 'category',
+            data : ['周一','周二','周三','周四','周五','周六','周日']
+        }
+    ],
+    series : [
+        {
+            name:'直接访问',
+            type:'bar',
+            stack: '总量',
+            data:[320, 302, 301, 334, 390, 330, 320]
+        },
+        {
+            name:'邮件营销',
+            type:'bar',
+            stack: '总量',
+            data:[120, 132, 101, 134, 90, 230, 210]
+        },
+        {
+            name:'联盟广告',
+            type:'bar',
+            stack: '总量',
+            data:[220, 182, 191, 234, 290, 330, 310]
+        },
+        {
+            name:'视频广告',
+            type:'bar',
+            stack: '总量',
+            data:[150, 212, 201, 154, 190, 330, 410]
+        },
+        {
+            name:'搜索引擎',
+            type:'bar',
+            stack: '总量',
+            data:[820, 832, 901, 934, 1290, 1330, 1320]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/bar5.html b/doc/example/bar5.html
new file mode 100644
index 0000000..c8a7441
--- /dev/null
+++ b/doc/example/bar5.html
@@ -0,0 +1,159 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['利润', '支出', '收入']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : [
+        {
+            type : 'value'
+        }
+    ],
+    yAxis : [
+        {
+            type : 'category',
+            data : ['周一','周二','周三','周四','周五','周六','周日']
+        }
+    ],
+    series : [
+        {
+            name:'利润',
+            type:'bar',
+            data:[200, 170, 240, 244, 200, 220, 210]
+        },
+        {
+            name:'收入',
+            type:'bar',
+            stack: '总量',
+            barWidth : 5,
+            itemStyle: {normal: {
+                color: 'rgba(138, 43, 226, 0.3)'
+            }},
+            data:[320, 302, 341, 374, 390, 450, 420]
+        },
+        {
+            name:'支出',
+            type:'bar',
+            stack: '总量',
+            itemStyle: {normal: {
+                color: 'rgba(30, 144, 255, 0.3)'
+            }},
+            data:[-120, -132, -101, -134, -190, -230, -210]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/dataZoom.html b/doc/example/dataZoom.html
new file mode 100644
index 0000000..8dac35f
--- /dev/null
+++ b/doc/example/dataZoom.html
@@ -0,0 +1,170 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : true,
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    dataZoom : {
+        show : true,
+        realtime : true,
+        //orient: 'vertical',   // 'horizontal'
+        //x: 0,
+        y: 36,
+        //width: 400,
+        height: 20,
+        backgroundColor: 'rgba(221,160,221,0.5)',
+        dataBackgroundColor: 'rgba(138,43,226,0.5)',
+        fillerColor: 'rgba(38,143,26,0.6)',
+        handleColor: 'rgba(128,43,16,0.8)',
+        //xAxisIndex:[],
+        //yAxisIndex:[],
+        start : 40,
+        end : 60
+    },
+    xAxis : [
+        {
+            type : 'category',
+            boundaryGap : false,
+            data : function(){
+                var list = [];
+                var n = 0;
+                while (n++ < 150) {
+                    list.push(n);
+                }
+                return list;
+            }()
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            splitArea : {show : true}
+        }
+    ],
+    series : [
+        {
+            name:'dz',
+            type:'line',
+            data:function(){
+                var list = [];
+                for (var i = 1; i <= 150; i++) {
+                    list.push(Math.round(Math.random()* 30));
+                }
+                return list;
+            }()
+        }
+    ],
+    calculable:false
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/dataZoom1.html b/doc/example/dataZoom1.html
new file mode 100644
index 0000000..ccb00c8
--- /dev/null
+++ b/doc/example/dataZoom1.html
@@ -0,0 +1,171 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['最高','最低']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : true,
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    dataZoom : {
+        show : true,
+        realtime : true,
+        start : 40,
+        end : 60
+    },
+    xAxis : [
+        {
+            type : 'category',
+            boundaryGap : false,
+            data : function(){
+                var list = [];
+                for (var i = 1; i <= 30; i++) {
+                    list.push('2013-03-' + i);
+                }
+                return list;
+            }()
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            splitArea : {show : true}
+        }
+    ],
+    series : [
+        {
+            name:'最高',
+            type:'line',
+            data:function(){
+                var list = [];
+                for (var i = 1; i <= 30; i++) {
+                    list.push(Math.round(Math.random()* 30));
+                }
+                return list;
+            }()
+        },
+        {
+            name:'最低',
+            type:'line',
+            data:function(){
+                var list = [];
+                for (var i = 1; i <= 30; i++) {
+                    list.push(Math.round(Math.random()* 10));
+                }
+                return list;
+            }()
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/demo.html b/doc/example/demo.html
new file mode 100644
index 0000000..c4e4d38
--- /dev/null
+++ b/doc/example/demo.html
@@ -0,0 +1,222 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    // color : []
+    tooltip : {
+        // show : true,        // default : true
+        trigger: 'axis',
+        borderWidth : 1,
+        borderColor : 'yellow',
+        padding : [8,12],
+        textStyle : {
+            color : '#eee',
+            fontSize : '16',
+            fontWeight:'blod',
+            fontFamily:'微软雅黑'
+        },
+        formatter: "Template : <br/>{b}<br/>{a}:{c}<br/>{a1}:{c1}<br/>{a2}:{c2}",
+        formatter: function(params) {
+            var res = 'Function : <br/>' + params[0][1];
+            for (var i = 0, l = params.length; i < l; i++) {
+                res += '<br/>' + params[i][0] + ' : ' + params[i][2];
+            }
+            return res;
+        }
+    },
+    legend: {
+        // orient : 'vertical',
+        // x : 'right',
+        borderWidth:0,
+        padding:[5,5],
+        //data:['Kener','Amy','apple','orange','peach','banana'],
+        data:['serie1','serie2','serie3','serie4']
+    },
+    grid : {
+        //x : 50,
+        //y : 30,
+        //width : 600,
+        //height : 320
+    },
+    xAxis : [
+        {
+            type : 'category',
+            position:'bottom',
+            // axisTick : {show:true, lineStyle:{color:'red'}},
+            // splitLine : {show:false},
+            // splitArea : {show:false, areaStyle:{color:['rgba(250,250,250,0.3)','rgba(200,200,200,0.3)']}},
+            data : ['2012-02-01','2012-02-02','2012-02-03','2012-02-04','2012-02-05']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            position:'left'
+        }
+    ],
+    series : [
+        {
+            name:'serie1',
+            type:'line',
+            itemStyle: {normal: {areaStyle: {color: 'rgba(144, 238, 144, 0.3)'}}},
+            data:[1,2,8,{value:20,tooltip : {trigger: 'item'}}]
+        },
+        {
+            name:'serie2',
+            stack: 'stack1',
+            type:'line',
+            itemStyle: {normal: {areaStyle: {color: 'rgba(98, 130, 10, 0.3)'}}},
+            data:[12,20,'-', 15, 9]
+        },
+        {
+            name:'serie3',
+            stack: 'stack1',
+            type:'line',
+            itemStyle: {normal: {areaStyle: {color: 'rgba(170, 130, 180, 0.3)'}}},
+            data:[13,3,33,9,7]
+        },
+        {
+            name:'serie4',
+            type:'line',
+            itemStyle: {normal: {areaStyle: {color: 'rgba(70, 30, 180, 0.3)'}}},
+            data:[4,14,3,6,4]
+        },
+        /*
+        {
+            name:'fruit',
+            type:'pie',
+            radius : [80, 120],
+            center: [400,200],
+            data:[
+                {value:10, name:'apple'},
+                {value:34, name:'orange'},
+                {value:35, name:'peach'},
+                {value:48, name:'banana'}
+            ]
+        },
+        {
+            name:'people',
+            type:'pie',
+            radius : [20, 60],
+            center: [400,200],
+            itemStyle : {
+                normal : {
+                    label : {
+                        position:'inner'
+                    },
+                    labelLine : {
+                        show : false
+                    }
+                }
+            },
+            data:[
+                {value:12, name:'Kener'},
+                {value:24, name:'Amy'},
+                {value:35, name:'Lily'},
+                {value:48, name:'Eric'}
+            ]
+        }
+        */
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/event.html b/doc/example/event.html
new file mode 100644
index 0000000..5a0079b
--- /dev/null
+++ b/doc/example/event.html
@@ -0,0 +1,191 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['最高','最低']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly:false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    dataZoom : {
+        show : true,
+        realtime : true,
+        start : 40,
+        end : 60
+    },
+    xAxis : [
+        {
+            type : 'category',
+            boundaryGap : true,
+            data : function(){
+                var list = [];
+                for (var i = 1; i <= 30; i++) {
+                    list.push('2013-03-' + i);
+                }
+                return list;
+            }()
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            splitArea : {show : true}
+        }
+    ],
+    series : [
+        {
+            name:'最高',
+            type:'line',
+            data:function(){
+                var list = [];
+                for (var i = 1; i <= 30; i++) {
+                    list.push(Math.round(Math.random()* 30) + 30);
+                }
+                return list;
+            }()
+        },
+        {
+            name:'最低',
+            type:'bar',
+            data:function(){
+                var list = [];
+                for (var i = 1; i <= 30; i++) {
+                    list.push(Math.round(Math.random()* 10));
+                }
+                return list;
+            }()
+        }
+    ]
+};
+var ecConfig = require('echarts/config');
+function eConsole(param) {
+    var mes = '【' + param.type + '】';
+    if (typeof param.seriesIndex != 'undefined') {
+        mes += '  seriesIndex : ' + param.seriesIndex;
+        mes += '  dataIndex : ' + param.dataIndex;
+    }
+    if (param.type == 'hover') {
+        document.getElementById('hover-console').innerHTML = 'Event Console : ' + mes;
+    }
+    else {
+        document.getElementById('console').innerHTML = mes;
+    }
+    console.log(param);
+}
+for (var e in ecConfig.EVENT) {
+    myChart.on(ecConfig.EVENT[e], eConsole);
+}
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                    <span id='hover-console' style="color:#1e90ff"></span>
+                    <span id='console' style="color:#1e90ff">Event Console</span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/lasagna.html b/doc/example/lasagna.html
new file mode 100644
index 0000000..5a67aba
--- /dev/null
+++ b/doc/example/lasagna.html
@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'item',
+        formatter: "{a} <br/>{b} : {c} ({d}%)"
+    },
+    legend: {
+        orient : 'vertical',
+        x : 'left',
+        data:['Chrome','Firefox','Safari','IE9+','IE8-']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            refresh : true
+        }
+    },
+    calculable : false,
+    series : (function(){
+        var series = [];
+        for (var i = 0; i < 30; i++) {
+            series.push({
+                name:'浏览器(数据纯属虚构)',
+                type:'pie',
+                itemStyle : {normal : {
+                    label : {show : i > 28},
+                    labelLine : {show : i > 28, length:20}
+                }},
+                radius : [i * 4 + 40, i * 4 + 43],
+                data:[
+                    {value: i * 128 + 80,  name:'Chrome'},
+                    {value: i * 64  + 160,  name:'Firefox'},
+                    {value: i * 32  + 320,  name:'Safari'},
+                    {value: i * 16  + 640,  name:'IE9+'},
+                    {value: i * 8  + 1280, name:'IE8-'}
+                ]
+            })
+        }
+        return series;
+    })()
+};
+setTimeout(function(){
+    var _ZR = myChart.getZrender();
+    // 补充千层饼
+    _ZR.addShape({
+        shape : 'text',
+        style : {
+            x : _ZR.getWidth() / 2,
+            y : _ZR.getHeight() / 2,
+            color: '#bbb',
+            text : '恶梦的过去',
+            textAlign : 'center'
+        }
+    });
+    _ZR.addShape({
+        shape : 'text',
+        style : {
+            x : _ZR.getWidth() / 2 + 200,
+            y : _ZR.getHeight() / 2,
+            brushType:'both',
+            color: 'orange',
+            strokeColor: 'yellow',
+            text : '美好的未来',
+            textAlign : 'left',
+            textFont:'normal 20px 微软雅黑'
+        }
+    });
+    _ZR.refresh();
+}, 2000);
+
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/legend.html b/doc/example/legend.html
new file mode 100644
index 0000000..9809d36
--- /dev/null
+++ b/doc/example/legend.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    legend: {
+        orient: 'horizontal', // 'vertical'
+        x: 'right', // 'center' | 'left' | {number},
+        y: 'bottom', // 'center' | 'top' | {number}
+        backgroundColor: '#eee',
+        borderColor: 'rgba(178,34,34,0.8)',
+        borderWidth: 4,
+        padding: 10,    // [5, 10, 15, 20]
+        itemGap: 20,
+        textStyle: {color: 'red'},
+        data: ['蒸发量','降水量','最高气温','最低气温','组成','索引不到的']
+    },
+    xAxis :{ data : [] },
+    series : [
+        {
+            name:'蒸发量',
+            type:'bar',
+            data:[]
+        },
+        {
+            name:'最高气温',
+            type:'line',
+            data:[]
+        },
+        {
+            name:'降水量',
+            type:'bar',
+            data:[]
+        },
+        {
+            name:'最低气温',
+            type:'line',
+            data:[]
+        },
+        {
+            name:'组成',
+            type:'pie',
+            data:[]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/line.html b/doc/example/line.html
new file mode 100644
index 0000000..6a27784
--- /dev/null
+++ b/doc/example/line.html
@@ -0,0 +1,230 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['邮件营销','联盟广告','直接访问','搜索引擎']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : [
+        {
+            type : 'category',
+            boundaryGap : false,
+            data : ['周一','周二','周三','周四','周五','周六','周日']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            splitArea : {show : true}
+        }
+    ],
+    series : [
+        {
+            name:'邮件营销',
+            type:'line',
+            stack: '总量',
+            brokenPoint: 'none',
+            itemStyle: {
+                normal: {
+                    areaStyle: {
+                        // 区域图,纵向渐变填充
+                        color : (function(){
+                            var zrColor = require('zrender/tool/color');
+                            return zrColor.getLinearGradient(
+                                0, 200, 0, 400,
+                                [[0, 'rgba(255,0,0,0.8)'],[0.8, 'rgba(255,255,255,0.1)']]
+                            )
+                        })()
+                    }
+                }
+            },
+            data:[120, 132, 301, 134, 90, 230, 210]
+        },
+        {
+            name:'联盟广告',
+            type:'line',
+            stack: '总量',
+            brokenPoint: 'emptyCircle',     // 系列级个性化拐点图形
+            brokenPointSize: 8,
+            data:[
+                120, 82,
+                {
+                    value:201,
+                    brokenPoint: 'circle',  // 数据级个性化拐点图形
+                    brokenPointSize : 10
+                },
+                {
+                    value:134,
+                    brokenPoint: 'none'
+                },
+                190, 230, 110
+            ]
+        },
+        {
+            name:'直接访问',
+            type:'line',
+            stack: '总量',
+            itemStyle: {
+                normal: {
+                    color: 'red',
+                    lineStyle: {        // 系列级个性化折线样式
+                        width: 2,
+                        type: 'dashed'
+                    }
+                },
+                emphasis: {
+                    color: 'blue'
+                }
+            },
+            data:[
+                320, 332, '-', 334,
+                {
+                    value: 390,
+                    brokenPointSize : 10,
+                    itemStyle: {        // 数据级个性化折线样式
+                        normal: {
+                            color: 'green'
+                        },
+                        emphasis: {
+                            color: 'orange'
+                        }
+                    }
+                },
+                330, 320
+            ]
+        },
+        {
+            name:'搜索引擎',
+            type:'line',
+            itemStyle: {
+                normal: {
+                    lineStyle: {            // 系列级个性化折线样式,横向渐变描边
+                        width: 2,
+                        color: (function(){
+                            var zrColor = require('zrender/tool/color');
+                            return zrColor.getLinearGradient(
+                                0, 0, 1000, 0,
+                                [[0, 'rgba(255,0,0,0.8)'],[0.8, 'rgba(255,255,0,0.8)']]
+                            )
+                        })()
+                    }
+                }
+            },
+            data:[620, 732, 701, 734, 890, 930, 820]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/line1.html b/doc/example/line1.html
new file mode 100644
index 0000000..dcc8a34
--- /dev/null
+++ b/doc/example/line1.html
@@ -0,0 +1,150 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['最高气温','最低气温']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : [
+        {
+            type : 'category',
+            boundaryGap : false,
+            data : ['周一','周二','周三','周四','周五','周六','周日']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            axisLabel : {
+                formatter: '{value} °C'
+            },
+            splitArea : {show : true}
+        }
+    ],
+    series : [
+        {
+            name:'最高气温',
+            type:'line',
+            data:[11, 11, 15, 13, 12, 13, 10]
+        },
+        {
+            name:'最低气温',
+            type:'line',
+            data:[-2, 1, 2, 5, 3, 2, 0]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/line2.html b/doc/example/line2.html
new file mode 100644
index 0000000..de408d2
--- /dev/null
+++ b/doc/example/line2.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['邮件营销','联盟广告','视频广告','直接访问','搜索引擎']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : [
+        {
+            type : 'category',
+            boundaryGap : false,
+            data : ['周一','周二','周三','周四','周五','周六','周日']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            splitArea : {show : true}
+        }
+    ],
+    series : [
+        {
+            name:'邮件营销',
+            type:'line',
+            stack: '总量',
+            data:[120, 132, 101, 134, 90, 230, 210]
+        },
+        {
+            name:'联盟广告',
+            type:'line',
+            stack: '总量',
+            data:[220, 182, 191, 234, 290, 330, 310]
+        },
+        {
+            name:'视频广告',
+            type:'line',
+            stack: '总量',
+            data:[150, 232, 201, 154, 190, 330, 410]
+        },
+        {
+            name:'直接访问',
+            type:'line',
+            stack: '总量',
+            data:[320, 332, 301, 334, 390, 330, 320]
+        },
+        {
+            name:'搜索引擎',
+            type:'line',
+            stack: '总量',
+            data:[820, 932, 901, 934, 1290, 1330, 1320]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/line3.html b/doc/example/line3.html
new file mode 100644
index 0000000..da6df54
--- /dev/null
+++ b/doc/example/line3.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['意向','预购','成交']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : [
+        {
+            type : 'category',
+            boundaryGap : false,
+            data : ['周一','周二','周三','周四','周五','周六','周日']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value'
+        }
+    ],
+    series : [
+        {
+            name:'成交',
+            type:'line',
+            itemStyle: {normal: {areaStyle: {type: 'default'}}},
+            data:[10, 12, 21, 54, 260, 830, 710]
+        },
+        {
+            name:'预购',
+            type:'line',
+            itemStyle: {normal: {areaStyle: {type: 'default'}}},
+            data:[30, 182, 434, 791, 390, 30, 10]
+        },
+        {
+            name:'意向',
+            type:'line',
+            itemStyle: {normal: {areaStyle: {type: 'default'}}},
+            data:[1320, 1132, 601, 234, 120, 90, 20]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/line4.html b/doc/example/line4.html
new file mode 100644
index 0000000..3dcb259
--- /dev/null
+++ b/doc/example/line4.html
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    legend: {
+        data:['邮件营销','联盟广告','视频广告','直接访问','搜索引擎']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : [
+        {
+            type : 'category',
+            boundaryGap : false,
+            data : ['周一','周二','周三','周四','周五','周六','周日']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value'
+        }
+    ],
+    series : [
+        {
+            name:'邮件营销',
+            type:'line',
+            stack: '总量',
+            itemStyle: {normal: {areaStyle: {
+                color: 'rgba(255, 69, 0, 0.7)'
+            }}},
+            data:[120, 132, 101, 134, 90, 230, 210]
+        },
+        {
+            name:'联盟广告',
+            type:'line',
+            stack: '总量',
+            itemStyle: {normal: {areaStyle: {
+                color: 'rgba(30, 144, 255, 0.6)'
+            }}},
+            data:[220, 182, 191, 234, 290, 330, 310]
+        },
+        {
+            name:'视频广告',
+            type:'line',
+            stack: '总量',
+            itemStyle: {normal: {areaStyle: {
+                color: 'rgba(138, 43, 226, 0.5)'
+            }}},
+            data:[150, 232, 201, 154, 190, 330, 410]
+        },
+        {
+            name:'直接访问',
+            type:'line',
+            stack: '总量',
+            itemStyle: {normal: {areaStyle: {
+                color: 'rgba(34, 139, 34, 0.4)'
+            }}},
+            data:[320, 332, 301, 334, 390, 330, 320]
+        },
+        {
+            name:'搜索引擎',
+            type:'line',
+            stack: '总量',
+            itemStyle: {normal: {areaStyle: {
+                color: 'rgba(220, 20, 60, 0.3)'
+            }}},
+            data:[820, 932, 901, 934, 1290, 1330, 1320]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/line5.html b/doc/example/line5.html
new file mode 100644
index 0000000..bcb2e56
--- /dev/null
+++ b/doc/example/line5.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    legend: {
+        data:['高度(km)与气温(°C)变化关系']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    tooltip : {
+        trigger: 'axis',
+        formatter: "Temperature : <br/>{b}km : {c}°C"
+    },
+    xAxis : [
+        {
+            type : 'value',
+            axisLabel : {
+                formatter: '{value} °C'
+            },
+            splitArea : {show : true}
+        }
+    ],
+    yAxis : [
+        {
+            type : 'category',
+            axisLabel : {
+                formatter: '{value} km'
+            },
+            boundaryGap : false,
+            data : ['0', '10', '20', '30', '40', '50', '60', '70', '80']
+        }
+    ],
+    series : [
+        {
+            name:'高度(km)与气温(°C)变化关系',
+            type:'line',
+            data:[15, -50, -56.5, -46.5, -22.1, -2.5, -27.7, -55.7, -76.5]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/loading.html b/doc/example/loading.html
new file mode 100644
index 0000000..562404e
--- /dev/null
+++ b/doc/example/loading.html
@@ -0,0 +1,244 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+var effect = ['spin' , 'bar' , 'ring' , 'whirling' , 'dynamicLine' , 'bubble'];
+effectIndex = ++effectIndex % effect.length;
+myChart.showLoading({
+    text : effect[effectIndex],
+    effect : effect[effectIndex],
+    textStyle : {
+        fontSize : 20
+    }
+});
+clearTimeout(loadingTicket);
+loadingTicket = setTimeout(function(){
+    refreshing = false;
+    myChart.setSeries([
+        {
+            name:'蒸发量',
+            type: effectIndex % 2 == 0 ? 'bar' : 'line',
+            data:[2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
+        },
+        {
+            name:'降水量',
+            type: effectIndex % 2 == 0 ? 'bar' : 'line',
+            data:[2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
+        }
+    ]);
+},2200);
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Loading ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script type="text/javascript">
+        var myChart;
+        var domCode = document.getElementById('sidebar-code');
+        var domGraphic = document.getElementById('graphic');
+        var domMain = document.getElementById('main');
+        var domMessage = document.getElementById('wrong-message');
+        var iconResize = document.getElementById('icon-resize');
+        var needRefresh = false;
+        var loadingTicket;
+
+        function autoResize() {
+            if (iconResize.className == 'icon-resize-full') {
+                focusCode();
+                iconResize.className = 'icon-resize-small';
+            }
+            else {
+                focusGraphic();
+                iconResize.className = 'icon-resize-full';
+            }
+        }
+
+        function focusCode() {
+            domCode.className = 'span8 ani';
+            domGraphic.className = 'span4 ani';
+        }
+
+        function focusGraphic() {
+            domCode.className = 'span4 ani';
+            domGraphic.className = 'span8 ani';
+            refresh()
+        }
+
+        var editor = CodeMirror.fromTextArea(
+            document.getElementById("code"),
+            { lineNumbers: true }
+        );
+        editor.setOption("theme", 'monokai');
+
+
+        editor.on('change', function(){needRefresh = true;});
+
+        var effectIndex = -1;
+        function refresh(isBtnRefresh){
+            if (isBtnRefresh) {
+                needRefresh = true;
+                focusGraphic();
+                return;
+            }
+            needRefresh = false;
+           // try {
+                (new Function(editor.doc.getValue()))();
+                domMessage.innerHTML = '';
+           // }catch (e) {
+            //    domMessage.innerHTML = e;
+           // }
+        }
+
+        require.config({
+            paths: {
+                'js': '../asset/js/esl/js'
+            },
+            packages: [
+                {
+                    name: 'echarts',
+                    location: '../../src',
+                    main: 'echarts'
+                },
+                {
+                    name: 'zrender',
+                    location: '../../../zrender/src',
+                    main: 'zrender'
+                }
+            ]
+        });
+
+        require(
+            ['echarts/echarts'],
+            function(echarts) {
+                if (myChart && myChart.dispose) {
+                    myChart.dispose();
+                }
+                myChart = echarts.init(domMain);
+                myChart.setOption({
+                    tooltip : {
+                        trigger: 'axis'
+                    },
+                    toolbox: {
+                        show : true,
+                        feature : {
+                            mark : true,
+                            dataView : {readOnly: false},
+                            magicType:['line', 'bar'],
+                            refresh : true
+                        }
+                    },
+                    legend: {
+                        data:['蒸发量','降水量']
+                    },
+                    xAxis : [
+                        {
+                            type : 'category',
+                            data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月']
+                        }
+                    ],
+                    yAxis : [
+                        {
+                            type : 'value',
+                            splitArea : {show : true}
+                        }
+                    ]},
+                    true
+                );
+                refresh();
+            }
+        )
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/mix1.html b/doc/example/mix1.html
new file mode 100644
index 0000000..3291b2b
--- /dev/null
+++ b/doc/example/mix1.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    legend: {
+        data:['蒸发量','降水量','平均温度']
+    },
+    xAxis : [
+        {
+            type : 'category',
+            data : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            axisLabel : {
+                formatter: '{value} ml'
+            },
+            splitArea : {show : true}
+        },
+        {
+            type : 'value',
+            axisLabel : {
+                formatter: '{value} °C'
+            },
+            splitLine : {show : false}
+        }
+    ],
+    series : [
+
+        {
+            name:'蒸发量',
+            type:'bar',
+            data:[2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
+        },
+        {
+            name:'降水量',
+            type:'bar',
+            data:[2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
+        },
+        {
+            name:'平均温度',
+            type:'line',
+            yAxisIndex: 1,
+            data:[2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/mix2.html b/doc/example/mix2.html
new file mode 100644
index 0000000..5b25486
--- /dev/null
+++ b/doc/example/mix2.html
@@ -0,0 +1,194 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'axis'
+    },
+    toolbox: {
+        show : true,
+        y: 'bottom',
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    legend: {
+        data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎','百度','谷歌','必应','其他']
+    },
+    xAxis : [
+        {
+            type : 'category',
+            splitLine : {show : false},
+            data : ['周一','周二','周三','周四','周五','周六','周日']
+        }
+    ],
+    yAxis : [
+        {
+            type : 'value',
+            position: 'right',
+            splitArea : {show : true}
+        }
+    ],
+    series : [
+        {
+            name:'直接访问',
+            type:'bar',
+            data:[320, 332, 301, 334, 390, 330, 320]
+        },
+        {
+            name:'邮件营销',
+            type:'bar',
+            tooltip : {trigger: 'item'},
+            stack: '广告',
+            data:[120, 132, 101, 134, 90, 230, 210]
+        },
+        {
+            name:'联盟广告',
+            type:'bar',
+            tooltip : {trigger: 'item'},
+            stack: '广告',
+            data:[220, 182, 191, 234, 290, 330, 310]
+        },
+        {
+            name:'视频广告',
+            type:'bar',
+            tooltip : {trigger: 'item'},
+            stack: '广告',
+            data:[150, 232, 201, 154, 190, 330, 410]
+        },
+        {
+            name:'搜索引擎',
+            type:'line',
+            data:[862, 1018, 964, 1026, 1679, 1600, 1570]
+        },
+
+        {
+            name:'搜索引擎细分',
+            type:'pie',
+            tooltip : {
+                trigger: 'item',
+                formatter: '{a} <br/>{b} : {c} ({d}%)'
+            },
+            center: [160,120],
+            radius : [0, 50],
+            itemStyle : {
+                normal : {
+                    labelLine : {
+                        length : 20
+                    }
+                }
+            },
+            data:[
+                {value:1048, name:'百度'},
+                {value:251, name:'谷歌'},
+                {value:147, name:'必应'},
+                {value:102, name:'其他'}
+            ]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/pie.html b/doc/example/pie.html
new file mode 100644
index 0000000..750817b
--- /dev/null
+++ b/doc/example/pie.html
@@ -0,0 +1,276 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        show: true,
+        formatter: "{a} <br/>{b} : {c} ({d}%)"
+    },
+    legend: {
+        orient : 'vertical',
+        x : 'left',
+        data:['直达','营销广告','搜索引擎','邮件营销','联盟广告','视频广告','百度','谷歌','必应','其他']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            refresh : true
+        }
+    },
+    calculable : true,
+    series : [
+        {
+            name:'访问来源',
+            type:'pie',
+            center : [300, 200],
+            radius : 80,
+            itemStyle : {
+                normal : {
+                    label : {
+                        position : 'inner'
+                    },
+                    labelLine : {
+                        show : false
+                    }
+                }
+            },
+            data:[
+                {value:335, name:'直达'},
+                {value:679, name:'营销广告'},
+                {
+                    value:1548,
+                    name:'搜索引擎',
+                    itemStyle : {
+                        normal : {
+                            label : {
+                                show : false
+                            }
+                        },
+                        emphasis : {
+                            label : {
+                                show : true,
+                                position : 'inner'
+                            }
+                        }
+                    }
+                }
+            ]
+        },
+        {
+            name:'访问来源',
+            type:'pie',
+            center : [300, 200],
+            radius : [110, 140],
+            data:[
+                {value:335, name:'直达'},
+                {value:310, name:'邮件营销'},
+                {value:234, name:'联盟广告'},
+                {value:135, name:'视频广告'},
+                {
+                    value:1048,
+                    name:'百度',
+                    itemStyle : {
+                        normal : {
+                            color : (function(){
+                                var zrColor = require('zrender/tool/color');
+                                return zrColor.getRadialGradient(
+                                    300, 200, 110, 300, 200, 140,
+                                    [[0, 'rgba(255,255,0,1)'],[1, 'rgba(30,144,250,1)']]
+                                )
+                            })(),
+                            label : {
+                                textStyle : {
+                                    color : 'rgba(30,144,255,0.8)',
+                                    align : 'center',
+                                    baseline : 'middle',
+                                    fontFamily : '微软雅黑',
+                                    fontSize : 30,
+                                    fontWeight : 'bolder'
+                                }
+                            },
+                            labelLine : {
+                                length : 80,
+                                lineStyle : {
+                                    color : '#f0f',
+                                    width : 3,
+                                    type : 'dotted'
+                                }
+                            }
+                        }
+                    }
+                },
+                {value:251, name:'谷歌'},
+                {
+                    value:102,
+                    name:'必应',
+                    itemStyle : {
+                        normal : {
+                            label : {
+                                show : false
+                            },
+                            labelLine : {
+                                show : false
+                            }
+                        },
+                        emphasis : {
+                            label : {
+                                show : true
+                            },
+                            labelLine : {
+                                show : true,
+                                length : 180
+                            }
+                        }
+                    }
+                },
+                {value:147, name:'其他'}
+            ]
+        },
+        {
+            name:'访问来源',
+            type:'pie',
+            startAngle: 90,
+            center : [650, 200],
+            radius : [80, 120],
+            itemStyle : {
+                normal : {
+                    label : {
+                        show : false
+                    },
+                    labelLine : {
+                        show : false
+                    }
+                },
+                emphasis : {
+                    color: (function(){
+                        var zrColor = require('zrender/tool/color');
+                        return zrColor.getRadialGradient(
+                            650, 200, 80, 650, 200, 120,
+                            [[0, 'rgba(255,255,0,1)'],[1, 'rgba(255,0,0,1)']]
+                        )
+                    })(),
+                    label : {
+                        show : true,
+                        position : 'center',
+                        textStyle : {
+                            color : 'red',
+                            fontSize : '30',
+                            fontFamily : '微软雅黑',
+                            fontWeight : 'bold'
+                        }
+                    }
+                }
+            },
+            data:[
+                {value:335, name:'直达'},
+                {value:310, name:'邮件营销'},
+                {value:234, name:'联盟广告'},
+                {value:135, name:'视频广告'},
+                {value:1548, name:'搜索引擎'}
+            ]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/pie1.html b/doc/example/pie1.html
new file mode 100644
index 0000000..7357a33
--- /dev/null
+++ b/doc/example/pie1.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'item',
+        formatter: "{a} <br/>{b} : {c} ({d}%)"
+    },
+    legend: {
+        orient : 'vertical',
+        x : 'left',
+        data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            refresh : true
+        }
+    },
+    calculable : true,
+    series : [
+        {
+            name:'访问来源',
+            type:'pie',
+            radius : [0, 120],
+            data:[
+                {value:335, name:'直接访问'},
+                {value:310, name:'邮件营销'},
+                {value:234, name:'联盟广告'},
+                {value:135, name:'视频广告'},
+                {value:1548, name:'搜索引擎'}
+            ]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/pie2.html b/doc/example/pie2.html
new file mode 100644
index 0000000..1a4d67d
--- /dev/null
+++ b/doc/example/pie2.html
@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'item',
+        formatter: "{a} <br/>{b} : {c} ({d}%)"
+    },
+    legend: {
+        orient : 'vertical',
+        x : 'left',
+        data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            refresh : true
+        }
+    },
+    calculable : true,
+    series : [
+        {
+            name:'访问来源',
+            type:'pie',
+            radius : [80, 120],
+            itemStyle : {
+                normal : {
+                    label : {
+                        show : false
+                    },
+                    labelLine : {
+                        show : false
+                    }
+                },
+                emphasis : {
+                    label : {
+                        show : true,
+                        position : 'center',
+                        textStyle : {
+                            fontSize : '30',
+                            fontWeight : 'bold'
+                        }
+                    }
+                }
+            },
+            data:[
+                {value:335, name:'直接访问'},
+                {value:310, name:'邮件营销'},
+                {value:234, name:'联盟广告'},
+                {value:135, name:'视频广告'},
+                {value:1548, name:'搜索引擎'}
+            ]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/pie3.html b/doc/example/pie3.html
new file mode 100644
index 0000000..43d894f
--- /dev/null
+++ b/doc/example/pie3.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {
+        trigger: 'item',
+        formatter: "{a} <br/>{b} : {c} ({d}%)"
+    },
+    legend: {
+        orient : 'vertical',
+        x : 'left',
+        data:['直达','营销广告','搜索引擎','邮件营销','联盟广告','视频广告','百度','谷歌','必应','其他']
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            refresh : true
+        }
+    },
+    calculable : true,
+    series : [
+        {
+            name:'访问来源',
+            type:'pie',
+            radius : [0, 70],
+            itemStyle : {
+                normal : {
+                    label : {
+                        position : 'inner'
+                    },
+                    labelLine : {
+                        show : false
+                    }
+                }
+            },
+            data:[
+                {value:335, name:'直达'},
+                {value:679, name:'营销广告'},
+                {value:1548, name:'搜索引擎'}
+            ]
+        },
+        {
+            name:'访问来源',
+            type:'pie',
+            radius : [100, 140],
+            data:[
+                {value:335, name:'直达'},
+                {value:310, name:'邮件营销'},
+                {value:234, name:'联盟广告'},
+                {value:135, name:'视频广告'},
+                {value:1048, name:'百度'},
+                {value:251, name:'谷歌'},
+                {value:147, name:'必应'},
+                {value:102, name:'其他'}
+            ]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/doc/example/tooltip.html b/doc/example/tooltip.html
new file mode 100644
index 0000000..2ef2eb6
--- /dev/null
+++ b/doc/example/tooltip.html
@@ -0,0 +1,197 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="../asset/js/esl/esl.js"></script>
+    <script src="../asset/js/codemirror.js"></script>
+    <script src="../asset/js/javascript.js"></script>
+
+    <link href="../asset/css/bootstrap.css" rel="stylesheet">
+    <link href="../asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="../asset/css/codemirror.css" rel="stylesheet">
+    <link href="../asset/css/monokai.css" rel="stylesheet">
+    <link href="../asset/css/echartsHome.css" rel="stylesheet">
+    <link rel="shortcut icon" href="../asset/ico/favicon.png">
+</head>
+
+<body>
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="../../index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li><a href="../../index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li class="active"><a href="../example.html" class="active">Example</a></li>
+                <li><a href="../doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="container-fluid">
+        <div class="row-fluid">
+            <div id="sidebar-code" class="span4">
+                <div class="well sidebar-nav">
+                    <div class="nav-header"><a href="#" onclick="autoResize()" class="icon-resize-full" id ="icon-resize" ></a>option</div>
+                    <textarea id="code" name="code">
+option = {
+    tooltip : {         // Option config. Can be overwrited by series or data
+        trigger: 'axis',
+        //show: true,   //default true
+        backgroundColor : 'rgba(255,0,255,0.7)',
+        borderColor : '#f50',
+        borderRadius : 8,
+        borderWidth: 2,
+        padding: 10,    // [5, 10, 15, 20]
+        textStyle : {
+            color: 'yellow',
+            decoration: 'none',
+            fontFamily: 'Verdana, sans-serif',
+            fontSize: 15,
+            fontStyle: 'italic',
+            fontWeight: 'bold'
+        },
+        formatter: function(params,ticket,callback) {
+            var res = 'Function formatter : <br/>' + params[0][1];
+            for (var i = 0, l = params.length; i < l; i++) {
+                res += '<br/>' + params[i][0] + ' : ' + params[i][2];
+            }
+            setTimeout(function(){
+                // 仅为了模拟异步回调
+                callback(ticket, res);
+            }, 1000)
+            return 'loading';
+        }
+        //formatter: "Template formatter: <br/>{b}<br/>{a}:{c}<br/>{a1}:{c1}"
+    },
+    toolbox: {
+        show : true,
+        feature : {
+            mark : true,
+            dataView : {readOnly: false},
+            magicType:['line', 'bar'],
+            refresh : true
+        }
+    },
+    calculable : true,
+    xAxis : {
+        data : ['周一','周二','周三','周四','周五','周六','周日']
+    },
+    series : [
+        {
+            name:'坐标轴触发1',
+            type:'bar',
+            data:[320, 332, 301, 334, 390, 330, 320]
+        },
+        {
+            name:'坐标轴触发2',
+            type:'bar',
+            data:[862, 1018, 964, 1026, 1679, 1600, 157]
+        },
+        {
+            name:'数据项触发1',
+            type:'bar',
+            tooltip : {             // Series config.
+                trigger: 'item',
+                backgroundColor: 'black',
+                formatter: "Series formatter: <br/>{a}<br/>{b}:{c}"
+            },
+            stack: '数据项',
+            data:[
+                120, 132,
+                {
+                    value: 301,
+                    itemStyle: {normal: {color: 'red'}},
+                    tooltip : {     // Data config.
+                        backgroundColor: 'blue',
+                        formatter: "Data formatter: <br/>{a}<br/>{b}:{c}"
+                    }
+                },
+                134, 90,
+                {
+                    value: 230,
+                    tooltip: {show: false}
+                },
+                210
+            ]
+        },
+        {
+            name:'数据项触发2',
+            type:'bar',
+            tooltip : {
+                show : false,
+                trigger: 'item'
+            },
+            stack: '数据项',
+            data:[150, 232, 201, 154, 190, 330, 410]
+        }
+    ]
+};
+                    </textarea>
+              </div><!--/.well -->
+            </div><!--/span-->
+            <div id="graphic" class="span8">
+                <div id="main" class="main"></div>
+                <div>
+                    <button onclick="refresh(true)">Refresh ~</button>
+                    <span id='wrong-message' style="color:red"></span>
+                </div>
+            </div><!--/span-->
+        </div><!--/row-->
+        <hr>
+        <!-- FOOTER -->
+        <footer>
+          <p class="pull-right"><a href="#">Back to top</a></p>
+          <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+        </footer>
+    </div><!--/.fluid-container-->
+
+    <script src="../asset/js/jquery.js"></script>
+    <script src="../asset/js/bootstrap-transition.js"></script>
+    <script src="../asset/js/bootstrap-alert.js"></script>
+    <script src="../asset/js/bootstrap-modal.js"></script>
+    <script src="../asset/js/bootstrap-dropdown.js"></script>
+    <script src="../asset/js/bootstrap-scrollspy.js"></script>
+    <script src="../asset/js/bootstrap-tab.js"></script>
+    <script src="../asset/js/bootstrap-tooltip.js"></script>
+    <script src="../asset/js/bootstrap-popover.js"></script>
+    <script src="../asset/js/bootstrap-button.js"></script>
+    <script src="../asset/js/bootstrap-collapse.js"></script>
+    <script src="../asset/js/bootstrap-carousel.js"></script>
+    <script src="../asset/js/bootstrap-typeahead.js"></script>
+    <script src="../asset/js/echartsExample.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..2d0bbe8
--- /dev/null
+++ b/index.html
@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <title>ECharts</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="description" content="ECharts">
+    <meta name="author" content="linzhifeng@baidu.com">
+
+    <script src="doc/asset/js/esl/esl.js"></script>
+
+    <!-- Le styles -->
+    <link href="doc/asset/css/bootstrap.css" rel="stylesheet">
+    <link href="doc/asset/css/bootstrap-responsive.css" rel="stylesheet">
+    <link href="doc/asset/css/echartsHome.css" rel="stylesheet">
+
+    <!-- Fav and touch icons -->
+    <link rel="shortcut icon" href="doc/asset/ico/favicon.png">
+  </head>
+
+  <body>
+
+    <!-- NAVBAR
+    ================================================== -->
+    <div class="navbar navbar-inverse navbar-fixed-top">
+      <div class="navbar-inner">
+        <div class="container">
+          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+            <span class="icon-bar"></span>
+          </button>
+          <a class="brand" href="index.html">ECharts</a>
+          <div class="nav-collapse collapse">
+              <a id="forkme_banner" href="https://github.com/ecomfe/echarts">View on GitHub</a>
+              <ul class="nav">
+                <li class="active"><a href="index.html"><i class="icon-home icon-white"></i> Home</a></li>
+                <li><a href="doc/example.html" class="active">Example</a></li>
+                <li><a href="doc/doc.html" >API &amp; Doc</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt icon-white"></i>Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe/echarts/archive/1.0.0.zip">ZIP (1.0.0)</a></li>
+                    <li><a href="https://github.com/ecomfe/echarts/archive/master.zip">ZIP (Latest)</a></li>
+                  </ul>
+                </li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Link <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="https://github.com/ecomfe" target="_blank">Ecom-FE</a></li>
+                    <li><a href="http://fe.baidu.com/doc/ecom/tech/topic/dv/index.html" target="_blank">Data Visualization</a></li>
+                    <li class="divider"></li>
+                    <!--li class="nav-header">Library</li-->
+                    <li><a href="http://ecomfe.github.io/zrender/index.html" target="_blank">ZRender</a></li>
+                    <li><a href="http://tangram.baidu.com/" target="_blank">Tangram</a></li>
+                  </ul>
+                </li>
+              </ul>
+           </div><!--/.nav-collapse -->
+        </div><!-- /.container -->
+      </div><!-- /.navbar-inner -->
+    </div><!-- /.navbar-wrapper -->
+
+    <div class="face" id='face'>
+    <!-- Carousel
+    ================================================== -->
+    <div id="myCarousel" class="carousel slide">
+      <div class="carousel-inner">
+        <div class="item active">
+          <img src="doc/asset/img/slide-02.png" alt="">
+          <div class="container">
+            <div class="carousel-caption">
+              <h1>ECharts</h1>
+              <h6>(1.0.0)</h6>
+              <p>基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。创新的拖拽重计算、数据视图等特性大大增强了用户体验,赋予了用户对数据进行挖掘、整合的能力。</p>
+              <p style="text-align: right;"><strong>———— 大数据时代,重新定义数据图表的时候到了</strong></p>
+            </div>
+          </div>
+        </div>
+        <div class="item">
+          <img src="doc/asset/img/slide-03.png" alt="">
+          <div class="container">
+            <div class="carousel-caption">
+              <h1>ZRender</h1>
+              <p>一个轻量级的Canvas类库,MVC封装,数据驱动,提供类Dom事件模型,让canvas绘图大不同~~</p>
+              <br/>
+              <a class="btn btn-large btn-primary" href="http://ecomfe.github.io/zrender/" target="_blank">了解更多 &raquo;</a>
+            </div>
+          </div>
+        </div>
+      </div>
+      <a class="left carousel-control" href="#myCarousel" data-slide="prev">&lsaquo;</a>
+      <a class="right carousel-control" href="#myCarousel" data-slide="next">&rsaquo;</a>
+    </div><!-- /.carousel -->
+    </div>
+    <!-- Marketing messaging and featurettes
+    ================================================== -->
+    <!-- Wrap the rest of the page in another container to center all the content. -->
+
+    <div class="container">
+      <div class="featurette">
+        <h2 class="featurette-heading">Architecture</h2>
+        <div class="span6 pull-right">
+            <img src="doc/asset/img/architecture.png" />
+        </div>
+        <p class="lead">ECharts (Enterprise Charts 商业产品图表库)</p>
+        <p>提供商业产品常用图表库,底层基于<a href="http://ecomfe.github.io/zrender/" target="_blank">ZRender</a>,创建了坐标系,图例,提示,工具箱等基础组件,并在此上构建出折线图(区域图)、柱状图(条状图)、饼图(环形图),同时支持任意维度的堆积和多图表混合展现。</p>
+        <div style="float:left;margin:10px 10px 30px 10px;"><img src="doc/asset/img/device.png" /></div>
+        <div>
+            <img src="doc/asset/img/explorer.png" />
+            <p>&nbsp;&nbsp;<i>(IE8- supported by <a href="https://code.google.com/p/explorercanvas/" target="_blank">excanvas</a> )</i></p>
+        </div>
+      </div>
+      <h2 class="featurette-heading">特色</h2>
+      <hr class="featurette-divider">
+      <div class="featurette">
+        <div class="span5 pull-left">
+            <img src="doc/asset/img/mix.jpg" />
+        </div>
+        <h2 class="featurette-heading">混搭</h2>
+        <p>标准图库支持3种基本图表类型及其任意混搭:</p>
+        <p>折线图line(包含区域图)、柱状图bar(包含横向条状图)、饼图pie。</p>
+        <p>(散点图scatter、雷达图radar,暂不提供)</p>
+        <p>混搭情况下一个标准图表:包含唯一图例模块,一个直角坐标系(可包含一条或多条类目轴线,一条或多条值轴线,最多上下左右四条)</p>
+      </div>
+      <hr class="featurette-divider">
+      <div class="featurette">
+        <div class="span6 pull-right">
+            <img src="doc/asset/img/draggable.gif" />
+        </div>
+        <h2 class="featurette-heading">拖拽重计算</h2>
+        <p>拖拽重计算特性(已申请专利)带来了数据统计图表从未有过的用户体验,允许用户对统计数据进行有效的提取、整合,甚至在多个图表间交换数据,赋予了用户对数据进行挖掘、整合的能力。</p>
+      </div>
+      <hr class="featurette-divider">
+      <div class="featurette">
+        <div class="span6 pull-left">
+            <img src="doc/asset/img/dataView.gif" />
+        </div>
+        <h2 class="featurette-heading">数据视图</h2>
+        <p>如果你所呈现的数据足够让用户所关心,那么他们将不满足于查看可视化的图表,要去逐一迎合他们下载保存,数据分享,加工整合已有数据等等需求?</p>
+        <p>或许你只要给予一个“,”分隔的数据文本他们就懂了,这就是ECharts的数据视图!当然,你可以重载数据视图的输出方法,用你独特的方式去呈现数据。</p>
+        <p>如果你的用户足够的高端,你甚至可以打开数据视图的编辑功能,跟拖拽重计算相比,这可是批量的数据修改!</p>
+      </div>
+      <hr class="featurette-divider">
+      <div class="featurette">
+          <div class="span6 pull-right">
+            <img src="doc/asset/img/magicType.gif" />
+        </div>
+        <h2 class="featurette-heading">动态类型切换</h2>
+        <p>很多图表类型本身所表现的能力是相似的,但由于数据差异、表现需求和个人喜好的不同导致最终图表所呈现的张力又大不一样,比如折线图和柱状图的选择总是让人头疼。</p>
+        <p>ECharts提供了动态类型切换,让用户随心所欲的切换到他所需要的图表类型。</p>
+      </div>
+      <hr class="featurette-divider">
+      <div class="featurette">
+        <div class="span6 pull-left">
+            <img src="doc/asset/img/legendSelected.gif" />
+        </div>
+        <h2 class="featurette-heading">图例开关</h2>
+        <p>ECharts提供了方便快捷的图例开关,可以随时切换到你所关心的数据系列。</p>
+      </div>
+      <hr class="featurette-divider">
+      <div class="featurette">
+          <div class="span6 pull-right">
+            <img src="doc/asset/img/datazoom.gif" />
+        </div>
+        <h2 class="featurette-heading">数据区域选择</h2>
+        <p>数据可以是无限的,但显示空间总是有限的,数据区域选择组件提供了大数据量中漫游的能力,让用户选择并呈现他所关心的数据区域。</p>
+      </div>
+      <hr class="featurette-divider">
+      <div class="featurette">
+        <div class="span6 pull-left">
+            <img src="doc/asset/img/mark.gif" />
+        </div>
+        <h2 class="featurette-heading">标线辅助</h2>
+        <p>趋势线?平均线?未来走势?修正值?有需求用户自然知道用意~</p>
+        <p>提供标线辅助在K线图中可是必要的功能!是的,K线图我们正在开发中~</p>
+      </div>
+      <hr class="featurette-divider">
+      <div class="featurette">
+        <div class="span6 pull-right">
+            <img src="doc/asset/img/multiStack.png" />
+        </div>
+        <h2 class="featurette-heading">多维度堆积</h2>
+        <p>支持多系列,多维度的数据堆积,配合自动伸缩的图形实体和直角坐标系,能呈现出更有内涵的统计图表~</p>
+      </div>
+      <hr class="featurette-divider">
+      <div class="featurette">
+        <div class="pull-left">
+            <img src="doc/asset/img/doc/multiControl.jpg" style="height:145px"/>
+        </div>
+        <div class="pull-left">
+            <img src="doc/asset/img/custom.png"/>
+        </div>
+        <h2 class="featurette-heading">个性化定制</h2>
+        <p>近300个可配置选项结合多级控制设计满足高度定制的个性化需求。</p>
+        <a href="doc/doc.html" target="_blank">详细文档 &raquo;</a>
+      </div>
+      <hr class="featurette-divider">
+      <div class="featurette">
+        <h2 class="featurette-heading">事件交互</h2>
+        <p>可以捕获的用户交互和数据变化事件实现图表与外界的联动。<a href="doc/example/event.html" target="_blank">try this &raquo;</a></p>
+      </div>
+      <hr>
+      <!-- /END THE FEATURETTES -->
+
+      <!-- FOOTER -->
+      <footer>
+        <p class="pull-right"><a href="#">Back to top</a></p>
+        <p>&copy; 2013 Ecom-FE. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
+      </footer>
+
+    </div><!-- /.container -->
+
+    <!-- Le javascript
+    ================================================== -->
+    <!-- Placed at the end of the document so the pages load faster -->
+    <script src="doc/asset/js/jquery.js"></script>
+    <script src="doc/asset/js/bootstrap-transition.js"></script>
+    <script src="doc/asset/js/bootstrap-alert.js"></script>
+    <script src="doc/asset/js/bootstrap-modal.js"></script>
+    <script src="doc/asset/js/bootstrap-dropdown.js"></script>
+    <script src="doc/asset/js/bootstrap-scrollspy.js"></script>
+    <script src="doc/asset/js/bootstrap-tab.js"></script>
+    <script src="doc/asset/js/bootstrap-tooltip.js"></script>
+    <script src="doc/asset/js/bootstrap-popover.js"></script>
+    <script src="doc/asset/js/bootstrap-button.js"></script>
+    <script src="doc/asset/js/bootstrap-collapse.js"></script>
+    <script src="doc/asset/js/bootstrap-carousel.js"></script>
+    <script src="doc/asset/js/bootstrap-typeahead.js"></script>
+    <script>
+        !function ($) {
+        $(function(){
+          // carousel demo
+         // $('#myCarousel').carousel()
+        })
+      }(window.jQuery)
+    </script>
+  </body>
+</html>
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..d61151f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,14 @@
+{

+    "name": "echarts",

+    "description": "Enterprise Charts,基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。",

+    "version": "1.0.0",

+    "maintainers": [

+        { "name": "Kener", "email": "linzhifeng@baidu.com" }

+    ],

+    "dependencies": {

+        "zrender": "~1.0.0"

+    },

+    "repository": "git://github.com/ecomfe/echarts",

+    "main": "echarts",

+    "homepage": "http://ecomfe.github.com/echarts"

+}
\ No newline at end of file
diff --git a/src/chart.js b/src/chart.js
new file mode 100644
index 0000000..935b179
--- /dev/null
+++ b/src/chart.js
@@ -0,0 +1,41 @@
+/**

+ * echart图表库

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ */

+define(function(require) {    //chart

+    var self = {};

+

+    var _chartLibrary = {};     //echart图表库

+

+    /**

+     * 定义图形实现

+     * @param {Object} name

+     * @param {Object} clazz 图形实现

+     */

+    self.define = function(name, clazz) {

+        _chartLibrary[name] = clazz;

+        return self;

+    };

+

+    /**

+     * 获取图形实现

+     * @param {Object} name

+     */

+    self.get = function(name) {

+        return _chartLibrary[name];

+    };

+

+    // 内置图表注册

+    self.define('island', require('./chart/island'));

+

+    self.define('pie', require('./chart/pie'));

+

+    self.define('bar', require('./chart/bar'));

+

+    self.define('line', require('./chart/line'));

+

+    return self;

+});
\ No newline at end of file
diff --git a/src/chart/bar.js b/src/chart/bar.js
new file mode 100644
index 0000000..538a8e5
--- /dev/null
+++ b/src/chart/bar.js
@@ -0,0 +1,764 @@
+/**

+ * echarts图表类:柱形图

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function(require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} series 数据

+     * @param {Object} component 组件

+     */

+    function Bar(messageCenter, zr, option, component){

+        // 基类装饰

+        var ComponentBase = require('../component/base');

+        ComponentBase.call(this, zr);

+        // 可计算特性装饰

+        var CalculableBase = require('./calculableBase');

+        CalculableBase.call(this, zr, option);

+

+        var ecConfig = require('../config');

+        var ecData = require('../util/ecData');

+

+        var self = this;

+        self.type = ecConfig.CHART_TYPE_BAR;

+

+        var series;                 // 共享数据源,不要修改跟自己无关的项

+

+        var _zlevelBase = self.getZlevelBase();

+

+        var _sIndex2colorMap = {};  // series默认颜色索引,seriesIndex索引到color

+

+        function _buildShape() {

+            self.selectedMap = {};

+

+            // 水平垂直双向series索引 ,position索引到seriesIndex

+            var _position2sIndexMap = {

+                top : [],

+                bottom : [],

+                left : [],

+                right : []

+            };

+            var xAxisIndex;

+            var yAxisIndex;

+            var xAxis;

+            var yAxis;

+            for (var i = 0, l = series.length; i < l; i++) {

+                if (series[i].type == ecConfig.CHART_TYPE_BAR) {

+                    series[i] = self.reformOption(series[i]);

+                    xAxisIndex = series[i].xAxisIndex;

+                    yAxisIndex = series[i].yAxisIndex;

+                    xAxis = component.xAxis.getAxis(xAxisIndex);

+                    yAxis = component.yAxis.getAxis(yAxisIndex);

+                    if (xAxis.type == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY

+                    ) {

+                        _position2sIndexMap[xAxis.getPosition()].push(i);

+                    }

+                    else if (yAxis.type == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY

+                    ) {

+                        _position2sIndexMap[yAxis.getPosition()].push(i);

+                    }

+                }

+            }

+            // console.log(_position2sIndexMap)

+            for (var position in _position2sIndexMap) {

+                if (_position2sIndexMap[position].length > 0) {

+                    _buildSinglePosition(

+                        position, _position2sIndexMap[position]

+                    );

+                }

+            }

+

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                self.shapeList[i].id = zr.newShapeId(self.type);

+                zr.addShape(self.shapeList[i]);

+            }

+        }

+

+        /**

+         * 构建单个方向上的柱形图

+         *

+         * @param {number} seriesIndex 系列索引

+         */

+        function _buildSinglePosition(position, seriesArray) {

+            var mapData = _mapData(seriesArray);

+            var locationMap = mapData.locationMap;

+            var maxDataLength = mapData.maxDataLength;

+

+            if (maxDataLength === 0 || locationMap.length === 0) {

+                return;

+            }

+

+            switch (position) {

+                case 'bottom' :

+                case 'top' :

+                    _buildHorizontal(maxDataLength, locationMap);

+                    break;

+                case 'left' :

+                case 'right' :

+                    _buildVertical(maxDataLength, locationMap);

+                    break;

+            }

+        }

+

+

+        /**

+         * 数据整形

+         * 数组位置映射到系列索引

+         */

+        function _mapData(seriesArray) {

+            var serie;                              // 临时映射变量

+            var dataIndex = 0;                      // 堆叠数据所在位置映射

+            var stackMap = {};                      // 堆叠数据位置映射,堆叠组在二维中的第几项

+            var magicStackKey = '__kener__stack__'; // 堆叠命名,非堆叠数据安单一堆叠处理

+            var stackKey;                           // 临时映射变量

+            var serieName;                          // 临时映射变量

+            var legend = component.legend;

+            var locationMap = [];                   // 需要返回的东西:数组位置映射到系列索引

+            var maxDataLength = 0;                  // 需要返回的东西:最大数据长度

+            // 计算需要显示的个数和分配位置并记在下面这个结构里

+            for (var i = 0, l = seriesArray.length; i < l; i++) {

+                serie = series[seriesArray[i]];

+                serieName = serie.name;

+                if (legend){

+                    self.selectedMap[serieName] = legend.isSelected(serieName);

+                    _sIndex2colorMap[seriesArray[i]] =

+                        legend.getColor(serieName);

+                } else {

+                    self.selectedMap[serieName] = true;

+                    _sIndex2colorMap[seriesArray[i]] =

+                        zr.getColor(seriesArray[i]);

+                }

+

+                if (self.selectedMap[serieName]) {

+                    stackKey = serie.stack || (magicStackKey + seriesArray[i]);

+                    if (typeof stackMap[stackKey] == 'undefined') {

+                        stackMap[stackKey] = dataIndex;

+                        locationMap[dataIndex] = [seriesArray[i]];

+                        dataIndex++;

+                    }

+                    else {

+                        // 已经分配了位置就推进去就行

+                        locationMap[stackMap[stackKey]].push(seriesArray[i]);

+                    }

+                }

+                // 兼职帮算一下最大长度

+                maxDataLength = Math.max(maxDataLength, serie.data.length);

+            }

+

+            /* 调试输出

+            var s = '';

+            for (var i = 0, l = maxDataLength; i < l; i++) {

+                s = '[';

+                for (var j = 0, k = locationMap.length; j < k; j++) {

+                    s +='['

+                    for (var m = 0, n = locationMap[j].length - 1; m < n; m++) {

+                        s += series[locationMap[j][m]].data[i] + ','

+                    }

+                    s += series[locationMap[j][locationMap[j].length - 1]]

+                         .data[i];

+                    s += ']'

+                }

+                s += ']';

+                console.log(s);

+            }

+            console.log(locationMap)

+            */

+

+            return {

+                locationMap : locationMap,

+                maxDataLength : maxDataLength

+            };

+        }

+

+        /**

+         * 构建类目轴为水平方向的柱形图系列

+         */

+        function _buildHorizontal(maxDataLength, locationMap) {

+            // 确定类目轴和数值轴,同一方向随便找一个即可

+            var seriesIndex = locationMap[0][0];

+            var serie = series[seriesIndex];

+            var xAxisIndex = serie.xAxisIndex;

+            var categoryAxis = component.xAxis.getAxis(xAxisIndex);

+            var yAxisIndex; // 数值轴各异

+            var valueAxis;  // 数值轴各异

+

+            var size = _mapSize(categoryAxis, locationMap);

+            var gap = size.gap;

+            var barGap = size.barGap;

+            var barWidthMap = size.barWidthMap;

+            var barWidth = size.barWidth;                   // 自适应宽度

+            var barMinHeightMap = size.barMinHeightMap;

+            var barHeight;

+

+            var x;

+            var y;

+            var lastYP; // 正向堆叠处理

+            var baseYP;

+            var lastYN; // 负向堆叠处理

+            var baseYN;

+            var barShape;

+            var data;

+            var value;

+            for (var i = 0, l = maxDataLength; i < l; i++) {

+                if (typeof categoryAxis.getNameByIndex(i) == 'undefined') {

+                    // 系列数据超出类目轴长度

+                    break;

+                }

+                x = categoryAxis.getCoordByIndex(i) - gap / 2;

+                for (var j = 0, k = locationMap.length; j < k; j++) {

+                    // 堆叠数据用第一条valueAxis

+                    yAxisIndex = series[locationMap[j][0]].yAxisIndex || 0;

+                    valueAxis = component.yAxis.getAxis(yAxisIndex);

+                    baseYP = lastYP = valueAxis.getCoord(0) - 1;

+                    baseYN = lastYN = lastYP + 2;

+                    for (var m = 0, n = locationMap[j].length; m < n; m++) {

+                        seriesIndex = locationMap[j][m];

+                        serie = series[seriesIndex];

+                        data = serie.data[i];

+                        value = typeof data != 'undefined'

+                                ? (typeof data.value != 'undefined'

+                                  ? data.value

+                                  : data)

+                                : '-';

+                        if (value == '-') {

+                            // 空数据在做完后补充拖拽提示框

+                            continue;

+                        }

+                        y = valueAxis.getCoord(value);

+                        if (value > 0) {

+                            // 正向堆叠

+                            barHeight = baseYP - y;

+                            // 非堆叠数据最小高度有效

+                            if (n == 1

+                                && barMinHeightMap[seriesIndex] > barHeight

+                            ) {

+                                barHeight = barMinHeightMap[seriesIndex];

+                            }

+                            lastYP -= barHeight;

+                            y = lastYP;

+                            lastYP -= 0.5; //白色视觉分隔线宽修正

+                        }

+                        else if (value < 0){

+                            // 负向堆叠

+                            barHeight = y - baseYN;

+                            // 非堆叠数据最小高度有效

+                            if (n == 1

+                                && barMinHeightMap[seriesIndex] > barHeight

+                            ) {

+                                barHeight = barMinHeightMap[seriesIndex];

+                            }

+                            y = lastYN;

+                            lastYN += barHeight;

+                            lastYN += 0.5; //白色视觉分隔线宽修正

+                        }

+                        else {

+                            // 0值

+                            barHeight = baseYP - y;

+                            // 最小高度无效

+                            lastYP -= barHeight;

+                            y = lastYP;

+                            lastYP -= 0.5; //白色视觉分隔线宽修正

+                        }

+

+                        barShape = _getBarItem(

+                            seriesIndex, i,

+                            categoryAxis.getNameByIndex(i),

+                            x, y,

+                            barWidthMap[seriesIndex] || barWidth,

+                            barHeight

+                        );

+                        barShape._orient = 'vertical';

+

+                        self.shapeList.push(barShape);

+                    }

+

+                    // 补充空数据的拖拽提示框

+                    for (var m = 0, n = locationMap[j].length; m < n; m++) {

+                        seriesIndex = locationMap[j][m];

+                        serie = series[seriesIndex];

+                        data = serie.data[i];

+                        value = typeof data != 'undefined'

+                                ? (typeof data.value != 'undefined'

+                                  ? data.value

+                                  : data)

+                                : '-';

+                        if (value != '-') {

+                            // 只关心空数据

+                            continue;

+                        }

+

+                        if (self.deepQuery(

+                                [data, serie, option], 'calculable'

+                            )

+                        ) {

+                            lastYP -= barMinHeightMap[seriesIndex];

+                            y = lastYP;

+

+                            barShape = _getBarItem(

+                                seriesIndex, i,

+                                categoryAxis.getNameByIndex(i),

+                                x + 1, y,

+                                (barWidthMap[seriesIndex] || barWidth) - 2,

+                                barMinHeightMap[seriesIndex]

+                            );

+                            barShape.hoverable = false;

+                            barShape.draggable = false;

+                            barShape.style.brushType = 'stroke';

+                            barShape.style.strokeColor =

+                                    serie.calculableHolderColor

+                                    || ecConfig.calculableHolderColor;

+

+                            self.shapeList.push(barShape);

+                        }

+                    }

+

+                    x += ((barWidthMap[seriesIndex] || barWidth) + barGap);

+                }

+            }

+        }

+

+        /**

+         * 构建类目轴为垂直方向的柱形图系列

+         */

+        function _buildVertical(maxDataLength, locationMap) {

+            // 确定类目轴和数值轴,同一方向随便找一个即可

+            var seriesIndex = locationMap[0][0];

+            var serie = series[seriesIndex];

+            var yAxisIndex = serie.yAxisIndex;

+            var categoryAxis = component.yAxis.getAxis(yAxisIndex);

+            var xAxisIndex; // 数值轴各异

+            var valueAxis;  // 数值轴各异

+

+            var size = _mapSize(categoryAxis, locationMap);

+            var gap = size.gap;

+            var barGap = size.barGap;

+            var barWidthMap = size.barWidthMap;

+            var barWidth = size.barWidth;                   // 自适应宽度

+            var barMinHeightMap = size.barMinHeightMap;

+            var barHeight;

+

+            var x;

+            var y;

+            var lastXP; // 正向堆叠处理

+            var baseXP;

+            var lastXN; // 负向堆叠处理

+            var baseXN;

+            var barShape;

+            var data;

+            var value;

+            for (var i = 0, l = maxDataLength; i < l; i++) {

+                if (typeof categoryAxis.getNameByIndex(i) == 'undefined') {

+                    // 系列数据超出类目轴长度

+                    break;

+                }

+                y = categoryAxis.getCoordByIndex(i) + gap / 2;

+                for (var j = 0, k = locationMap.length; j < k; j++) {

+                    // 堆叠数据用第一条valueAxis

+                    xAxisIndex = series[locationMap[j][0]].xAxisIndex || 0;

+                    valueAxis = component.xAxis.getAxis(xAxisIndex);

+                    baseXP = lastXP = valueAxis.getCoord(0) + 1;

+                    baseXN = lastXN = lastXP - 2;

+                    for (var m = 0, n = locationMap[j].length; m < n; m++) {

+                        seriesIndex = locationMap[j][m];

+                        serie = series[seriesIndex];

+                        data = serie.data[i];

+                        value = typeof data != 'undefined'

+                                ? (typeof data.value != 'undefined'

+                                  ? data.value

+                                  : data)

+                                : '-';

+                        if (value == '-') {

+                            // 空数据在做完后补充拖拽提示框

+                            continue;

+                        }

+                        x = valueAxis.getCoord(value);

+                        if (value > 0) {

+                            // 正向堆叠

+                            barHeight = x - baseXP;

+                            // 非堆叠数据最小高度有效

+                            if (n == 1

+                                && barMinHeightMap[seriesIndex] > barHeight

+                            ) {

+                                barHeight = barMinHeightMap[seriesIndex];

+                            }

+                            x = lastXP;

+                            lastXP += barHeight;

+                            lastXP += 0.5; //白色视觉分隔线宽修正

+                        }

+                        else if (value < 0){

+                            // 负向堆叠

+                            barHeight = baseXN - x;

+                            // 非堆叠数据最小高度有效

+                            if (n == 1

+                                && barMinHeightMap[seriesIndex] > barHeight

+                            ) {

+                                barHeight = barMinHeightMap[seriesIndex];

+                            }

+                            lastXN -= barHeight;

+                            x = lastXN;

+                            lastXN -= 0.5; //白色视觉分隔线宽修正

+                        }

+                        else {

+                            // 0值

+                            barHeight = x - baseXP;

+                            // 最小高度无效

+                            x = lastXP;

+                            lastXP += barHeight;

+                            lastXP += 0.5; //白色视觉分隔线宽修正

+                        }

+

+                        barShape = _getBarItem(

+                            seriesIndex, i,

+                            categoryAxis.getNameByIndex(i),

+                            x, y - (barWidthMap[seriesIndex] || barWidth),

+                            barHeight,

+                            barWidthMap[seriesIndex] || barWidth

+                        );

+                        barShape._orient = 'horizontal';

+

+                        self.shapeList.push(barShape);

+                    }

+

+                    // 补充空数据的拖拽提示框

+                    for (var m = 0, n = locationMap[j].length; m < n; m++) {

+                        seriesIndex = locationMap[j][m];

+                        serie = series[seriesIndex];

+                        data = serie.data[i];

+                        value = typeof data != 'undefined'

+                                ? (typeof data.value != 'undefined'

+                                  ? data.value

+                                  : data)

+                                : '-';

+                        if (value != '-') {

+                            // 只关心空数据

+                            continue;

+                        }

+

+                        if (self.deepQuery(

+                                [data, serie, option], 'calculable'

+                            )

+                        ) {

+                            x = lastXP;

+                            lastXP += barMinHeightMap[seriesIndex];

+

+                            barShape = _getBarItem(

+                                seriesIndex,

+                                i,

+                                categoryAxis.getNameByIndex(i),

+                                x,

+                                y + 1 - (barWidthMap[seriesIndex] || barWidth),

+                                barMinHeightMap[seriesIndex],

+                                (barWidthMap[seriesIndex] || barWidth) - 2

+                            );

+                            barShape.hoverable = false;

+                            barShape.draggable = false;

+                            barShape.style.brushType = 'stroke';

+                            barShape.style.strokeColor =

+                                    serie.calculableHolderColor

+                                    || ecConfig.calculableHolderColor;

+

+                            self.shapeList.push(barShape);

+                        }

+                    }

+

+                    y -= ((barWidthMap[seriesIndex] || barWidth) + barGap);

+                }

+            }

+        }

+        /**

+         * 我真是自找麻烦啊,为啥要允许系列级个性化最小宽度和高度啊!!!

+         * @param {CategoryAxis} categoryAxis 类目坐标轴,需要知道类目间隔大小

+         * @param {Array} locationMap 整形数据的系列索引

+         */

+        function _mapSize(categoryAxis, locationMap, ignoreUserDefined) {

+            var barWidthMap = {};

+            var barMinHeightMap = {};

+            var sBarWidth;

+            var sBarWidthCounter = 0;

+            var sBarWidthTotal = 0;

+            var sBarMinHeight;

+            var hasFound;

+

+            for (var j = 0, k = locationMap.length; j < k; j++) {

+                hasFound = false;   // 同一堆叠第一个barWidth生效

+                for (var m = 0, n = locationMap[j].length; m < n; m++) {

+                    seriesIndex = locationMap[j][m];

+                    if (!ignoreUserDefined) {

+                        if (!hasFound) {

+                            sBarWidth = self.deepQuery(

+                                [series[seriesIndex]],

+                                'barWidth'

+                            );

+                            if (typeof sBarWidth != 'undefined') {

+                                barWidthMap[seriesIndex] = sBarWidth;

+                                sBarWidthTotal += sBarWidth;

+                                sBarWidthCounter++;

+                                hasFound = true;

+                            }

+                        } else {

+                            barWidthMap[seriesIndex] = sBarWidth;   // 用找到的一个

+                        }

+                    }

+

+                    sBarMinHeight = self.deepQuery(

+                        [series[seriesIndex]],

+                        'barMinHeight'

+                    );

+                    if (typeof sBarMinHeight != 'undefined') {

+                        barMinHeightMap[seriesIndex] = sBarMinHeight;

+                    }

+                }

+            }

+

+            var gap;

+            var barWidth;

+            var barGap;

+            if (locationMap.length != sBarWidthCounter) {

+                // 至少存在一个自适应宽度的柱形图

+                gap = Math.round(categoryAxis.getGap() * 4 / 5);

+                barWidth = Math.round(

+                        ((gap - sBarWidthTotal) * 3)

+                        / (4 * (locationMap.length) - 3 * sBarWidthCounter - 1)

+                    );

+                barGap = Math.round(barWidth / 3);

+                if (barWidth < 0) {

+                    // 无法满足用户定义的宽度设计,忽略用户宽度,打回重做

+                    return _mapSize(categoryAxis, locationMap, true);

+                }

+            }

+            else {

+                // 全是自定义宽度

+                barWidth = 0;

+                barGap = Math.round((sBarWidthTotal / sBarWidthCounter) / 3);

+                gap = sBarWidthTotal + barGap * (sBarWidthCounter - 1);

+                if (Math.round(categoryAxis.getGap() * 4 / 5) < gap) {

+                    // 无法满足用户定义的宽度设计,忽略用户宽度,打回重做

+                    return _mapSize(categoryAxis, locationMap, true);

+                }

+            }

+

+

+            return {

+                barWidthMap : barWidthMap,

+                barMinHeightMap : barMinHeightMap ,

+                gap : gap,

+                barWidth : barWidth,

+                barGap : barGap

+            };

+        }

+

+        /**

+         * 生成最终图形数据

+         */

+        function _getBarItem(

+            seriesIndex, dataIndex, name, x, y, width, height

+        ) {

+            var barShape;

+            var serie = series[seriesIndex];

+            var data = serie.data[dataIndex];

+            // 多级控制

+            var defaultColor = _sIndex2colorMap[seriesIndex];

+            var normalColor = self.deepQuery(

+                [data, serie],

+                'itemStyle.normal.color'

+            );

+            var emphasisColor = self.deepQuery(

+                [data, serie],

+                'itemStyle.emphasis.color'

+            );

+

+            barShape = {

+                shape : 'rectangle',

+                zlevel : _zlevelBase,

+                clickable: true,

+                style : {

+                    x : x,

+                    y : y,

+                    width : width,

+                    height : height,

+                    brushType : 'both',

+                    color : normalColor || defaultColor,

+                    strokeColor : '#fff'

+                },

+                highlightStyle : {

+                    color : emphasisColor || normalColor || defaultColor

+                }

+            };

+

+            if (self.deepQuery(

+                    [data, serie, option],

+                    'calculable'

+                )

+            ) {

+                self.setCalculable(barShape);

+                barShape.draggable = true;

+            }

+

+            ecData.pack(

+                barShape,

+                series[seriesIndex], seriesIndex,

+                series[seriesIndex].data[dataIndex] || '-', dataIndex,

+                name

+            );

+

+            return barShape;

+        }

+

+        /**

+         * 构造函数默认执行的初始化方法,也用于创建实例后动态修改

+         * @param {Object} newZr

+         * @param {Object} newSeries

+         * @param {Object} newComponent

+         */

+        function init(newOption, newComponent) {

+            option = newOption;

+            component = newComponent;

+

+            series = option.series;

+

+            self.clear();

+            _buildShape();

+        }

+

+        /**

+         * 刷新

+         */

+        function refresh() {

+            self.clear();

+            _buildShape();

+        }

+

+        /**

+         * 动画设定

+         */

+        function animation() {

+            var duration;

+            var easing;

+            var width;

+            var height;

+            var x;

+            var y;

+            var serie;

+            var dataIndex;

+            var value;

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                if (self.shapeList[i].shape == 'rectangle') {

+                    serie = ecData.get(self.shapeList[i], 'series');

+                    dataIndex = ecData.get(self.shapeList[i], 'dataIndex');

+                    value = ecData.get(self.shapeList[i], 'value');

+                    duration = self.deepQuery(

+                        [serie, option], 'animationDuration'

+                    );

+                    easing = self.deepQuery(

+                        [serie, option], 'animationEasing'

+                    );

+

+                    if (self.shapeList[i]._orient == 'horizontal') {

+                        // 条形图

+                        width = self.shapeList[i].style.width;

+                        x = self.shapeList[i].style.x;

+                        if (value < 0) {

+                            zr.modShape(

+                                self.shapeList[i].id,

+                                {

+                                    style: {

+                                        x : x + width,

+                                        width: 0

+                                    }

+                                }

+                            );

+                            zr.animate(self.shapeList[i].id, 'style')

+                                .when(

+                                    duration + dataIndex * 100,

+                                    {

+                                        x : x,

+                                        width : width

+                                    },

+                                    easing

+                                )

+                                .start();

+                        }

+                        else {

+                            zr.modShape(

+                                self.shapeList[i].id,

+                                {

+                                    style: {

+                                        width: 0

+                                    }

+                                }

+                            );

+                            zr.animate(self.shapeList[i].id, 'style')

+                                .when(

+                                    duration + dataIndex * 100,

+                                    {

+                                        width : width

+                                    },

+                                    easing

+                                )

+                                .start();

+                        }

+                    }

+                    else {

+                        // 柱形图

+                        height = self.shapeList[i].style.height;

+                        y = self.shapeList[i].style.y;

+                        if (value < 0) {

+                            zr.modShape(

+                                self.shapeList[i].id,

+                                {

+                                    style: {

+                                        height: 0

+                                    }

+                                }

+                            );

+                            zr.animate(self.shapeList[i].id, 'style')

+                                .when(

+                                    duration + dataIndex * 100,

+                                    {

+                                        height : height

+                                    },

+                                    easing

+                                )

+                                .start();

+                        }

+                        else {

+                            zr.modShape(

+                                self.shapeList[i].id,

+                                {

+                                    style: {

+                                        y: y + height,

+                                        height: 0

+                                    }

+                                }

+                            );

+                            zr.animate(self.shapeList[i].id, 'style')

+                                .when(

+                                    duration + dataIndex * 100,

+                                    {

+                                        y : y,

+                                        height : height

+                                    },

+                                    easing

+                                )

+                                .start();

+                        }

+                    }

+                }

+            }

+        }

+

+        self.init = init;

+        self.refresh = refresh;

+        self.animation = animation;

+

+        init(option, component);

+    }

+

+    return Bar;

+});
\ No newline at end of file
diff --git a/src/chart/calculableBase.js b/src/chart/calculableBase.js
new file mode 100644
index 0000000..b3a6283
--- /dev/null
+++ b/src/chart/calculableBase.js
@@ -0,0 +1,151 @@
+/**

+ * echarts组件基类

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function(require) {

+    function Base(zr, option){

+        var ecData = require('../util/ecData');

+

+        var zrUtil = require('zrender/tool/util');

+        var self = this;

+

+        self.selectedMap = {};

+

+        self.shapeHandler = {

+            onclick : function() {

+                self.isClick = true;

+            },

+            ondragover : function (param) {

+                // 返回触发可计算特性的图形提示

+                var calculableShape = zrUtil.clone(param.target);

+                calculableShape.highlightStyle = {

+                    text : '',

+                    r : calculableShape.style.r + 5,

+                    brushType : 'stroke',

+                    strokeColor : self.zr.getCalculableColor(),

+                    lineWidth : (calculableShape.style.lineWidth || 1) + 12

+                };

+                self.zr.addHoverShape(calculableShape);

+            },

+

+            ondrop : function (param) {

+                // 排除一些非数据的拖拽进入

+                if (typeof ecData.get(param.dragged, 'data') != 'undefined') {

+                    self.isDrop = true;

+                }

+            },

+

+            ondragend : function () {

+                self.isDragend = true;

+            }

+        };

+

+        function setCalculable(shape) {

+            shape.ondragover = self.shapeHandler.ondragover;

+            shape.ondragend = self.shapeHandler.ondragend;

+            shape.ondrop = self.shapeHandler.ondrop;

+            return shape;

+        }

+

+        /**

+         * 数据项被拖拽进来

+         */

+        function ondrop(param, status) {

+            if (!self.isDrop || !param.target) {

+                // 没有在当前实例上发生拖拽行为则直接返回

+                return;

+            }

+

+            var target = param.target;      // 拖拽安放目标

+            var dragged = param.dragged;    // 当前被拖拽的图形对象

+

+            var seriesIndex = ecData.get(target, 'seriesIndex');

+            var dataIndex = ecData.get(target, 'dataIndex');

+

+            // 落到bar上,数据被拖拽到某个数据项上,数据修改

+            var data = option.series[seriesIndex].data[dataIndex] || '-';

+            if (data.value) {

+                if (data.value != '-') {

+                    option.series[seriesIndex].data[dataIndex].value +=

+                        ecData.get(dragged, 'value');

+                }

+                else {

+                    option.series[seriesIndex].data[dataIndex].value =

+                        ecData.get(dragged, 'value');

+                }

+            }

+            else {

+                if (data != '-') {

+                    option.series[seriesIndex].data[dataIndex] +=

+                        ecData.get(dragged, 'value');

+                }

+                else {

+                    option.series[seriesIndex].data[dataIndex] =

+                        ecData.get(dragged, 'value');

+                }

+            }

+

+            // 别status = {}赋值啊!!

+            status.dragIn = status.dragIn || true;

+

+            // 处理完拖拽事件后复位

+            self.isDrop = false;

+

+            return;

+        }

+

+        /**

+         * 数据项被拖拽出去

+         */

+        function ondragend(param, status) {

+            if (!self.isDragend || !param.target) {

+                // 没有在当前实例上发生拖拽行为则直接返回

+                return;

+            }

+            var target = param.target;      // 被拖拽图形元素

+

+            var seriesIndex = ecData.get(target, 'seriesIndex');

+            var dataIndex = ecData.get(target, 'dataIndex');

+

+            // 被拖拽的图形是折线图bar,删除被拖拽走的数据

+            option.series[seriesIndex].data[dataIndex] = '-';

+

+            // 别status = {}赋值啊!!

+            status.dragOut = true;

+            status.needRefresh = true;

+

+            // 处理完拖拽事件后复位

+            self.isDragend = false;

+

+            return;

+        }

+

+        /**

+         * 图例选择

+         */

+        function onlegendSelected(param, status) {

+            var legendSelected = param.selected;

+            for (var itemName in self.selectedMap) {

+                if (self.selectedMap[itemName] != legendSelected[itemName]) {

+                    // 有一项不一致都需要重绘

+                    status.needRefresh = true;

+                    return;

+                }

+            }

+        }

+

+        /**

+         * 基类方法

+         */

+        self.setCalculable = setCalculable;

+        self.ondrop = ondrop;

+        self.ondragend = ondragend;

+        self.onlegendSelected = onlegendSelected;

+    }

+

+    return Base;

+});

diff --git a/src/chart/island.js b/src/chart/island.js
new file mode 100644
index 0000000..86bea4b
--- /dev/null
+++ b/src/chart/island.js
@@ -0,0 +1,211 @@
+/**

+ * echarts组件:孤岛数据

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function (require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} option 图表选项

+     */

+    function Island(messageCenter, zr) {

+        // 基类装饰

+        var ComponentBase = require('../component/base');

+        ComponentBase.call(this, zr);

+        // 可计算特性装饰

+        var CalculableBase = require('./calculableBase');

+        CalculableBase.call(this, zr);

+

+        var ecConfig = require('../config');

+        var ecData = require('../util/ecData');

+

+        var zrEvent = require('zrender/tool/event');

+

+        var self = this;

+        self.type = ecConfig.CHART_TYPE_ISLAND;

+        var option;

+

+        var _zlevelBase = self.getZlevelBase();

+        var _nameConnector;

+        var _valueConnector;

+

+        /**

+         * 孤岛合并

+         *

+         * @param {string} tarShapeIndex 目标索引

+         * @param {Object} srcShape 源目标,合入目标后删除

+         */

+        function _combine(tarShape, srcShape) {

+            var zrColor = require('zrender/tool/color');

+            var value = ecData.get(tarShape, 'value')

+                        + ecData.get(srcShape, 'value');

+            var name = ecData.get(tarShape, 'name')

+                       + _nameConnector

+                       + ecData.get(srcShape, 'name');

+

+            tarShape.style.text = name + _valueConnector + value;

+

+            ecData.set(tarShape, 'value', value);

+            ecData.set(tarShape, 'name', name);

+            tarShape.style.r = option.island.r;

+            tarShape.style.color = zrColor.mix(

+                tarShape.style.color,

+                srcShape.style.color

+            );

+        }

+

+        function render(newOption) {

+            newOption.island = self.reformOption(newOption.island);

+            option = newOption;

+

+            _nameConnector = option.nameConnector;

+            _valueConnector = option.valueConnector;

+

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                zr.addShape(self.shapeList[i]);

+            }

+        }

+

+        function add(shape) {

+            var name = ecData.get(shape, 'name');

+            var value = ecData.get(shape, 'value');

+            var seriesName = typeof ecData.get(shape, 'series') != 'undefined'

+                             ? ecData.get(shape, 'series').name

+                             : '';

+            var font = self.getFont(option.island.textStyle);

+            var islandShape = {

+                shape : 'circle',

+                id : zr.newShapeId(self.type),

+                zlevel : _zlevelBase,

+                style : {

+                    x : shape.style.x,

+                    y : shape.style.y,

+                    r : option.island.r,

+                    color : shape.style.color || shape.style.strokeColor,

+                    text : name + _valueConnector + value,

+                    textFont : font

+                },

+                draggable : true,

+                hoverable : true,

+                onmousewheel : self.shapeHandler.onmousewheel,

+                _type : 'island'

+            };

+            self.setCalculable(islandShape);

+            ecData.pack(

+                islandShape,

+                {name:seriesName}, -1,

+                value, -1,

+                name

+            );

+            self.shapeList.push(islandShape);

+            zr.addShape(islandShape);

+        }

+

+        function del(shape) {

+            zr.delShape(shape.id);

+            var newShapeList = [];

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                if (self.shapeList[i].id != shape.id) {

+                    newShapeList.push(self.shapeList[i]);

+                }

+            }

+            self.shapeList = newShapeList;

+        }

+

+        /**

+         * 数据项被拖拽进来, 重载基类方法

+         */

+        function ondrop(param, status) {

+            if (!self.isDrop || !param.target) {

+                // 没有在当前实例上发生拖拽行为则直接返回

+                return;

+            }

+            // 拖拽产生孤岛数据合并

+            var target = param.target;      // 拖拽安放目标

+            var dragged = param.dragged;    // 当前被拖拽的图形对象

+

+            _combine(target, dragged);

+            zr.modShape(target.id, target);

+

+            status.dragIn = true;

+

+            // 处理完拖拽事件后复位

+            self.isDrop = false;

+

+            return;

+        }

+

+        /**

+         * 数据项被拖拽出去, 重载基类方法

+         */

+        function ondragend(param, status) {

+            var target = param.target;      // 拖拽安放目标

+            if (!self.isDragend) {

+                // 拖拽的不是孤岛数据,如果没有图表接受孤岛数据,需要新增孤岛数据

+                if (!status.dragIn) {

+                    target.style.x = zrEvent.getX(param.event);

+                    target.style.y = zrEvent.getY(param.event);

+                    add(target);

+                    status.needRefresh = true;

+                }

+            }

+            else {

+                // 拖拽的是孤岛数据,如果有图表接受了孤岛数据,需要删除孤岛数据

+                if (status.dragIn) {

+                    del(target);

+                    status.needRefresh = true;

+                }

+            }

+

+            // 处理完拖拽事件后复位

+            self.isDragend = false;

+

+            return;

+        }

+

+        /**

+         * 滚轮改变孤岛数据值

+         */

+        self.shapeHandler.onmousewheel = function(param) {

+            var shape = param.target;

+

+            var event = param.event;

+            var delta = zrEvent.getDelta(event);

+            delta = delta > 0 ? (-1) : 1;

+            shape.style.r -= delta;

+            shape.style.r = shape.style.r < 5 ? 5 : shape.style.r;

+

+            var value = ecData.get(shape, 'value');

+            var dvalue = value * option.island.calculateStep;

+            if (dvalue > 1) {

+                value = Math.round(value - dvalue * delta);

+            }

+            else {

+                value = (value - dvalue * delta).toFixed(2) - 0;

+            }

+

+            var name = ecData.get(shape, 'name');

+            shape.style.text = name + ':' + value;

+

+            ecData.set(shape, 'value', value);

+            ecData.set(shape, 'name', name);

+

+            zr.modShape(shape.id, shape);

+            zr.refresh();

+            zrEvent.stop(event);

+        };

+

+        self.render = render;

+        self.add = add;

+        self.del = del;

+        self.ondrop = ondrop;

+        self.ondragend = ondragend;

+    }

+

+    return Island;

+});
\ No newline at end of file
diff --git a/src/chart/line.js b/src/chart/line.js
new file mode 100644
index 0000000..9d523a0
--- /dev/null
+++ b/src/chart/line.js
@@ -0,0 +1,804 @@
+/**

+ * echarts图表类:折线图

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function(require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} series 数据

+     * @param {Object} component 组件

+     */

+    function Line(messageCenter, zr, option, component){

+        // 基类装饰

+        var ComponentBase = require('../component/base');

+        ComponentBase.call(this, zr);

+        // 可计算特性装饰

+        var CalculableBase = require('./calculableBase');

+        CalculableBase.call(this, zr, option);

+

+        var ecConfig = require('../config');

+        var ecData = require('../util/ecData');

+

+        var zrColor = require('zrender/tool/color');

+

+        var self = this;

+        self.type = ecConfig.CHART_TYPE_LINE;

+

+        var series;                 // 共享数据源,不要修改跟自己无关的项

+

+        var _zlevelBase = self.getZlevelBase();

+

+        var _sIndex2ColorMap = {};  // series默认颜色索引,seriesIndex索引到color

+        var _brokenPoint = [

+              'circle', 'rectangle', 'triangle', 'diamond',

+              'emptyCircle', 'emptyRectangle', 'emptyTriangle', 'emptyDiamond'

+            ];

+        var _sIndex2ShapeMap = {};  // series拐点图形类型,seriesIndex索引到shape type

+

+        function _buildShape() {

+            self.selectedMap = {};

+

+            // 水平垂直双向series索引 ,position索引到seriesIndex

+            var _position2sIndexMap = {

+                top : [],

+                bottom : [],

+                left : [],

+                right : []

+            };

+            var xAxisIndex;

+            var yAxisIndex;

+            var xAxis;

+            var yAxis;

+            for (var i = 0, l = series.length; i < l; i++) {

+                if (series[i].type == ecConfig.CHART_TYPE_LINE) {

+                    series[i] = self.reformOption(series[i]);

+                    xAxisIndex = series[i].xAxisIndex;

+                    yAxisIndex = series[i].yAxisIndex;

+                    xAxis = component.xAxis.getAxis(xAxisIndex);

+                    yAxis = component.yAxis.getAxis(yAxisIndex);

+                    if (xAxis.type == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY

+                    ) {

+                        _position2sIndexMap[xAxis.getPosition()].push(i);

+                    }

+                    else if (yAxis.type == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY

+                    ) {

+                        _position2sIndexMap[yAxis.getPosition()].push(i);

+                    }

+                }

+            }

+            //console.log(_position2sIndexMap)

+            for (var position in _position2sIndexMap) {

+                if (_position2sIndexMap[position].length > 0) {

+                    _buildSinglePosition(

+                        position, _position2sIndexMap[position]

+                    );

+                }

+            }

+

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                self.shapeList[i].id = zr.newShapeId(self.type);

+                zr.addShape(self.shapeList[i]);

+            }

+        }

+

+        /**

+         * 构建单个方向上的折线图

+         *

+         * @param {number} seriesIndex 系列索引

+         */

+        function _buildSinglePosition(position, seriesArray) {

+            var mapData = _mapData(seriesArray);

+            var locationMap = mapData.locationMap;

+            var maxDataLength = mapData.maxDataLength;

+

+            if (maxDataLength === 0 || locationMap.length === 0) {

+                return;

+            }

+

+            switch (position) {

+                case 'bottom' :

+                case 'top' :

+                    _buildHorizontal(maxDataLength, locationMap);

+                    break;

+                case 'left' :

+                case 'right' :

+                    _buildVertical(maxDataLength, locationMap);

+                    break;

+            }

+        }

+

+        /**

+         * 数据整形

+         * 数组位置映射到系列索引

+         */

+        function _mapData(seriesArray) {

+            var serie;                              // 临时映射变量

+            var dataIndex = 0;                      // 堆叠数据所在位置映射

+            var stackMap = {};                      // 堆叠数据位置映射,堆叠组在二维中的第几项

+            var magicStackKey = '__kener__stack__'; // 堆叠命名,非堆叠数据安单一堆叠处理

+            var stackKey;                           // 临时映射变量

+            var serieName;                          // 临时映射变量

+            var legend = component.legend;

+            var locationMap = [];                   // 需要返回的东西:数组位置映射到系列索引

+            var maxDataLength = 0;                  // 需要返回的东西:最大数据长度

+            // 计算需要显示的个数和分配位置并记在下面这个结构里

+            for (var i = 0, l = seriesArray.length; i < l; i++) {

+                serie = series[seriesArray[i]];

+                serieName = serie.name;

+                if (legend){

+                    self.selectedMap[serieName] = legend.isSelected(serieName);

+                    _sIndex2ColorMap[seriesArray[i]]

+                        = legend.getColor(serieName);

+                } else {

+                    self.selectedMap[serieName] = true;

+                    _sIndex2ColorMap[seriesArray[i]]

+                        = zr.getColor(seriesArray[i]);

+                }

+                _sIndex2ShapeMap[seriesArray[i]]

+                    = _sIndex2ShapeMap[seriesArray[i]]

+                      || self.deepQuery(

+                             [serie],

+                             'brokenPoint'

+                         )

+                      || _brokenPoint[i % _brokenPoint.length];

+

+                if (self.selectedMap[serieName]) {

+                    stackKey = serie.stack || (magicStackKey + seriesArray[i]);

+                    if (typeof stackMap[stackKey] == 'undefined') {

+                        stackMap[stackKey] = dataIndex;

+                        locationMap[dataIndex] = [seriesArray[i]];

+                        dataIndex++;

+                    }

+                    else {

+                        // 已经分配了位置就推进去就行

+                        locationMap[stackMap[stackKey]].push(seriesArray[i]);

+                    }

+                }

+                // 兼职帮算一下最大长度

+                maxDataLength = Math.max(maxDataLength, serie.data.length);

+            }

+

+            /* 调试输出

+            var s = '';

+            for (var i = 0, l = maxDataLength; i < l; i++) {

+                s = '[';

+                for (var j = 0, k = locationMap.length; j < k; j++) {

+                    s +='['

+                    for (var m = 0, n = locationMap[j].length - 1; m < n; m++) {

+                        s += series[locationMap[j][m]].data[i] + ','

+                    }

+                    s += series[locationMap[j][locationMap[j].length - 1]]

+                         .data[i];

+                    s += ']'

+                }

+                s += ']';

+                console.log(s);

+            }

+            console.log(locationMap)

+            */

+

+            return {

+                locationMap : locationMap,

+                maxDataLength : maxDataLength

+            };

+        }

+

+        /**

+         * 构建类目轴为水平方向的折线图系列

+         */

+        function _buildHorizontal(maxDataLength, locationMap) {

+            // 确定类目轴和数值轴,同一方向随便找一个即可

+            var seriesIndex = locationMap[0][0];

+            var serie = series[seriesIndex];

+            var xAxisIndex = serie.xAxisIndex;

+            var categoryAxis = component.xAxis.getAxis(xAxisIndex);

+            var yAxisIndex; // 数值轴各异

+            var valueAxis;  // 数值轴各异

+

+            var x;

+            var y;

+            var lastYP; // 正向堆叠处理

+            var baseYP;

+            var lastYN; // 负向堆叠处理

+            var baseYN;

+            var finalPLMap = {}; // 完成的point list(PL)

+            var curPLMap = {};   // 正在记录的point list(PL)

+            var data;

+            var value;

+            for (var i = 0, l = maxDataLength; i < l; i++) {

+                if (typeof categoryAxis.getNameByIndex(i) == 'undefined') {

+                    // 系列数据超出类目轴长度

+                    break;

+                }

+                x = categoryAxis.getCoordByIndex(i);

+                for (var j = 0, k = locationMap.length; j < k; j++) {

+                    // 堆叠数据用第一条valueAxis

+                    yAxisIndex = series[locationMap[j][0]].yAxisIndex || 0;

+                    valueAxis = component.yAxis.getAxis(yAxisIndex);

+                    baseYP = lastYP = baseYN = lastYN = valueAxis.getCoord(0);

+                    for (var m = 0, n = locationMap[j].length; m < n; m++) {

+                        seriesIndex = locationMap[j][m];

+                        serie = series[seriesIndex];

+                        data = serie.data[i];

+                        value = typeof data != 'undefined'

+                                ? (typeof data.value != 'undefined'

+                                  ? data.value

+                                  : data)

+                                : '-';

+                        curPLMap[seriesIndex] = curPLMap[seriesIndex] || [];

+                        if (value == '-') {

+                            // 空数据则把正在记录的curPLMap添加到finalPLMap中

+                            if (curPLMap[seriesIndex].length > 0) {

+                                finalPLMap[seriesIndex] =

+                                    finalPLMap[seriesIndex] || [];

+

+                                finalPLMap[seriesIndex].push(

+                                    curPLMap[seriesIndex]

+                                );

+

+                                curPLMap[seriesIndex] = [];

+                            }

+                            continue;

+                        }

+                        y = valueAxis.getCoord(value);

+                        if (value >= 0) {

+                            // 正向堆叠

+                            lastYP -= (baseYP - y);

+                            y = lastYP;

+                        }

+                        else if (value < 0){

+                            // 负向堆叠

+                            lastYN += y - baseYN;

+                            y = lastYN;

+                        }

+                        curPLMap[seriesIndex].push(

+                            [x, y, i, categoryAxis.getNameByIndex(i), x, baseYP]

+                        );

+                    }

+                }

+                // 补充空数据的拖拽提示

+                lastYP = component.grid.getY();

+                var brokenPointSize;

+                for (var j = 0, k = locationMap.length; j < k; j++) {

+                    for (var m = 0, n = locationMap[j].length; m < n; m++) {

+                        seriesIndex = locationMap[j][m];

+                        serie = series[seriesIndex];

+                        data = serie.data[i];

+                        value = typeof data != 'undefined'

+                                ? (typeof data.value != 'undefined'

+                                  ? data.value

+                                  : data)

+                                : '-';

+                        if (value != '-') {

+                            // 只关心空数据

+                            continue;

+                        }

+                        if (self.deepQuery(

+                                [data, serie, option], 'calculable'

+                            )

+                        ) {

+                            brokenPointSize = self.deepQuery(

+                                [data, serie],

+                                'brokenPointSize'

+                            );

+                            lastYP += brokenPointSize * 2 + 2;

+                            y = lastYP;

+                            self.shapeList.push(_getCalculableItem(

+                                seriesIndex, i, categoryAxis.getNameByIndex(i),

+                                x, y

+                            ));

+                        }

+                    }

+                }

+            }

+

+            // 把剩余未完成的curPLMap全部添加到finalPLMap中

+            for (var sId in curPLMap) {

+                if (curPLMap[sId].length > 0) {

+                    finalPLMap[sId] = finalPLMap[sId] || [];

+                    finalPLMap[sId].push(curPLMap[sId]);

+                    curPLMap[sId] = [];

+                }

+            }

+            _buildBorkenLine(finalPLMap, categoryAxis, 'horizontal');

+        }

+

+        /**

+         * 构建类目轴为垂直方向的折线图系列

+         */

+        function _buildVertical(maxDataLength, locationMap) {

+            // 确定类目轴和数值轴,同一方向随便找一个即可

+            var seriesIndex = locationMap[0][0];

+            var serie = series[seriesIndex];

+            var yAxisIndex = serie.yAxisIndex;

+            var categoryAxis = component.yAxis.getAxis(yAxisIndex);

+            var xAxisIndex; // 数值轴各异

+            var valueAxis;  // 数值轴各异

+

+            var x;

+            var y;

+            var lastXP; // 正向堆叠处理

+            var baseXP;

+            var lastXN; // 负向堆叠处理

+            var baseXN;

+            var finalPLMap = {}; // 完成的point list(PL)

+            var curPLMap = {};   // 正在记录的point list(PL)

+            var data;

+            var value;

+            for (var i = 0, l = maxDataLength; i < l; i++) {

+                if (typeof categoryAxis.getNameByIndex(i) == 'undefined') {

+                    // 系列数据超出类目轴长度

+                    break;

+                }

+                y = categoryAxis.getCoordByIndex(i);

+                for (var j = 0, k = locationMap.length; j < k; j++) {

+                    // 堆叠数据用第一条valueAxis

+                    xAxisIndex = series[locationMap[j][0]].xAxisIndex || 0;

+                    valueAxis = component.xAxis.getAxis(xAxisIndex);

+                    baseXP = lastXP = baseXN = lastXN = valueAxis.getCoord(0);

+                    for (var m = 0, n = locationMap[j].length; m < n; m++) {

+                        seriesIndex = locationMap[j][m];

+                        serie = series[seriesIndex];

+                        data = serie.data[i];

+                        value = typeof data != 'undefined'

+                                ? (typeof data.value != 'undefined'

+                                  ? data.value

+                                  : data)

+                                : '-';

+                        curPLMap[seriesIndex] = curPLMap[seriesIndex] || [];

+                        if (value == '-') {

+                            // 空数据则把正在记录的curPLMap添加到finalPLMap中

+                            if (curPLMap[seriesIndex].length > 0) {

+                                finalPLMap[seriesIndex] =

+                                    finalPLMap[seriesIndex] || [];

+

+                                finalPLMap[seriesIndex].push(

+                                    curPLMap[seriesIndex]

+                                );

+

+                                curPLMap[seriesIndex] = [];

+                            }

+                            continue;

+                        }

+                        x = valueAxis.getCoord(value);

+                        if (value >= 0) {

+                            // 正向堆叠

+                            lastXP += x - baseXP;

+                            x = lastXP;

+                        }

+                        else if (value < 0){

+                            // 负向堆叠

+                            lastXN -= baseXN - x;

+                            x = lastXN;

+                        }

+                        curPLMap[seriesIndex].push(

+                            [x, y, i, categoryAxis.getNameByIndex(i), baseXP, y]

+                        );

+                    }

+                }

+                // 补充空数据的拖拽提示

+                lastXP = component.grid.getXend();

+                var brokenPointSize;

+                for (var j = 0, k = locationMap.length; j < k; j++) {

+                    for (var m = 0, n = locationMap[j].length; m < n; m++) {

+                        seriesIndex = locationMap[j][m];

+                        serie = series[seriesIndex];

+                        data = serie.data[i];

+                        value = typeof data != 'undefined'

+                                ? (typeof data.value != 'undefined'

+                                  ? data.value

+                                  : data)

+                                : '-';

+                        if (value != '-') {

+                            // 只关心空数据

+                            continue;

+                        }

+                        if (self.deepQuery(

+                                [data, serie, option], 'calculable'

+                            )

+                        ) {

+                            brokenPointSize = self.deepQuery(

+                                [data, serie],

+                                'brokenPointSize'

+                            );

+                            lastXP -= brokenPointSize * 2 + 2;

+                            x = lastXP;

+                            self.shapeList.push(_getCalculableItem(

+                                seriesIndex, i, categoryAxis.getNameByIndex(i),

+                                x, y

+                            ));

+                        }

+                    }

+                }

+            }

+

+            // 把剩余未完成的curPLMap全部添加到finalPLMap中

+            for (var sId in curPLMap) {

+                if (curPLMap[sId].length > 0) {

+                    finalPLMap[sId] = finalPLMap[sId] || [];

+                    finalPLMap[sId].push(curPLMap[sId]);

+                    curPLMap[sId] = [];

+                }

+            }

+            //console.log(finalPLMap);

+            _buildBorkenLine(finalPLMap, categoryAxis, 'vertical');

+        }

+

+        /**

+         * 生成折线和折线上的拐点

+         */

+        function _buildBorkenLine(pointList, categoryAxis, orient) {

+            var defaultColor;

+

+            // 折线相关

+            var lineWidth;

+            var lineType;

+            var lineColor;

+            var normalColor;

+            var emphasisColor;

+

+            // 填充相关

+            var isFill;

+            var fillNormalColor;

+

+            var serie;

+            var data;

+            var seriesPL;

+            var singlePL;

+

+            // 堆叠层叠需求,反顺序构建

+            for (var seriesIndex = series.length - 1;

+                seriesIndex >= 0;

+                seriesIndex--

+            ) {

+                serie = series[seriesIndex];

+                seriesPL = pointList[seriesIndex];

+                if (serie.type == ecConfig.CHART_TYPE_LINE

+                    && typeof seriesPL != 'undefined'

+                ) {

+                    defaultColor = _sIndex2ColorMap[seriesIndex];

+                    // 多级控制

+                    lineWidth = self.deepQuery(

+                        [serie], 'itemStyle.normal.lineStyle.width'

+                    );

+                    lineType = self.deepQuery(

+                        [serie], 'itemStyle.normal.lineStyle.type'

+                    );

+                    lineColor = self.deepQuery(

+                        [serie], 'itemStyle.normal.lineStyle.color'

+                    );

+                    normalColor = self.deepQuery(

+                        [serie], 'itemStyle.normal.color'

+                    );

+                    emphasisColor = self.deepQuery(

+                        [serie], 'itemStyle.emphasis.color'

+                    );

+

+                    isFill = typeof self.deepQuery(

+                        [serie], 'itemStyle.normal.areaStyle'

+                    ) != 'undefined';

+

+                    fillNormalColor = self.deepQuery(

+                        [serie], 'itemStyle.normal.areaStyle.color'

+                    );

+

+                    for (var i = 0, l = seriesPL.length; i < l; i++) {

+                        singlePL = seriesPL[i];

+                        for (var j = 0, k = singlePL.length; j < k; j++) {

+                            data = serie.data[singlePL[j][2]];

+                            if ((categoryAxis.isMainAxis(singlePL[j][2]) // 主轴

+                                 && self.deepQuery(                      // 非空

+                                        [data, serie], 'brokenPoint'

+                                    ) != 'none'

+                                )

+                                || self.deepQuery(                      // 可计算

+                                        [data, serie, option],

+                                        'calculable'

+                                   )

+                            ) {

+                                self.shapeList.push(_getBrokenPoint(

+                                    seriesIndex,

+                                    singlePL[j][2], // dataIndex

+                                    singlePL[j][3], // name

+                                    singlePL[j][0], // x

+                                    singlePL[j][1], // y

+                                    self.deepQuery(

+                                        [data], 'itemStyle.normal.color'

+                                    ) || normalColor

+                                      || defaultColor,

+                                    self.deepQuery(

+                                        [data], 'itemStyle.emphasis.color'

+                                    ) || emphasisColor

+                                      || normalColor

+                                      || defaultColor

+                                ));

+                            }

+

+                        }

+                        if (isFill) {

+                            // 区域图添加垂直两点

+                            singlePL.push([

+                                singlePL[singlePL.length - 1][4],

+                                singlePL[singlePL.length - 1][5] - 2

+                            ]);

+                            singlePL.push([

+                                singlePL[0][4],

+                                singlePL[0][5] - 2

+                            ]);

+                            self.shapeList.push({

+                                shape : 'polygon',

+                                zlevel : _zlevelBase,

+                                style : {

+                                    pointList : singlePL,

+                                    brushType : 'both',

+                                    strokeColor : lineColor

+                                                  || normalColor

+                                                  || defaultColor,

+                                    color : fillNormalColor

+                                            ? fillNormalColor

+                                            : zrColor.alpha(defaultColor,0.5),

+                                    lineWidth : lineWidth,

+                                    lineType : lineType

+                                },

+                                hoverable : false,

+                                _main : true,

+                                _serie : serie,

+                                _orient : orient

+                            });

+                        }

+                        else {

+                            // 折线图

+                            self.shapeList.push({

+                                shape : 'brokenLine',

+                                zlevel : _zlevelBase,

+                                style : {

+                                    pointList : singlePL,

+                                    strokeColor : lineColor

+                                                  || normalColor

+                                                  || defaultColor,

+                                    lineWidth : lineWidth,

+                                    lineType : lineType

+                                },

+                                hoverable : false,

+                                _main : true,

+                                _serie : serie,

+                                _orient : orient

+                            });

+                        }

+                    }

+            }

+            }

+        }

+

+        /**

+         * 生成空数据所需的可计算提示图形

+         */

+        function _getCalculableItem(seriesIndex, dataIndex, name, x, y) {

+            var color = series[seriesIndex].calculableHolderColor

+                        || ecConfig.calculableHolderColor;

+

+            var itemShape = _getBrokenPoint(

+                seriesIndex, dataIndex, name,

+                x, y,

+                color,

+                _sIndex2ColorMap[seriesIndex]

+            );

+

+            itemShape.hoverable = false;

+            itemShape.draggable = false;

+            itemShape.highlightStyle.lineWidth = 20;

+

+            return itemShape;

+        }

+

+        /**

+         * 生成折线图上的拐点图形

+         */

+        function _getBrokenPoint(

+            seriesIndex, dataIndex, name, x, y, normalColor, emphasisColor

+        ) {

+            var serie = series[seriesIndex];

+            var data = serie.data[dataIndex];

+            var brokenPoint = self.deepQuery([data], 'brokenPoint')

+                              || _sIndex2ShapeMap[seriesIndex]

+                              || 'cricle';

+            var brokenPointSize = self.deepQuery(

+                [data, serie],

+                'brokenPointSize'

+            );

+

+            var itemShape;

+            switch (brokenPoint) {

+                case 'circle' :

+                case 'emptyCircle' :

+                    itemShape = {

+                        shape : 'circle',

+                        style : {

+                            x : x,

+                            y : y,

+                            r : brokenPointSize,

+                            brushType : brokenPoint == 'circle'

+                                        ? 'fill' : 'stroke'

+                        }

+                    };

+                    break;

+                case 'rectangle' :

+                case 'emptyRectangle' :

+                    itemShape = {

+                        shape : 'rectangle',

+                        style : {

+                            x : x - brokenPointSize,

+                            y : y - brokenPointSize,

+                            width : brokenPointSize * 2,

+                            height : brokenPointSize * 2,

+                            brushType : brokenPoint == 'rectangle'

+                                        ? 'fill' : 'stroke'

+                        }

+                    };

+                    break;

+                case 'triangle' :

+                case 'emptyTriangle' :

+                    itemShape = {

+                        shape : 'polygon',

+                        style : {

+                            pointList : [

+                                [x, y - brokenPointSize],

+                                [x + brokenPointSize, y + brokenPointSize],

+                                [x - brokenPointSize, y + brokenPointSize]

+                            ],

+                            brushType : brokenPoint == 'triangle'

+                                        ? 'fill' : 'stroke'

+                        }

+                    };

+                    break;

+                case 'diamond' :

+                case 'emptyDiamond' :

+                    itemShape = {

+                        shape : 'polygon',

+                        style : {

+                            pointList : [

+                                [x, y - brokenPointSize],

+                                [x + brokenPointSize, y],

+                                [x, y + brokenPointSize],

+                                [x - brokenPointSize, y]

+                            ],

+                            brushType : brokenPoint == 'diamond'

+                                        ? 'fill' : 'stroke'

+                        }

+                    };

+                    break;

+                default:

+                    itemShape = {

+                        shape : 'circle',

+                        style : {

+                            x : x,

+                            y : y,

+                            r : brokenPointSize,

+                            brushType : 'fill'

+                        }

+                    };

+                    break;

+            }

+            itemShape.clickable = true;

+            itemShape.zlevel = _zlevelBase + 1;

+            itemShape.style.color = normalColor;

+            itemShape.style.strokeColor = normalColor;

+            itemShape.highlightStyle = {

+                color : emphasisColor,

+                strokeColor : emphasisColor

+            };

+

+            if (self.deepQuery([data, serie, option], 'calculable')) {

+                self.setCalculable(itemShape);

+                itemShape.draggable = true;

+            }

+

+            ecData.pack(

+                itemShape,

+                series[seriesIndex], seriesIndex,

+                series[seriesIndex].data[dataIndex] || '-', dataIndex,

+                name

+            );

+

+            itemShape._x = x;

+            itemShape._y = y;

+

+            return itemShape;

+        }

+

+        /**

+         * 构造函数默认执行的初始化方法,也用于创建实例后动态修改

+         * @param {Object} newZr

+         * @param {Object} newSeries

+         * @param {Object} newComponent

+         */

+        function init(newOption, newComponent) {

+            option = newOption;

+            component = newComponent;

+

+            series = option.series;

+

+            self.clear();

+            _buildShape();

+        }

+

+        /**

+         * 刷新

+         */

+        function refresh() {

+            self.clear();

+            _buildShape();

+        }

+

+        /**

+         * 动画设定

+         */

+        function animation() {

+            var duration = self.deepQuery([option], 'animationDuration');

+            var easing = self.deepQuery([option], 'animationEasing');

+            var x;

+            var y;

+            var serie;

+            var dataIndex = 0;

+

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                if (self.shapeList[i]._main) {

+                    serie = self.shapeList[i]._serie;

+                    dataIndex += 1;

+                    x = self.shapeList[i].style.pointList[0][0];

+                    y = self.shapeList[i].style.pointList[0][1];

+                    if (self.shapeList[i]._orient == 'horizontal') {

+                        zr.modShape(self.shapeList[i].id, {

+                            scale : [0, 1, x, y]

+                        });

+                    }

+                    else {

+                        zr.modShape(self.shapeList[i].id, {

+                            scale : [1, 0, x, y]

+                        });

+                    }

+                    zr.animate(self.shapeList[i].id, '')

+                        .when(

+                            (self.deepQuery([serie],'animationDuration')

+                            || duration)

+                            + dataIndex * 100,

+

+                            {scale : [1, 1, x, y]},

+

+                            (self.deepQuery([serie], 'animationEasing')

+                            || easing)

+                        )

+                        .start();

+                }

+                else {

+                    x = self.shapeList[i]._x || 0;

+                    y = self.shapeList[i]._y || 0;

+                    zr.modShape(self.shapeList[i].id, {

+                        scale : [0, 0, x, y]

+                    });

+                    zr.animate(self.shapeList[i].id, '')

+                        .when(

+                            duration,

+                            {scale : [1, 1, x, y]},

+                            'QuinticOut'

+                        )

+                        .start();

+                }

+            }

+        }

+

+        self.init = init;

+        self.refresh = refresh;

+        self.animation = animation;

+

+        init(option, component);

+    }

+

+    return Line;

+});
\ No newline at end of file
diff --git a/src/chart/pie.js b/src/chart/pie.js
new file mode 100644
index 0000000..3e02e47
--- /dev/null
+++ b/src/chart/pie.js
@@ -0,0 +1,813 @@
+/**

+ * echarts图表类:饼图

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function(require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} series 数据

+     * @param {Object} component 组件

+     */

+    function Pie(messageCenter, zr, option, component){

+        // 基类装饰

+        var ComponentBase = require('../component/base');

+        ComponentBase.call(this, zr);

+        // 可计算特性装饰

+        var CalculableBase = require('./calculableBase');

+        CalculableBase.call(this, zr, option);

+

+        var ecConfig = require('../config');

+        var ecData = require('../util/ecData');

+

+        var zrMath = require('zrender/tool/math');

+        var zrUtil = require('zrender/tool/util');

+

+        var self = this;

+        self.type = ecConfig.CHART_TYPE_PIE;

+

+        var series;                 // 共享数据源,不要修改跟自己无关的项

+

+        var _zlevelBase = self.getZlevelBase();

+

+        function _buildShape() {

+            self.selectedMap = {};

+

+            var pieCase;        // 饼图箱子

+            for (var i = 0, l = series.length; i < l; i++) {

+                if (series[i].type == ecConfig.CHART_TYPE_PIE) {

+                    series[i] = self.reformOption(series[i]);

+                    if (self.deepQuery([series[i], option], 'calculable')) {

+                        pieCase = {

+                            shape : series[i].radius[0] <= 10

+                                    ? 'circle' : 'ring',

+                            zlevel : _zlevelBase,

+                            hoverable : false,

+                            style : {

+                                x : series[i].center[0],          // 圆心横坐标

+                                y : series[i].center[1],          // 圆心纵坐标

+                                r0 : series[i].radius[0] <= 10    // 圆环内半径

+                                     ? 0 : series[i].radius[0] - 10,

+                                r : series[i].radius[1] + 10,     // 圆环外半径

+                                brushType : 'stroke',

+                                strokeColor : series[i].calculableHolderColor

+                                              || ecConfig.calculableHolderColor

+                            }

+                        };

+                        ecData.pack(pieCase, series[i], i, undefined, -1);

+                        self.setCalculable(pieCase);

+                        self.shapeList.push(pieCase);

+                    }

+                    _buildSinglePie(i);

+                }

+            }

+

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                self.shapeList[i].id = zr.newShapeId(self.type);

+                zr.addShape(self.shapeList[i]);

+            }

+        }

+

+        /**

+         * 构建单个饼图

+         *

+         * @param {number} seriesIndex 系列索引

+         */

+        function _buildSinglePie(seriesIndex) {

+            var serie = series[seriesIndex];

+            var data = serie.data;

+            var legend = component.legend;

+            var itemName;

+            var totalSelected = 0;               // 迭代累计

+            var totalValue = 0;                  // 迭代累计

+

+            // 计算需要显示的个数和总值

+            for (var i = 0, l = data.length; i < l; i++) {

+                itemName = data[i].name;

+                if (legend){

+                    self.selectedMap[itemName] = legend.isSelected(itemName);

+                } else {

+                    self.selectedMap[itemName] = true;

+                }

+                if (self.selectedMap[itemName]) {

+                    totalSelected++;

+                    totalValue += +data[i].value;

+                }

+            }

+

+            var percent;

+            var startAngle = serie.startAngle.toFixed(2) - 0;

+            var endAngle;

+            var minAngle = serie.minAngle;

+            var totalAngle = 360 - (minAngle * totalSelected);

+            var defaultColor;

+

+            for (var i = 0, l = data.length; i < l; i++){

+                itemName = data[i].name;

+                if (!self.selectedMap[itemName]) {

+                    continue;

+                }

+                // 默认颜色策略

+                if (legend) {

+                    // 有图例则从图例中获取颜色定义

+                    defaultColor = legend.getColor(itemName);

+                }

+                else {

+                    // 全局颜色定义

+                    defaultColor = zr.getColor(i);

+                }

+

+                percent = data[i].value / totalValue;

+                endAngle = (percent * totalAngle

+                            + startAngle + minAngle).toFixed(2) - 0;

+                percent = (percent * 100).toFixed(2);

+

+                _buildItem(

+                    seriesIndex, i, percent,

+                    startAngle, endAngle, defaultColor

+                );

+                startAngle = endAngle;

+            }

+        }

+

+        /**

+         * 构建单个扇形及指标

+         */

+        function _buildItem(

+            seriesIndex, dataIndex, percent,

+            startAngle, endAngle, defaultColor

+        ) {

+            // 扇形

+            var sector = _getSector(

+                    seriesIndex, dataIndex, percent,

+                    startAngle, endAngle, defaultColor

+                );

+            // 图形需要附加的私有数据

+            ecData.pack(

+                sector,

+                series[seriesIndex], seriesIndex,

+                series[seriesIndex].data[dataIndex], dataIndex,

+                series[seriesIndex].data[dataIndex].name,

+                percent

+            );

+            self.shapeList.push(sector);

+

+            // 文本标签,需要显示则会有返回

+            var label = _getLabel(

+                    seriesIndex, dataIndex,

+                    startAngle, endAngle, defaultColor,

+                    false

+                );

+            if (label) {

+                label._dataIndex = dataIndex;

+                self.shapeList.push(label);

+            }

+

+            // 文本标签视觉引导线,需要显示则会有返回

+            var labelLine = _getLabelLine(

+                    seriesIndex, dataIndex,

+                    startAngle, endAngle, defaultColor,

+                    false

+                );

+            if (labelLine) {

+                labelLine._dataIndex = dataIndex;

+                self.shapeList.push(labelLine);

+            }

+        }

+

+        /**

+         * 构建扇形

+         */

+        function _getSector(

+            seriesIndex, dataIndex, percent,

+            startAngle, endAngle, defaultColor

+        ) {

+            var serie = series[seriesIndex];

+            var data = serie.data[dataIndex];

+

+            // 多级控制

+            var normalColor = self.deepQuery(

+                    [data, serie],

+                    'itemStyle.normal.color'

+                );

+

+            var emphasisColor = self.deepQuery(

+                    [data, serie],

+                    'itemStyle.emphasis.color'

+                );

+

+            var sector = {

+                shape : 'sector',             // 扇形

+                zlevel : _zlevelBase,

+                style : {

+                    x : serie.center[0],          // 圆心横坐标

+                    y : serie.center[1],          // 圆心纵坐标

+                    r0 : serie.radius[0],         // 圆环内半径

+                    r : serie.radius[1],          // 圆环外半径

+                    startAngle : startAngle,

+                    endAngle : endAngle,

+                    brushType : 'both',

+                    color : normalColor || defaultColor,

+                    strokeColor : '#fff',

+                    lineWidth: 2

+                },

+                highlightStyle : {

+                    color : emphasisColor || normalColor || defaultColor

+                },

+                clickable : true,

+                onclick : self.shapeHandler.onclick

+            };

+            if (self.deepQuery([data, serie, option], 'calculable')) {

+                self.setCalculable(sector);

+                sector.draggable = true;

+            }

+

+            if (_needLabel(serie, data, false)

+                && self.deepQuery(

+                    [data, serie],

+                    'itemStyle.normal.label.position'

+                ) == 'inner'

+            ) {

+                sector.style.text = data.name;

+                sector.style.textPosition = 'specific';

+                sector.style.textColor = self.deepQuery(

+                    [data, serie],

+                    'itemStyle.normal.label.textStyle.color'

+                ) || '#fff';

+                sector.style.textAlign = self.deepQuery(

+                    [data, serie],

+                    'itemStyle.normal.label.textStyle.align'

+                ) || 'center';

+                sector.style.textBaseLine = self.deepQuery(

+                    [data, serie],

+                    'itemStyle.normal.label.textStyle.baseline'

+                ) || 'middle';

+                sector.style.textX = Math.round(

+                    serie.center[0]

+                    + (serie.radius[1] + serie.radius[0]) / 2

+                      * zrMath.cos((startAngle + endAngle) / 2, true)

+                );

+                sector.style.textY = Math.round(

+                    serie.center[1]

+                    - (serie.radius[1] + serie.radius[0]) / 2

+                       * zrMath.sin((startAngle + endAngle) / 2, true)

+                );

+                sector.style.textFont = self.getFont(self.deepQuery(

+                    [data, serie],

+                    'itemStyle.normal.label.textStyle'

+                ));

+            }

+

+            if (_needLabel(serie, data, true)

+                && self.deepQuery(

+                    [data, serie],

+                    'itemStyle.emphasis.label.position'

+                ) == 'inner'

+            ) {

+                sector.highlightStyle.text = data.name;

+                sector.highlightStyle.textPosition = 'specific';

+                sector.highlightStyle.textColor = self.deepQuery(

+                    [data, serie],

+                    'itemStyle.emphasis.label.textStyle.color'

+                ) || '#fff';

+                sector.highlightStyle.textAlign = self.deepQuery(

+                    [data, serie],

+                    'itemStyle.emphasis.label.textStyle.align'

+                ) || 'center';

+                sector.highlightStyle.textBaseLine = self.deepQuery(

+                    [data, serie],

+                    'itemStyle.normal.label.textStyle.baseline'

+                ) || 'middle';

+                sector.highlightStyle.textX = Math.round(

+                    serie.center[0]

+                    + (serie.radius[1] + serie.radius[0]) / 2

+                      * zrMath.cos((startAngle + endAngle) / 2, true)

+                );

+                sector.highlightStyle.textY = Math.round(

+                    serie.center[1]

+                    - (serie.radius[1] + serie.radius[0]) / 2

+                      * zrMath.sin((startAngle + endAngle) / 2, true)

+                );

+                sector.highlightStyle.textFont = self.getFont(self.deepQuery(

+                    [data, serie],

+                    'itemStyle.emphasis.label.textStyle'

+                ));

+            }

+

+            // “normal下不显示,emphasis显示”添加事件响应

+            if (_needLabel(serie, data, true)          // emphasis下显示文本

+                || _needLabelLine(serie, data, true)   // emphasis下显示引导线

+            ) {

+                sector.onmouseover = self.shapeHandler.onmouserover;

+            }

+            return sector;

+        }

+

+        /**

+         * 需要显示则会有返回构建好的shape,否则返回undefined

+         */

+        function _getLabel(

+            seriesIndex, dataIndex,

+            startAngle, endAngle, defaultColor,

+            isEmphasis

+        ) {

+            var serie = series[seriesIndex];

+            var data = serie.data[dataIndex];

+            // 特定状态下是否需要显示文本标签

+            if (_needLabel(serie, data, isEmphasis)) {

+                var status = isEmphasis ? 'emphasis' : 'normal';

+

+                // serie里有默认配置,放心大胆的用!

+                var itemStyle = zrUtil.merge(

+                        zrUtil.clone(data.itemStyle) || {},

+                        serie.itemStyle,

+                        {

+                            'overwrite' : false,

+                            'recursive' : true

+                        }

+                    );

+                // label配置

+                var labelControl = itemStyle[status].label;

+                var textStyle = labelControl.textStyle || {};

+

+                var centerX = serie.center[0];                      // 圆心横坐标

+                var centerY = serie.center[1];                      // 圆心纵坐标

+                var midAngle = ((endAngle + startAngle) / 2) % 360; // 角度中值

+                var radius;                                         // 标签位置半径

+                var textAlign;

+                if (labelControl.position == 'outer') {

+                    // 外部显示,默认

+                    radius = serie.radius[1]

+                             + itemStyle[status].labelLine.length

+                             + textStyle.fontSize;

+                    textAlign = (midAngle >= 150 && midAngle <= 210)

+                                ? 'right'

+                                : ((midAngle <= 30 || midAngle >= 330)

+                                       ? 'left'

+                                       : 'center'

+                                   );

+                    return {

+                        shape : 'text',

+                        zlevel : _zlevelBase + 1,

+                        hoverable : false,

+                        style : {

+                            x : centerX + radius * zrMath.cos(midAngle, true),

+                            y : centerY - radius * zrMath.sin(midAngle, true),

+                            color : textStyle.color || defaultColor,

+                            text : data.name,

+                            textAlign : textStyle.align

+                                        || textAlign,

+                            textBaseline : textStyle.baseline || 'middle',

+                            textFont : self.getFont(textStyle)

+                        },

+                        highlightStyle : {

+                            brushType : 'fill'

+                        }

+                    };

+                }

+                else if (labelControl.position == 'center') {

+                    return {

+                        shape : 'text',

+                        zlevel : _zlevelBase + 1,

+                        hoverable : false,

+                        style : {

+                            x : centerX,

+                            y : centerY,

+                            color : textStyle.color || defaultColor,

+                            text : data.name,

+                            textAlign : textStyle.align

+                                        || 'center',

+                            textBaseline : textStyle.baseline || 'middle',

+                            textFont : self.getFont(textStyle)

+                        },

+                        highlightStyle : {

+                            brushType : 'fill'

+                        }

+                    };

+                }

+                else {

+                    // 内部显示由sector自带,不返回即可

+                    return;

+                    /*

+                    radius = (serie.radius[0] + serie.radius[1]) / 2;

+                    textAlign = 'center';

+                    defaultColor = '#fff';

+                    */

+                }

+            }

+            else {

+                return;

+            }

+        }

+

+        /**

+         * 需要显示则会有返回构建好的shape,否则返回undefined

+         */

+        function _getLabelLine(

+            seriesIndex, dataIndex,

+            startAngle, endAngle, defaultColor,

+            isEmphasis

+        ) {

+            var serie = series[seriesIndex];

+            var data = serie.data[dataIndex];

+

+            // 特定状态下是否需要显示文本标签

+            if (_needLabelLine(serie, data, isEmphasis)) {

+                var status = isEmphasis ? 'emphasis' : 'normal';

+

+                // serie里有默认配置,放心大胆的用!

+                var itemStyle = zrUtil.merge(

+                        zrUtil.clone(data.itemStyle) || {},

+                        serie.itemStyle,

+                        {

+                            'overwrite' : false,

+                            'recursive' : true

+                        }

+                    );

+                // labelLine配置

+                var labelLineControl = itemStyle[status].labelLine;

+                var lineStyle = labelLineControl.lineStyle || {};

+

+                var centerX = serie.center[0];                    // 圆心横坐标

+                var centerY = serie.center[1];                    // 圆心纵坐标

+                // 视觉引导线起点半径

+                var midRadius = serie.radius[1];

+                // 视觉引导线终点半径

+                var maxRadius = midRadius + labelLineControl.length;

+                var midAngle = ((endAngle + startAngle) / 2) % 360; // 角度中值

+                var cosValue = zrMath.cos(midAngle, true);

+                var sinValue = zrMath.sin(midAngle, true);

+                // 三角函数缓存已在zrender/tool/math中做了

+                return {

+                    shape : 'line',

+                    zlevel : _zlevelBase + 1,

+                    hoverable : false,

+                    style : {

+                        xStart : centerX + midRadius * cosValue,

+                        yStart : centerY - midRadius * sinValue,

+                        xEnd : centerX + maxRadius * cosValue,

+                        yEnd : centerY - maxRadius * sinValue,

+                        strokeColor : lineStyle.color || defaultColor,

+                        lineType : lineStyle.type,

+                        lineWidth : lineStyle.width

+                    }

+                };

+            }

+            else {

+                return;

+            }

+        }

+

+        /**

+         * 返回特定状态(normal or emphasis)下是否需要显示label标签文本

+         * @param {Object} serie

+         * @param {Object} data

+         * @param {boolean} isEmphasis true is 'emphasis' and false is 'normal'

+         */

+        function _needLabel(serie, data, isEmphasis) {

+            return self.deepQuery(

+                [data, serie],

+                'itemStyle.'

+                + (isEmphasis ? 'emphasis' : 'normal')

+                + '.label.show'

+            );

+        }

+

+        /**

+         * 返回特定状态(normal or emphasis)下是否需要显示labelLine标签视觉引导线

+         * @param {Object} serie

+         * @param {Object} data

+         * @param {boolean} isEmphasis true is 'emphasis' and false is 'normal'

+         */

+        function _needLabelLine(serie, data, isEmphasis) {

+            return self.deepQuery(

+                [data, serie],

+                'itemStyle.'

+                + (isEmphasis ? 'emphasis' : 'normal')

+                +'.labelLine.show'

+            );

+        }

+        /**

+         * 参数修正&默认值赋值,重载基类方法

+         * @param {Object} opt 参数

+         */

+        function reformOption(opt) {

+            // 常用方法快捷方式

+            var _merge = zrUtil.merge;

+            opt = _merge(

+                      opt || {},

+                      ecConfig.pie,

+                      {

+                          'overwrite' : false,

+                          'recursive' : true

+                      }

+                  );

+

+            // 圆心坐标,无则为自适应居中

+            if (!opt.center) {

+                opt.center = [

+                    Math.round(zr.getWidth() / 2),

+                    Math.round(zr.getHeight() / 2)

+                ];

+            }

+

+            // 传数组实现环形图,[内半径,外半径],传单个则默认为外半径为

+            if (typeof opt.radius == 'undefined') {

+                opt.radius = [

+                    0,

+                    Math.round(Math.min(zr.getWidth(), zr.getHeight()) / 2 - 50)

+                ];

+            } else if (!(opt.radius instanceof Array)) {

+                opt.radius = [0, opt.radius];

+            }

+

+            // 通用字体设置

+            opt.itemStyle.normal.label.textStyle = _merge(

+                opt.itemStyle.normal.label.textStyle || {},

+                ecConfig.textStyle,

+                {

+                    'overwrite' : false,

+                    'recursive' : true

+                }

+            );

+            opt.itemStyle.emphasis.label.textStyle = _merge(

+                opt.itemStyle.emphasis.label.textStyle || {},

+                ecConfig.textStyle,

+                {

+                    'overwrite' : false,

+                    'recursive' : true

+                }

+            );

+

+            return opt;

+        }

+

+        /**

+         * 构造函数默认执行的初始化方法,也用于创建实例后动态修改

+         * @param {Object} newZr

+         * @param {Object} newSeries

+         * @param {Object} newComponent

+         */

+        function init(newOption, newComponent) {

+            option = newOption;

+            component = newComponent;

+

+            series = option.series;

+

+            self.clear();

+            _buildShape();

+        }

+

+        /**

+         * 刷新

+         */

+        function refresh() {

+            self.clear();

+            _buildShape();

+        }

+

+        /**

+         * 动画设定

+         */

+        function animation() {

+            var duration = self.deepQuery([option], 'animationDuration');

+            var easing = self.deepQuery([option], 'animationEasing');

+            var x;

+            var y;

+            var r0;

+            var r;

+            var serie;

+            var dataIndex;

+

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                if (self.shapeList[i].shape == 'sector'

+                    || self.shapeList[i].shape == 'circle'

+                    || self.shapeList[i].shape == 'ring'

+                ) {

+                    x = self.shapeList[i].style.x;

+                    y = self.shapeList[i].style.y;

+                    r0 = self.shapeList[i].style.r0;

+                    r = self.shapeList[i].style.r;

+

+                    zr.modShape(self.shapeList[i].id, {

+                        rotation : [Math.PI*2, x, y],

+                        style : {

+                            r0 : 0,

+                            r : 0

+                        }

+                    });

+

+                    serie = ecData.get(self.shapeList[i], 'series');

+                    dataIndex = ecData.get(self.shapeList[i], 'dataIndex');

+                    zr.animate(self.shapeList[i].id, 'style')

+                        .when(

+                            (self.deepQuery([serie],'animationDuration')

+                            || duration)

+                            + dataIndex * 10,

+

+                            {

+                                r0 : r0,

+                                r : r

+                            },

+

+                            'QuinticOut'

+                        )

+                        .start();

+                    zr.animate(self.shapeList[i].id, '')

+                        .when(

+                            (self.deepQuery([serie],'animationDuration')

+                            || duration)

+                            + dataIndex * 100,

+

+                            {rotation : [0, x, y]},

+

+                            (self.deepQuery([serie], 'animationEasing')

+                            || easing)

+                        )

+                        .start();

+                }

+                else {

+                    dataIndex = self.shapeList[i]._dataIndex;

+                    zr.modShape(self.shapeList[i].id, {

+                        scale : [0, 0, x, y]

+                    });

+                    zr.animate(self.shapeList[i].id, '')

+                        .when(

+                            duration + dataIndex * 100,

+                            {scale : [1, 1, x, y]},

+                            'QuinticOut'

+                        )

+                        .start();

+                }

+            }

+        }

+

+        function onclick(param) {

+            if (!self.isClick || !param.target) {

+                // 没有在当前实例上发生点击直接返回

+                return;

+            }

+            var deviation = 10;             // 偏移

+            var target = param.target;

+            var style = target.style;

+

+            if (!style._hasClick) {

+                var midAngle = ((style.startAngle + style.endAngle) / 2)

+                               .toFixed(2) - 0;

+                target.style._hasClick = true;

+                target.style._x = target.style.x;

+                target.style._y = target.style.y;

+                target.style.x += zrMath.cos(midAngle, true) * deviation;

+                target.style.y -= zrMath.sin(midAngle, true) * deviation;

+            }

+            else {

+                // 复位

+                target.style.x = target.style._x;

+                target.style.y = target.style._y;

+                target.style._hasClick = false;

+            }

+

+            zr.modShape(target.id, target);

+            zr.refresh();

+        }

+

+        /**

+         * 数据项被拖拽进来, 重载基类方法

+         */

+        function ondrop(param, status) {

+            if (!self.isDrop || !param.target) {

+                // 没有在当前实例上发生拖拽行为则直接返回

+                return;

+            }

+

+            var target = param.target;      // 拖拽安放目标

+            var dragged = param.dragged;    // 当前被拖拽的图形对象

+

+            var seriesIndex = ecData.get(target, 'seriesIndex');

+            var dataIndex = ecData.get(target, 'dataIndex');

+

+            var data;

+            var legend = component.legend;

+            if (dataIndex == -1) {

+                // 落到pieCase上,数据被拖拽进某个饼图,增加数据

+                data = {

+                    value : ecData.get(dragged, 'value'),

+                    name : ecData.get(dragged, 'name')

+                };

+

+                // 修饼图数值不为负值

+                if (data.value < 0) {

+                    data.value = 0;

+                }

+

+                series[seriesIndex].data.push(data);

+

+                legend.add(

+                    data.name,

+                    dragged.style.color || dragged.style.strokeColor

+                );

+            }

+            else {

+                // 落到sector上,数据被拖拽到某个数据项上,数据修改

+                data = series[seriesIndex].data[dataIndex];

+                legend.del(data.name);

+                data.name += option.nameConnector

+                             + ecData.get(dragged, 'name');

+                data.value += ecData.get(dragged, 'value');

+                legend.add(

+                    data.name,

+                    dragged.style.color || dragged.style.strokeColor

+                );

+            }

+

+            // 别status = {}赋值啊!!

+            status.dragIn = status.dragIn || true;

+

+            // 处理完拖拽事件后复位

+            self.isDrop = false;

+

+            return;

+        }

+

+        /**

+         * 数据项被拖拽出去,重载基类方法

+         */

+        function ondragend(param, status) {

+            if (!self.isDragend || !param.target) {

+                // 没有在当前实例上发生拖拽行为则直接返回

+                return;

+            }

+

+            var target = param.target;      // 被拖拽图形元素

+

+            var seriesIndex = ecData.get(target, 'seriesIndex');

+            var dataIndex = ecData.get(target, 'dataIndex');

+

+            // 被拖拽的图形是饼图sector,删除被拖拽走的数据

+            component.legend.del(

+                series[seriesIndex].data[dataIndex].name

+            );

+            series[seriesIndex].data.splice(dataIndex, 1);

+

+            // 别status = {}赋值啊!!

+            status.dragOut = true;

+            status.needRefresh = true;

+

+            // 处理完拖拽事件后复位

+            self.isDragend = false;

+

+            return;

+        }

+

+        /**

+         * 输出动态视觉引导线

+         */

+        self.shapeHandler.onmouserover = function(param) {

+            var shape = param.target;

+            var seriesIndex = ecData.get(shape, 'seriesIndex');

+            var dataIndex = ecData.get(shape, 'dataIndex');

+

+            var startAngle = shape.style.startAngle;

+            var endAngle = shape.style.endAngle;

+            var defaultColor = shape.highlightStyle.color;

+

+            // 文本标签,需要显示则会有返回

+            var label = _getLabel(

+                    seriesIndex, dataIndex,

+                    startAngle, endAngle, defaultColor,

+                    true

+                );

+            if (label) {

+                zr.addHoverShape(label);

+            }

+

+            // 文本标签视觉引导线,需要显示则会有返回

+            var labelLine = _getLabelLine(

+                    seriesIndex, dataIndex,

+                    startAngle, endAngle, defaultColor,

+                    true

+                );

+            if (labelLine) {

+                zr.addHoverShape(labelLine);

+            }

+        };

+

+        self.reformOption = reformOption;   // 重载基类方法

+

+        self.init = init;

+        self.refresh = refresh;

+        self.animation = animation;

+        self.onclick = onclick;

+        self.ondrop = ondrop;

+        self.ondragend = ondragend;

+

+        init(option, component);

+    }

+

+    return Pie;

+});
\ No newline at end of file
diff --git a/src/component.js b/src/component.js
new file mode 100644
index 0000000..c53fabf
--- /dev/null
+++ b/src/component.js
@@ -0,0 +1,52 @@
+/**

+ * echart组件库

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function(require) {    //component

+    var self = {};

+

+    var _componentLibrary = {};     //echart组件库

+

+    /**

+     * 定义图形实现

+     * @param {Object} name

+     * @param {Object} clazz 图形实现

+     */

+    self.define = function(name, clazz) {

+        _componentLibrary[name] = clazz;

+        return self;

+    };

+

+    /**

+     * 获取图形实现

+     * @param {Object} name

+     */

+    self.get = function(name) {

+        return _componentLibrary[name];

+    };

+

+    // 内置组件注册

+    self.define('axis', require('./component/axis'));

+

+    self.define('categoryAxis', require('./component/categoryAxis'));

+

+    self.define('valueAxis', require('./component/valueAxis'));

+

+    self.define('grid', require('./component/grid'));

+

+    self.define('dataZoom', require('./component/dataZoom'));

+

+    self.define('legend', require('./component/legend'));

+

+    self.define('tooltip', require('./component/tooltip'));

+

+    self.define('toolbox', require('./component/toolbox'));

+

+    self.define('dataView', require('./component/dataView'));

+

+    return self;

+});
\ No newline at end of file
diff --git a/src/component/axis.js b/src/component/axis.js
new file mode 100644
index 0000000..bdc77cb
--- /dev/null
+++ b/src/component/axis.js
@@ -0,0 +1,188 @@
+/**

+ * echarts组件类: 坐标轴

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ * 直角坐标系中坐标轴数组,数组中每一项代表一条横轴(纵轴)坐标轴。

+ * 标准(1.0)中规定最多同时存在2条横轴和2条纵轴

+ *    单条横轴时可指定安放于grid的底部(默认)或顶部,2条同时存在时则默认第一条安放于底部,第二天安放于顶部

+ *    单条纵轴时可指定安放于grid的左侧(默认)或右侧,2条同时存在时则默认第一条安放于左侧,第二天安放于右侧。

+ * 坐标轴有两种类型,类目型和数值型(区别详见axis):

+ *    横轴通常为类目型,但条形图时则横轴为数值型,散点图时则横纵均为数值型

+ *    纵轴通常为数值型,但条形图时则纵轴为类目型。

+ *

+ */

+define(function (require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} option 图表选项

+     *     @param {string=} option.xAxis.type 坐标轴类型,横轴默认为类目型'category'

+     *     @param {string=} option.yAxis.type 坐标轴类型,纵轴默认为类目型'value'

+     * @param {Object} component 组件

+     * @param {string} axisType 横走or纵轴

+     */

+    function Axis(messageCenter, zr, option, component, axisType) {

+        var Base = require('./base');

+        Base.call(this, zr);

+

+        var ecConfig = require('../config');

+

+        var self = this;

+        self.type = ecConfig.COMPONENT_TYPE_AXIS;

+

+        var _axisList = [];

+

+        /**

+         * 参数修正&默认值赋值,重载基类方法

+         * @param {Object} opt 参数

+         */

+        function reformOption(opt) {

+            // 不写或传了个空数值默认为数值轴

+            if (!opt

+                || (opt instanceof Array && opt.length === 0)

+            ) {

+                opt = [{

+                    type : ecConfig.COMPONENT_TYPE_AXIS_VALUE

+                }];

+            }

+            else if (!(opt instanceof Array)){

+                opt = [opt];

+            }

+

+            // 最多两条,其他参数忽略

+            if (opt.length > 2) {

+                opt = [opt[0],opt[1]];

+            }

+

+

+            if (axisType == 'xAxis') {

+                // 横轴位置默认配置

+                if (!opt[0].position            // 没配置或配置错

+                    || (opt[0].position != 'bottom'

+                        && opt[0].position != 'top')

+                ) {

+                    opt[0].position = 'bottom';

+                }

+                if (opt.length > 1) {

+                    opt[1].position = opt[0].position == 'bottom'

+                                      ? 'top' : 'bottom';

+                }

+

+                for (var i = 0, l = opt.length; i < l; i++) {

+                    // 坐标轴类型,横轴默认为类目型'category'

+                    opt[i].type = opt[i].type || 'category';

+                    // 标识轴类型&索引

+                    opt[i].xAxisIndex = i;

+                    opt[i].yAxisIndex = -1;

+                }

+            }

+            else {

+                // 纵轴位置默认配置

+                if (!opt[0].position            // 没配置或配置错

+                    || (opt[0].position != 'left'

+                        && opt[0].position != 'right')

+                ) {

+                    opt[0].position = 'left';

+                }

+

+                if (opt.length > 1) {

+                    opt[1].position = opt[0].position == 'left'

+                                      ? 'right' : 'left';

+                }

+

+                for (var i = 0, l = opt.length; i < l; i++) {

+                    // 坐标轴类型,纵轴默认为数值型'value'

+                    opt[i].type = opt[i].type || 'value';

+                    // 标识轴类型&索引

+                    opt[i].xAxisIndex = -1;

+                    opt[i].yAxisIndex = i;

+                }

+            }

+

+            return opt;

+        }

+

+        /**

+         * 构造函数默认执行的初始化方法,也用于创建实例后动态修改

+         * @param {Object} newZr

+         * @param {Object} newOption

+         * @param {Object} newCompoent

+         */

+        function init(newOption, newCompoent, newAxisType) {

+            component = newCompoent;

+            axisType = newAxisType;

+

+            self.clear();

+

+            var axisOption;

+            if (axisType == 'xAxis') {

+                option.xAxis =self.reformOption(newOption.xAxis);

+                axisOption = option.xAxis;

+            }

+            else {

+                option.yAxis = reformOption(newOption.yAxis);

+                axisOption = option.yAxis;

+            }

+

+            var CategoryAxis = require('./categoryAxis');

+            var ValueAxis = require('./valueAxis');

+            for (var i = 0, l = axisOption.length; i < l; i++) {

+                _axisList.push(

+                    axisOption[i].type == 'category'

+                    ? new CategoryAxis(

+                          messageCenter, zr,

+                          axisOption[i], component

+                      )

+                    : new ValueAxis(

+                          messageCenter, zr,

+                          axisOption[i], component,

+                          option.series

+                      )

+                );

+            }

+        }

+

+        /**

+         * 刷新

+         */

+        function refresh() {

+            for (var i = 0, l = _axisList.length; i < l; i++) {

+                _axisList[i].refresh && _axisList[i].refresh();

+            }

+        }

+

+        /**

+         * 根据值换算位置

+         * @param {number} idx 坐标轴索引0~1

+         */

+        function getAxis(idx) {

+            return _axisList[idx];

+        }

+

+        /**

+         * 清除坐标轴子对象,实例仍可用,重载基类方法

+         */

+        function clear() {

+            for (var i = 0, l = _axisList.length; i < l; i++) {

+                _axisList[i].dispose && _axisList[i].dispose();

+            }

+            _axisList = [];

+        }

+

+        // 重载基类方法

+        self.clear = clear;

+        self.reformOption = reformOption;

+

+        self.init = init;

+        self.refresh = refresh;

+        self.getAxis = getAxis;

+

+        init(option, component, axisType);

+    }

+

+    return Axis;

+});
\ No newline at end of file
diff --git a/src/component/base.js b/src/component/base.js
new file mode 100644
index 0000000..2661d04
--- /dev/null
+++ b/src/component/base.js
@@ -0,0 +1,185 @@
+/**

+ * echarts组件基类

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function(require) {

+    function Base(zr){

+        var ecConfig = require('../config');

+        var zrUtil = require('zrender/tool/util');

+        var self = this;

+

+        self.zr =zr;

+

+        self.shapeList = [];

+

+        /**

+         * 获取zlevel基数配置

+         * @param {Object} contentType

+         */

+        function getZlevelBase(contentType) {

+            contentType = contentType || self.type + '';

+

+            switch (contentType) {

+                case ecConfig.COMPONENT_TYPE_GRID :

+                case ecConfig.COMPONENT_TYPE_AXIS_CATEGORY :

+                case ecConfig.COMPONENT_TYPE_AXIS_VALUE :

+                    return 0;

+

+                case ecConfig.CHART_TYPE_LINE :

+                case ecConfig.CHART_TYPE_BAR :

+                case ecConfig.CHART_TYPE_SCATTER :

+                case ecConfig.CHART_TYPE_PIE :

+                case ecConfig.CHART_TYPE_RADAR :

+                    return 2;

+

+                case ecConfig.COMPONENT_TYPE_LEGEND :

+                case ecConfig.COMPONENT_TYPE_DATAZOOM :

+                    return 4;

+

+                case ecConfig.CHART_TYPE_ISLAND :

+                    return 5;

+

+                case ecConfig.COMPONENT_TYPE_TOOLTIP :

+                case ecConfig.COMPONENT_TYPE_TOOLBOX :

+                    return 6;

+

+                default :

+                    return 0;

+            }

+        }

+

+        /**

+         * 参数修正&默认值赋值

+         * @param {Object} opt 参数

+         *

+         * @return {Object} 修正后的参数

+         */

+        function reformOption(opt) {

+            return zrUtil.merge(

+                       opt || {},

+                       ecConfig[self.type] || {},

+                       {

+                           'overwrite': false,

+                           'recursive': true

+                       }

+                   );

+        }

+

+        /**

+         * css类属性数组补全,如padding,margin等~

+         */

+        function reformCssArray(p) {

+            if (p instanceof Array) {

+                switch (p.length + '') {

+                    case '4':

+                        return p;

+                    case '3':

+                        return [p[0], p[1], p[2], p[1]];

+                    case '2':

+                        return [p[0], p[1], p[0], p[1]];

+                    case '1':

+                        return [p[0], p[0], p[0], p[0]];

+                    case '0':

+                        return [0, 0, 0, 0];

+                }

+            }

+            else {

+                return [p, p, p, p];

+            }

+        }

+

+

+        /**

+         * 获取多级控制嵌套属性的基础方法

+         * 返回ctrList中优先级最高(最靠前)的非undefined属性,ctrList中均无定义则返回undefined

+         */

+        var deepQuery = (function() {

+            /**

+             * 获取嵌套选项的基础方法

+             * 返回optionTarget中位于optionLocation上的值,如果没有定义,则返回undefined

+             */

+            function _query(optionTarget, optionLocation) {

+                if (typeof optionTarget == 'undefined') {

+                    return undefined;

+                }

+                if (!optionLocation) {

+                    return optionTarget;

+                }

+                optionLocation = optionLocation.split('.');

+

+                var length = optionLocation.length;

+                var curIdx = 0;

+                while (curIdx < length) {

+                    optionTarget = optionTarget[optionLocation[curIdx]];

+                    if (typeof optionTarget == 'undefined') {

+                        return undefined;

+                    }

+                    curIdx++;

+                }

+                return optionTarget;

+            }

+

+            return function(ctrList, optionLocation) {

+                var finalOption;

+                for (var i = 0, l = ctrList.length; i < l; i++) {

+                    finalOption = _query(ctrList[i], optionLocation);

+                    if (typeof finalOption != 'undefined') {

+                        return finalOption;

+                    }

+                }

+                return undefined;

+            };

+        })();

+

+        /**

+         * 获取自定义和默认配置合并后的字体设置

+         */

+        function getFont(textStyle) {

+            var finalTextStyle = zrUtil.merge(

+                zrUtil.clone(textStyle) || {},

+                ecConfig.textStyle,

+                { 'overwrite': false}

+            );

+            return finalTextStyle.fontStyle + ' '

+                   + finalTextStyle.fontWeight + ' '

+                   + finalTextStyle.fontSize + 'px '

+                   + finalTextStyle.fontFamily;

+        }

+

+        /**

+         * 清除图形数据,实例仍可用

+         */

+        function clear() {

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                self.zr.delShape(self.shapeList[i].id);

+            }

+            self.shapeList = [];

+        }

+

+        /**

+         * 释放后实例不可用

+         */

+        function dispose() {

+            self.clear();

+            self.shapeList = null;

+            self = null;

+        }

+

+        /**

+         * 基类方法

+         */

+        self.getZlevelBase = getZlevelBase;

+        self.reformOption = reformOption;

+        self.reformCssArray = reformCssArray;

+        self.deepQuery = deepQuery;

+        self.getFont = getFont;

+        self.clear = clear;

+        self.dispose = dispose;

+    }

+

+    return Base;

+});

diff --git a/src/component/categoryAxis.js b/src/component/categoryAxis.js
new file mode 100644
index 0000000..c3e2245
--- /dev/null
+++ b/src/component/categoryAxis.js
@@ -0,0 +1,643 @@
+/**

+ * echarts组件: 类目轴

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function (require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} option 类目轴参数

+     * @param {Grid} grid 网格对象

+     */

+    function CategoryAxis(messageCenter, zr, option, component) {

+        var Base = require('./base');

+        Base.call(this, zr);

+

+        var ecConfig = require('../config');

+

+        var zrUtil = require('zrender/tool/util');

+        var zrArea = require('zrender/tool/area');

+

+        var self = this;

+        self.type = ecConfig.COMPONENT_TYPE_AXIS_CATEGORY;

+

+        var grid = component.grid;

+

+        var _zlevelBase = self.getZlevelBase();

+        var _interval;                              // 标签显示的挑选间隔

+        var _labelData;

+

+        function _reformLabel() {

+            var data = zrUtil.clone(option.data);

+            var axisFormatter = option.axisLabel.formatter;

+            var formatter;

+            for (var i = 0, l = data.length; i < l; i++) {

+                formatter = data[i].formatter || axisFormatter;

+                if (formatter) {

+                    if (typeof formatter == 'function') {

+                        if (typeof data[i].value != 'undefined') {

+                            data[i].value = formatter(data[i].value);

+                        }

+                        else {

+                            data[i] = formatter(data[i]);

+                        }

+                    }

+                    else if (typeof formatter == 'string') {

+                        if (typeof data[i].value != 'undefined') {

+                            data[i].value = formatter.replace(

+                                '{value}',data[i].value

+                            );

+                        }

+                        else {

+                            data[i] = formatter.replace('{value}',data[i]);

+                        }

+                    }

+                }

+            }

+            return data;

+        }

+

+        /**

+         * 计算标签显示挑选间隔

+         */

+        function _getInterval() {

+            var interval   = option.axisLabel.interval;

+            if (interval == 'auto') {

+                // 麻烦的自适应计算

+                var fontSize = option.axisLabel.textStyle.fontSize;

+                var font = self.getFont(option.axisLabel.textStyle);

+                var data = option.data;

+                var dataLength = option.data.length;

+

+                if (option.position == 'bottom' || option.position == 'top') {

+                    // 横向

+                    if (dataLength > 3) {

+                        var gap = getCoord(data[1]) -  getCoord(data[0]);

+                        var isEnough = false;

+                        var labelSpace;

+                        var labelSize;

+                        interval = 0;

+                        while (!isEnough && interval < dataLength) {

+                            interval++;

+                            isEnough = true;

+                            labelSpace = gap * interval - 10; // 标签左右至少间隔为5px

+                            for (var i = 0; i < dataLength; i += interval) {

+                                if (option.axisLabel.rotate !== 0) {

+                                    // 有旋转

+                                    labelSize = fontSize;

+                                }

+                                else if (data[i].textStyle) {

+                                    labelSize = zrArea.getTextWidth(

+                                        _labelData[i].value || _labelData[i],

+                                        self.getFont(

+                                            zrUtil.merge(

+                                                data[i].textStyle,

+                                                option.axisLabel.textStyle,

+                                                {

+                                                    'overwrite': false,

+                                                    'recursive': true

+                                                }

+                                           )

+                                        )

+                                    );

+                                }

+                                else {

+                                    labelSize = zrArea.getTextWidth(

+                                        _labelData[i].value || _labelData[i],

+                                        font

+                                    );

+                                }

+

+                                if (labelSpace < labelSize) {

+                                    // 放不下,中断循环让interval++

+                                    isEnough = false;

+                                    break;

+                                }

+                            }

+                        }

+                    }

+                    else {

+                        // 少于3个则全部显示

+                        interval = 1;

+                    }

+                }

+                else {

+                    // 纵向

+                    if (dataLength > 3) {

+                        var gap = getCoord(data[0]) - getCoord(data[1]);

+                        interval = 1;

+                        // 标签上下至少间隔为3px

+                        while ((gap * interval - 6) < fontSize

+                                && interval < dataLength

+                        ) {

+                            interval++;

+                        }

+                    }

+                    else {

+                        // 少于3个则全部显示

+                        interval = 1;

+                    }

+                }

+            }

+            else {

+                // 用户自定义间隔

+                interval += 1;

+            }

+

+            return interval;

+        }

+

+        function _buildShape() {

+            _labelData = _reformLabel();

+            _interval = _getInterval();

+            option.splitArea.show && _buildSplitArea();

+            option.splitLine.show && _buildSplitLine();

+            option.axisLine.show && _buildAxisLine();

+            option.axisTick.show && _buildAxisTick();

+            option.axisLabel.show && _buildAxisLabel();

+

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                self.shapeList[i].id = zr.newShapeId(self.type);

+                zr.addShape(self.shapeList[i]);

+            }

+        }

+

+        // 轴线

+        function _buildAxisLine() {

+            var axShape = {

+                shape : 'line',

+                zlevel: _zlevelBase + 1,

+                hoverable: false

+            };

+            switch (option.position) {

+                case 'left':

+                    axShape.style = {

+                        xStart : grid.getX(),

+                        yStart : grid.getY(),

+                        xEnd : grid.getX(),

+                        yEnd : grid.getYend()

+                    };

+                    break;

+                case 'right':

+                    axShape.style = {

+                        xStart : grid.getXend(),

+                        yStart : grid.getY(),

+                        xEnd : grid.getXend(),

+                        yEnd : grid.getYend()

+                    };

+                    break;

+                case 'bottom':

+                    axShape.style = {

+                        xStart : grid.getX(),

+                        yStart : grid.getYend(),

+                        xEnd : grid.getXend(),

+                        yEnd : grid.getYend()

+                    };

+                    break;

+                case 'top':

+                    axShape.style = {

+                        xStart : grid.getX(),

+                        yStart : grid.getY(),

+                        xEnd : grid.getXend(),

+                        yEnd : grid.getY()

+                    };

+                    break;

+            }

+

+            axShape.style.strokeColor = option.axisLine.lineStyle.color;

+            axShape.style.lineWidth = option.axisLine.lineStyle.width;

+            axShape.style.lineType = option.axisLine.lineStyle.type;

+

+            self.shapeList.push(axShape);

+        }

+

+        // 小标记

+        function _buildAxisTick() {

+            var axShape;

+            var data       = option.data;

+            var dataLength = option.data.length;

+            var length     = option.axisTick.length;

+            var color      = option.axisTick.lineStyle.color;

+            var lineWidth  = option.axisTick.lineStyle.width;

+

+            if (option.position == 'bottom' || option.position == 'top') {

+                // 横向

+                var yPosition = option.position == 'bottom'

+                                ? grid.getYend()

+                                : (grid.getY() - length);

+                for (var i = 0; i < dataLength; i++) {

+                    axShape = {

+                        shape : 'line',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            xStart : getCoord(data[i].value || data[i]),

+                            yStart : yPosition,

+                            xEnd : getCoord(data[i].value || data[i]),

+                            yEnd : yPosition + length,

+                            strokeColor : color,

+                            lineWidth : lineWidth

+                        }

+                    };

+                    self.shapeList.push(axShape);

+                }

+            }

+            else {

+                // 纵向

+                var xPosition = option.position == 'left'

+                                ? (grid.getX() - length)

+                                : grid.getXend();

+                for (var i = 0; i < dataLength; i++) {

+                    axShape = {

+                        shape : 'line',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            xStart : xPosition,

+                            yStart : getCoord(data[i].value || data[i]),

+                            xEnd : xPosition + length,

+                            yEnd : getCoord(data[i].value || data[i]),

+                            strokeColor : color,

+                            lineWidth : lineWidth

+                        }

+                    };

+                    self.shapeList.push(axShape);

+                }

+            }

+        }

+

+        // 坐标轴文本

+        function _buildAxisLabel() {

+            var axShape;

+            var data       = option.data;

+            var dataLength = option.data.length;

+            var rotate     = option.axisLabel.rotate;

+            var margin     = option.axisLabel.margin;

+            var textStyle  = option.axisLabel.textStyle;

+            var dataTextStyle;

+

+            if (option.position == 'bottom' || option.position == 'top') {

+                // 横向

+                var yPosition;

+                var baseLine;

+                if (option.position == 'bottom') {

+                    yPosition = grid.getYend() + margin;

+                    baseLine = 'top';

+                }

+                else {

+                    yPosition = grid.getY() - margin;

+                    baseLine = 'bottom';

+                }

+

+                for (var i = 0; i < dataLength; i += _interval) {

+                    dataTextStyle = zrUtil.merge(

+                        data[i].textStyle || {},

+                        textStyle,

+                        {'overwrite': false}

+                    );

+                    axShape = {

+                        shape : 'text',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            x : getCoord(data[i].value || data[i]),

+                            y : yPosition,

+                            color : dataTextStyle.color,

+                            text : _labelData[i].value || _labelData[i],

+                            textFont : self.getFont(dataTextStyle),

+                            textAlign : 'center',

+                            textBaseline : baseLine

+                        }

+                    };

+                    if (rotate) {

+                        axShape.style.textAlign = rotate > 0

+                                                  ? (option.position == 'bottom'

+                                                    ? 'right' : 'left')

+                                                  : (option.position == 'bottom'

+                                                    ? 'left' : 'right');

+                        axShape.rotation = [

+                            rotate * Math.PI / 180,

+                            axShape.style.x,

+                            axShape.style.y

+                        ];

+                    }

+                    self.shapeList.push(axShape);

+                }

+            }

+            else {

+                // 纵向

+                var xPosition;

+                var align;

+                if (option.position == 'left') {

+                    xPosition = grid.getX() - margin;

+                    align = 'right';

+                }

+                else {

+                    xPosition = grid.getXend() + margin;

+                    align = 'left';

+                }

+

+                for (var i = 0; i < dataLength; i += _interval) {

+                    dataTextStyle = zrUtil.merge(

+                        data[i].textStyle || {},

+                        textStyle,

+                        {'overwrite': false}

+                    );

+                    axShape = {

+                        shape : 'text',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            x : xPosition,

+                            y : getCoord(data[i].value || data[i]),

+                            color : dataTextStyle.color,

+                            text : _labelData[i].value || _labelData[i],

+                            textFont : self.getFont(dataTextStyle),

+                            textAlign : align,

+                            textBaseline : 'middle'

+                        }

+                    };

+                    if (rotate) {

+                        axShape.rotation = [

+                            rotate * Math.PI / 180,

+                            axShape.style.x,

+                            axShape.style.y

+                        ];

+                    }

+                    self.shapeList.push(axShape);

+                }

+            }

+        }

+

+        function _buildSplitLine() {

+            var axShape;

+            var data       = option.data;

+            var dataLength = option.data.length;

+

+            if (option.position == 'bottom' || option.position == 'top') {

+                // 横向

+                var sy = grid.getY();

+                var ey = grid.getYend();

+                var x;

+

+                for (var i = 0; i < dataLength; i += _interval) {

+                    x = getCoord(data[i].value || data[i]);

+                    axShape = {

+                        shape : 'line',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            xStart : x,

+                            yStart : sy,

+                            xEnd : x,

+                            yEnd : ey,

+                            strokeColor : option.splitLine.lineStyle.color,

+                            lineType : option.splitLine.lineStyle.type,

+                            lineWidth : option.splitLine.lineStyle.width

+                        }

+                    };

+                    self.shapeList.push(axShape);

+                }

+

+            }

+            else {

+                // 纵向

+                var sx = grid.getX();

+                var ex = grid.getXend();

+                var y;

+

+                for (var i = 0; i < dataLength; i += _interval) {

+                    y = getCoord(data[i].value || data[i]);

+                    axShape = {

+                        shape : 'line',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            xStart : sx,

+                            yStart : y,

+                            xEnd : ex,

+                            yEnd : y,

+                            strokeColor : option.splitLine.lineStyle.color,

+                            linetype : option.splitLine.lineStyle.type,

+                            lineWidth : option.splitLine.lineStyle.width

+                        }

+                    };

+                    self.shapeList.push(axShape);

+                }

+            }

+        }

+

+        function _buildSplitArea() {

+            var axShape;

+            var color = option.splitArea.areaStyle.color;

+            color = color instanceof Array ? color : [color];

+            var colorLength = color.length;

+            var data        = option.data;

+            var dataLength  = option.data.length;

+

+            if (option.position == 'bottom' || option.position == 'top') {

+                // 横向

+                var y = grid.getY();

+                var height = grid.getHeight();

+                var lastX = grid.getX();

+                var curX;

+

+                for (var i = 0; i <= dataLength; i++) {

+                    curX = i < dataLength

+                           ? getCoord(data[i].value || data[i])

+                           : grid.getXend();

+                    axShape = {

+                        shape : 'rectangle',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            x : lastX,

+                            y : y,

+                            width : curX - lastX,

+                            height : height,

+                            color : color[i % colorLength]

+                            // type : option.splitArea.areaStyle.type,

+                        }

+                    };

+                    self.shapeList.push(axShape);

+                    lastX = curX;

+                }

+            }

+            else {

+                // 纵向

+                var x = grid.getX();

+                var width = grid.getWidth();

+                var lastYend = grid.getYend();

+                var curY;

+

+                for (var i = 0; i <= dataLength; i++) {

+                    curY = i < dataLength

+                           ? getCoord(data[i].value || data[i])

+                           : grid.getY();

+                    axShape = {

+                        shape : 'rectangle',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            x : x,

+                            y : curY,

+                            width : width,

+                            height : lastYend - curY,

+                            color : color[i % colorLength]

+                            // type : option.splitArea.areaStyle.type

+                        }

+                    };

+                    self.shapeList.push(axShape);

+                    lastYend = curY;

+                }

+            }

+        }

+

+        /**

+         * 构造函数默认执行的初始化方法,也用于创建实例后动态修改

+         * @param {Object} newZr

+         * @param {Object} newOption

+         * @param {Object} newGrid

+         */

+        function init(newOption, newGrid) {

+            if (newOption.data.length < 1) {

+                return;

+            }

+

+            option = self.reformOption(newOption);

+            // 通用字体设置

+            option.axisLabel.textStyle = zrUtil.merge(

+                option.axisLabel.textStyle || {},

+                ecConfig.textStyle,

+                {

+                    'overwrite' : false,

+                    'recursive' : true

+                }

+            );

+            option.axisLabel.textStyle = zrUtil.merge(

+                option.axisLabel.textStyle || {},

+                ecConfig.textStyle,

+                {

+                    'overwrite' : false,

+                    'recursive' : true

+                }

+            );

+            grid = newGrid;

+

+            self.clear();

+            _buildShape();

+        }

+

+        /**

+         * 刷新

+         */

+        function refresh() {

+            self.clear();

+            _buildShape();

+        }

+

+        /**

+         * 返回间隔

+         */

+        function getGap() {

+            var dataLength = option.data.length;

+            var total = (option.position == 'bottom'

+                        || option.position == 'top')

+                        ? grid.getWidth()

+                        : grid.getHeight();

+            if (option.boundaryGap) {               // 留空

+                return total / (dataLength + 1);

+            }

+            else {                                  // 顶头

+                return total / (dataLength > 1 ? (dataLength - 1) : 1);

+            }

+        }

+

+        // 根据值换算位置

+        function getCoord(value) {

+            var data = option.data;

+            var dataLength = data.length;

+            var gap = getGap();

+            var position = option.boundaryGap ? gap : 0;

+

+            // Math.floor可能引起一些偏差,但性能会更好

+            for (var i = 0; i < dataLength; i++) {

+                if (data[i] == value

+                    || (data[i].value && data[i].value == value)

+                ) {

+                    if (option.position == 'bottom'

+                        || option.position == 'top'

+                    ) {

+                        // 横向

+                        position = grid.getX() + position;

+                    }

+                    else {

+                        // 纵向

+                        position = grid.getYend() - position;

+                    }

+                    return Math.floor(position);

+                }

+                position += gap;

+            }

+        }

+

+        // 根据类目轴数据索引换算位置

+        function getCoordByIndex(dataIndex) {

+            if (dataIndex < 0) {

+                if (option.position == 'bottom' || option.position == 'top') {

+                    return grid.getX();

+                }

+                else {

+                    return grid.getYend();

+                }

+            }

+            else if (dataIndex >= option.data.length) {

+                if (option.position == 'bottom' || option.position == 'top') {

+                    return grid.getXend();

+                }

+                else {

+                    return grid.getY();

+                }

+            }

+            else {

+                return getCoord(option.data[dataIndex]);

+            }

+        }

+

+        // 根据类目轴数据索引换算类目轴名称

+        function getNameByIndex(dataIndex) {

+            return option.data[dataIndex];

+        }

+

+        /**

+         * 根据类目轴数据索引返回是否为主轴线

+         * @param {number} dataIndex 类目轴数据索引

+         * @return {boolean} 是否为主轴

+         */

+        function isMainAxis(dataIndex) {

+            return dataIndex % _interval === 0;

+        }

+

+        function getPosition() {

+            return option.position;

+        }

+

+        self.init = init;

+        self.refresh = refresh;

+        self.getGap = getGap;

+        self.getCoord = getCoord;

+        self.getCoordByIndex = getCoordByIndex;

+        self.getNameByIndex = getNameByIndex;

+        self.isMainAxis = isMainAxis;

+        self.getPosition = getPosition;

+

+        init(option, grid);

+    }

+

+    return CategoryAxis;

+});
\ No newline at end of file
diff --git a/src/component/dataView.js b/src/component/dataView.js
new file mode 100644
index 0000000..a447929
--- /dev/null
+++ b/src/component/dataView.js
@@ -0,0 +1,431 @@
+/**

+ * echarts组件:提示框

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function (require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} option 提示框参数

+     * @param {HtmlElement} dom 目标对象

+     */

+    function DataView(messageCenter, zr, option, dom) {

+        var Base = require('./base');

+        Base.call(this, zr);

+

+        var ecConfig = require('../config');

+

+        var self = this;

+        self.type = ecConfig.COMPONENT_TYPE_DATAVIEW;

+

+        var _lang = ['Data View', 'close', 'refresh'];

+

+        // dataview dom & css

+        var _tDom = document.createElement('div');

+        var _textArea = document.createElement('textArea');

+        var _buttonRefresh = document.createElement('button');

+        var _buttonClose = document.createElement('button');

+        var _hasShow = false;

+

+        // 通用样式

+        var _gCssText = 'position:absolute;'

+                        + 'display:block;'

+                        + 'overflow:hidden;'

+                        + 'transition:height 0.8s,background-color 1s;;'

+                        + '-moz-transition:height 0.8s,background-color 1s;'

+                        + '-webkit-transition:height 0.8s,background-color 1s;'

+                        + '-o-transition:height 0.8s,background-color 1s;'

+                        + 'z-index:1;'

+                        + 'left:0;'

+                        + 'top:0;';

+        var _sizeCssText;

+        var _cssName = 'echarts-dataview';

+

+        // 缓存一些高宽数据

+        var _zrHeight = zr.getHeight();

+        var _zrWidth = zr.getWidth();

+

+        function hide() {

+            _sizeCssText = 'width:' + _zrWidth + 'px;'

+                           + 'height:' + 0 + 'px;'

+                           + 'background-color:#f0ffff;';

+            _tDom.style.cssText = _gCssText + _sizeCssText;

+            // 这是个很恶心的事情

+            dom.onselectstart = function() {

+                return false;

+            };

+        }

+

+        function show(newOption) {

+            _hasShow = true;

+            var lang = self.deepQuery([option],'toolbox.feature.dataView.lang')

+                       || _lang;

+

+            option = newOption;

+

+

+            _tDom.innerHTML = '<p style="padding:8px 0;margin:0 0 10px 0;'

+                              + 'border-bottom:1px solid #eee">'

+                              + (lang[0] || _lang[0])

+                              + '</p>';

+

+            _textArea.style.cssText =

+                'display:block;margin:0 0 8px 0;padding:4px 6px;overflow:auto;'

+                + 'width:' + (_zrWidth - 15) + 'px;'

+                + 'height:' + (_zrHeight - 100) + 'px;';

+            var customContent = self.deepQuery(

+                [option], 'toolbox.feature.dataView.optionToContent'

+            );

+            if (typeof customContent != 'function') {

+                _textArea.value = _optionToContent();

+            }

+            else {

+                _textArea.value = customContent(option);

+            }

+            _tDom.appendChild(_textArea);

+

+            _buttonClose.style.cssText = 'float:right;padding:1px 6px;';

+            _buttonClose.innerHTML = lang[1] || _lang[1];

+            _buttonClose.onclick = hide;

+            _tDom.appendChild(_buttonClose);

+

+            if (self.deepQuery([option], 'toolbox.feature.dataView.readOnly')

+                === false

+            ) {

+                _buttonRefresh.style.cssText =

+                    'float:right;margin-right:10px;padding:1px 6px;';

+                _buttonRefresh.innerHTML = lang[2] || _lang[2];

+                _buttonRefresh.onclick = _save;

+                _tDom.appendChild(_buttonRefresh);

+                _textArea.readOnly = false;

+                _textArea.style.cursor = 'default';

+            }

+            else {

+                _textArea.readOnly = true;

+                _textArea.style.cursor = 'text';

+            }

+

+            _sizeCssText = 'width:' + _zrWidth + 'px;'

+                           + 'height:' + _zrHeight + 'px;'

+                           + 'background-color:#fff;';

+            _tDom.style.cssText = _gCssText + _sizeCssText;

+

+            // 这是个很恶心的事情

+            dom.onselectstart = function() {

+                return true;

+            };

+        }

+

+        function _optionToContent() {

+            var i;

+            var j;

+            var k;

+            var len;

+            var data;

+            var valueList;

+            var axisList = [];

+            var content = '';

+            if (option.xAxis) {

+                if (option.xAxis instanceof Array) {

+                    axisList = option.xAxis;

+                } else {

+                    axisList = [option.xAxis];

+                }

+                for (i = 0, len = axisList.length; i < len; i++) {

+                    // 横纵默认为类目

+                    if ((axisList[i].type || 'category') == 'category') {

+                        valueList = [];

+                        for (j = 0, k = axisList[i].data.length; j < k; j++) {

+                            data = axisList[i].data[j];

+                            valueList.push(

+                                typeof data.value != 'undefined'

+                                ? data.value : data

+                            );

+                        }

+                        content += valueList.join(', ') + '\n\n';

+                    }

+                }

+            }

+

+            if (option.yAxis) {

+                if (option.yAxis instanceof Array) {

+                    axisList = option.yAxis;

+                } else {

+                    axisList = [option.yAxis];

+                }

+                for (i = 0, len = axisList.length; i < len; i++) {

+                    if (axisList[i].type  == 'category') {

+                        valueList = [];

+                        for (j = 0, k = axisList[i].data.length; j < k; j++) {

+                            data = axisList[i].data[j];

+                            valueList.push(

+                                typeof data.value != 'undefined'

+                                ? data.value : data

+                            );

+                        }

+                        content += valueList.join(', ') + '\n\n';

+                    }

+                }

+            }

+

+            var series = option.series;

+            var itemName;

+            for (i = 0, len = series.length; i < len; i++) {

+                valueList = [];

+                for (j = 0, k = series[i].data.length; j < k; j++) {

+                    data = series[i].data[j];

+                    if (series[i].type == ecConfig.CHART_TYPE_PIE) {

+                        itemName = (data.name || '-') + ':';

+                    }

+                    else {

+                        itemName = '';

+                    }

+                    valueList.push(

+                        itemName

+                        + (typeof data.value != 'undefined' ? data.value : data)

+                    );

+                }

+                content += (series[i].name || '-') + ' : \n';

+                content += valueList.join(', ') + '\n\n';

+            }

+

+            return content;

+        }

+

+        function _save() {

+            var text = _textArea.value;

+            var customContent = self.deepQuery(

+                [option], 'toolbox.feature.dataView.contentToOption'

+            );

+            if (typeof customContent != 'function') {

+                text = text.split('\n');

+                var content = [];

+                for (var i = 0, l = text.length; i < l; i++) {

+                    text[i] = _trim(text[i]);

+                    if (text[i] !== '') {

+                        content.push(text[i]);

+                    }

+                }

+                _contentToOption(content);

+            }

+            else {

+                customContent(text, option);

+            }

+

+            hide();

+

+            setTimeout(

+                function(){

+                    messageCenter && messageCenter.dispatch(

+                        ecConfig.EVENT.DATA_VIEW_CHANGED

+                    );

+                },

+                document.createElement('canvas').getContext ? 800 : 100

+            );

+        }

+

+        function _contentToOption(content) {

+            var i;

+            var j;

+            var k;

+            var len;

+            var data;

+            var axisList = [];

+

+            var contentIdx = 0;

+            var contentValueList;

+            var value;

+

+            if (option.xAxis) {

+                if (option.xAxis instanceof Array) {

+                    axisList = option.xAxis;

+                } else {

+                    axisList = [option.xAxis];

+                }

+                for (i = 0, len = axisList.length; i < len; i++) {

+                    // 横纵默认为类目

+                    if ((axisList[i].type || 'category') == 'category'

+                    ) {

+                        contentValueList = content[contentIdx].split(',');

+                        for (j = 0, k = axisList[i].data.length; j < k; j++) {

+                            value = _trim(contentValueList[j] || '');

+                            data = axisList[i].data[j];

+                            if (typeof axisList[i].data[j].value != 'undefined'

+                            ) {

+                                axisList[i].data[j].value = value;

+                            }

+                            else {

+                                axisList[i].data[j] = value;

+                            }

+                        }

+                        contentIdx++;

+                    }

+                }

+            }

+

+            if (option.yAxis) {

+                if (option.yAxis instanceof Array) {

+                    axisList = option.yAxis;

+                } else {

+                    axisList = [option.yAxis];

+                }

+                for (i = 0, len = axisList.length; i < len; i++) {

+                    if (axisList[i].type  == 'category') {

+                        contentValueList = content[contentIdx].split(',');

+                        for (j = 0, k = axisList[i].data.length; j < k; j++) {

+                            value = _trim(contentValueList[j] || '');

+                            data = axisList[i].data[j];

+                            if (typeof axisList[i].data[j].value != 'undefined'

+                            ) {

+                                axisList[i].data[j].value = value;

+                            }

+                            else {

+                                axisList[i].data[j] = value;

+                            }

+                        }

+                        contentIdx++;

+                    }

+                }

+            }

+

+            var series = option.series;

+            for (i = 0, len = series.length; i < len; i++) {

+                contentIdx++;

+                contentValueList = content[contentIdx].split(',');

+                for (var j = 0, k = series[i].data.length; j < k; j++) {

+                    value = (contentValueList[j] || '').replace(/.*:/,'');

+                    value = _trim(value);

+                    value = (value != '-' && value !== '')

+                            ? (value - 0)

+                            : '-';

+                    if (typeof series[i].data[j].value != 'undefined'

+                    ) {

+                        series[i].data[j].value = value;

+

+                    }

+                    else {

+                        series[i].data[j] = value;

+                    }

+                }

+                contentIdx++;

+            }

+        }

+

+        function _trim(str){

+            var trimer = new RegExp(

+                '(^[\\s\\t\\xa0\\u3000]+)|([\\u3000\\xa0\\s\\t]+\x24)', 'g'

+            );

+            return str.replace(trimer, '');

+        }

+

+        // 阻塞zrender事件

+        function _stop(e){

+            e = e || window.event;

+            if (e.stopPropagation) {

+                e.stopPropagation();

+            }

+            else {

+                e.cancelBubble = true;

+            }

+        }

+

+        function _init() {

+            _tDom.className = _cssName;

+            hide();

+            dom.firstChild.appendChild(_tDom);

+

+            if (window.addEventListener) {

+                _tDom.addEventListener('click', _stop);

+                _tDom.addEventListener('mousewheel', _stop);

+                _tDom.addEventListener('mousemove', _stop);

+                _tDom.addEventListener('mousedown', _stop);

+                _tDom.addEventListener('mouseup', _stop);

+

+                // mobile支持

+                _tDom.addEventListener('touchstart', _stop);

+                _tDom.addEventListener('touchmove', _stop);

+                _tDom.addEventListener('touchend', _stop);

+            }

+            else {

+                _tDom.attachEvent('onclick', _stop);

+                _tDom.attachEvent('onmousewheel', _stop);

+                _tDom.attachEvent('onmousemove', _stop);

+                _tDom.attachEvent('onmousedown', _stop);

+                _tDom.attachEvent('onmouseup', _stop);

+            }

+        }

+

+        /**

+         * zrender事件响应:窗口大小改变

+         */

+        function resize() {

+            _zrHeight = zr.getHeight();

+            _zrWidth = zr.getWidth();

+            if (_tDom.offsetHeight > 10) {

+                _sizeCssText = 'width:' + _zrWidth + 'px;'

+                               + 'height:' + _zrHeight + 'px;'

+                               + 'background-color:#fff;';

+                _tDom.style.cssText = _gCssText + _sizeCssText;

+            }

+        }

+

+        /**

+         * 释放后实例不可用,重载基类方法

+         */

+        function dispose() {

+            if (window.removeEventListener) {

+                _tDom.removeEventListener('click', _stop);

+                _tDom.removeEventListener('mousewheel', _stop);

+                _tDom.removeEventListener('mousemove', _stop);

+                _tDom.removeEventListener('mousedown', _stop);

+                _tDom.removeEventListener('mouseup', _stop);

+

+                // mobile支持

+                _tDom.removeEventListener('touchstart', _stop);

+                _tDom.removeEventListener('touchmove', _stop);

+                _tDom.removeEventListener('touchend', _stop);

+            }

+            else {

+                _tDom.detachEvent('onclick', _stop);

+                _tDom.detachEvent('onmousewheel', _stop);

+                _tDom.detachEvent('onmousemove', _stop);

+                _tDom.detachEvent('onmousedown', _stop);

+                _tDom.detachEvent('onmouseup', _stop);

+            }

+

+            _buttonRefresh.onclick = null;

+            _buttonClose.onclick = null;

+

+            if (_hasShow) {

+                _tDom.removeChild(_textArea);

+                _tDom.removeChild(_buttonRefresh);

+                _tDom.removeChild(_buttonClose);

+            }

+

+            _textArea = null;

+            _buttonRefresh = null;

+            _buttonClose = null;

+

+            dom.firstChild.removeChild(_tDom);

+            _tDom = null;

+            self = null;

+        }

+

+

+        // 重载基类方法

+        self.dispose = dispose;

+

+        self.resize = resize;

+        self.show = show;

+        self.hide = hide;

+

+        _init();

+    }

+

+    return DataView;

+});
\ No newline at end of file
diff --git a/src/component/dataZoom.js b/src/component/dataZoom.js
new file mode 100644
index 0000000..9d5a407
--- /dev/null
+++ b/src/component/dataZoom.js
@@ -0,0 +1,673 @@
+/**

+ * echarts组件:数据区域缩放

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function (require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} option 图表参数

+     * @param {Object} component 组件

+     */

+    function DataZoom(messageCenter, zr, option, component) {

+        var Base = require('./base');

+        Base.call(this, zr);

+

+        var ecConfig = require('../config');

+

+        var self = this;

+        self.type = ecConfig.COMPONENT_TYPE_DATAZOOM;

+

+        var _zlevelBase = self.getZlevelBase();

+

+        var zoomOption;

+

+        var _fillerSize = 30;       // 填充大小

+        var _handleSize = 10;       // 手柄大小

+        var _location;              // 位置参数,通过计算所得x, y, width, height

+        var _zoom;                  // 缩放参数

+        var _fillerShae;

+        var _startShape;

+        var _endShape;

+

+        var _syncTicket;

+

+        var _originalData;

+

+        function _buildShape() {

+            _location = _getLocation();

+            _zoom =  _getZoom();

+            _backupData();

+

+            _buildBackground();

+            _buildDataBackground();

+            _buildFiller();

+            _bulidHandle();

+

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                self.shapeList[i].id = zr.newShapeId(self.type);

+                zr.addShape(self.shapeList[i]);

+            }

+

+            _syncData();

+        }

+

+        /**

+         * 根据选项计算实体的位置坐标

+         */

+        function _getLocation() {

+            var x;

+            var y;

+            var width;

+            var height;

+            var grid = component.grid;

+

+            // 不指定则根据grid适配

+            if (zoomOption.orient == 'horizontal') {

+                // 水平布局

+                width = zoomOption.width || grid.getWidth();

+                height = zoomOption.height || _fillerSize;

+                x = typeof zoomOption.x != 'undefined'

+                    ? zoomOption.x : grid.getX();

+                y = typeof zoomOption.y != 'undefined'

+                    ? zoomOption.y : (zr.getHeight() - height);

+            }

+            else {

+                // 垂直布局

+                width = zoomOption.width || _fillerSize;

+                height = zoomOption.height || grid.getHeight();

+                x = typeof zoomOption.x != 'undefined'

+                    ? zoomOption.x : 0;

+                y = typeof zoomOption.y != 'undefined'

+                    ? zoomOption.y : grid.getY();

+            }

+

+            return {

+                x : x,

+                y : y,

+                width : width,

+                height : height

+            };

+        }

+

+        /**

+         * 计算缩放参数

+         * 修正单坐标轴只传对象为数组。

+         */

+        function _getZoom() {

+            var series = option.series;

+            var xAxis = option.xAxis;

+            if (xAxis && !(xAxis instanceof Array)) {

+                xAxis = [xAxis];

+                option.xAxis = xAxis;

+            }

+            var yAxis = option.yAxis;

+            if (yAxis && !(yAxis instanceof Array)) {

+                yAxis = [yAxis];

+                option.yAxis = yAxis;

+            }

+

+            var zoomSeriesIndex = [];

+            var xAxisIndex;

+            var yAxisIndex;

+

+            var zOptIdx = zoomOption.xAxisIndex;

+            if (xAxis && typeof zOptIdx == 'undefined') {

+                xAxisIndex = [];

+                for (var i = 0, l = xAxis.length; i < l; i++) {

+                    // 横纵默认为类目轴

+                    if (xAxis[i].type == 'category'

+                        || typeof xAxis[i].type == 'undefined'

+                    ) {

+                        xAxisIndex.push(i);

+                    }

+                }

+            }

+            else {

+                if (zOptIdx instanceof Array) {

+                    xAxisIndex = zOptIdx;

+                }

+                else if (typeof zOptIdx != 'undefined') {

+                    xAxisIndex = [zOptIdx];

+                }

+                else {

+                    xAxisIndex = [];

+                }

+            }

+

+            zOptIdx = zoomOption.yAxisIndex;

+            if (yAxis && typeof zOptIdx == 'undefined') {

+                yAxisIndex = [];

+                for (var i = 0, l = yAxis.length; i < l; i++) {

+                    if (yAxis[i].type == 'category') {

+                        yAxisIndex.push(i);

+                    }

+                }

+            }

+            else {

+                if (zOptIdx instanceof Array) {

+                    yAxisIndex = zOptIdx;

+                }

+                else if (typeof zOptIdx != 'undefined') {

+                    yAxisIndex = [zOptIdx];

+                }

+                else {

+                    yAxisIndex = [];

+                }

+            }

+

+            // 找到缩放控制的所有series

+            for (var i = 0, l = series.length; i < l; i++) {

+                for (var j = 0, k = xAxisIndex.length; j < k; j++) {

+                    if (xAxisIndex[j] == (series[i].xAxisIndex || 0)) {

+                        zoomSeriesIndex.push(i);

+                        break;

+                    }

+                }

+                for (var j = 0, k = yAxisIndex.length; j < k; j++) {

+                    if (yAxisIndex[j] == (series[i].yAxisIndex || 0)) {

+                        zoomSeriesIndex.push(i);

+                        break;

+                    }

+                }

+            }

+

+            var start = typeof zoomOption.start != 'undefined'

+                        && zoomOption.start >= 0

+                        && zoomOption.start <= 100

+                        ? zoomOption.start : 0;

+            var end = typeof zoomOption.end != 'undefined'

+                      && zoomOption.end >= 0

+                      && zoomOption.end <= 100

+                      ? zoomOption.end : 100;

+            if (start > end) {

+                // 大小颠倒自动翻转

+                start = start + end;

+                end = start - end;

+                start = start - end;

+            }

+            var size = Math.round(

+                           (end - start) / 100

+                           * (zoomOption.orient == 'horizontal'

+                             ? _location.width : _location.height)

+                       );

+            return {

+                start : start,

+                end : end,

+                size : size,

+                xAxisIndex : xAxisIndex,

+                yAxisIndex : yAxisIndex,

+                seriesIndex : zoomSeriesIndex

+            };

+        }

+

+        function _backupData() {

+            _originalData = {

+                xAxis : {},

+                yAxis : {},

+                series : {}

+            };

+            var xAxis = option.xAxis;

+            var xAxisIndex = _zoom.xAxisIndex;

+            for (var i = 0, l = xAxisIndex.length; i < l; i++) {

+                _originalData.xAxis[xAxisIndex[i]] = xAxis[xAxisIndex[i]].data;

+            }

+

+            var yAxis = option.yAxis;

+            var yAxisIndex = _zoom.yAxisIndex;

+            for (var i = 0, l = yAxisIndex.length; i < l; i++) {

+                _originalData.yAxis[yAxisIndex[i]] = yAxis[yAxisIndex[i]].data;

+            }

+

+            var series = option.series;

+            var seriesIndex = _zoom.seriesIndex;

+            for (var i = 0, l = seriesIndex.length; i < l; i++) {

+                _originalData.series[seriesIndex[i]]

+                    = series[seriesIndex[i]].data;

+            }

+        }

+

+        function _buildBackground() {

+            self.shapeList.push({

+                shape : 'rectangle',

+                zlevel : _zlevelBase,

+                hoverable :false,

+                style : {

+                    x : _location.x,

+                    y : _location.y,

+                    width : _location.width,

+                    height : _location.height,

+                    color : zoomOption.backgroundColor

+                }

+            });

+        }

+

+        function _buildDataBackground() {

+            self.shapeList.push({

+                shape : 'rectangle',

+                zlevel : _zlevelBase,

+                hoverable :false,

+                style : {

+                    x : _location.x,

+                    y : _location.y,

+                    width : _location.width,

+                    height : _location.height,

+                    color : zoomOption.backgroundColor

+                }

+            });

+

+            var maxLength = 0;

+            var xAxis = option.xAxis;

+            var xAxisIndex = _zoom.xAxisIndex;

+            for (var i = 0, l = xAxisIndex.length; i < l; i++) {

+                maxLength = Math.max(

+                    maxLength, xAxis[xAxisIndex[i]].data.length

+                );

+            }

+            var yAxis = option.yAxis;

+            var yAxisIndex = _zoom.yAxisIndex;

+            for (var i = 0, l = yAxisIndex.length; i < l; i++) {

+                maxLength = Math.max(

+                    maxLength, yAxis[yAxisIndex[i]].data.length

+                );

+            }

+

+            var data = option.series[_zoom.seriesIndex[0]].data;

+            var maxValue = Number.MIN_VALUE;

+            var minValue = Number.MAX_VALUE;

+            var value;

+            for (var i = 0, l = data.length; i < l; i++) {

+                value = typeof data[i] != 'undefined'

+                        ? (typeof data[i].value != 'undefined'

+                          ? data[i].value : data[i])

+                        : 0;

+                if (isNaN(value)) {

+                    value = 0;

+                }

+                maxValue = Math.max(maxValue, value);

+                minValue = Math.min(minValue, value);

+            }

+

+            var pointList = [];

+            var x = _location.width / maxLength;

+            var y = _location.height / maxLength;

+            for (var i = 0, l = maxLength; i < l; i++) {

+                value = typeof data[i] != 'undefined'

+                        ? (typeof data[i].value != 'undefined'

+                          ? data[i].value : data[i])

+                        : 0;

+                if (isNaN(value)) {

+                    value = 0;

+                }

+                if (zoomOption.orient == 'horizontal') {

+                    pointList.push([

+                        _location.x + x * i,

+                        _location.y + _location.height - 5 - Math.round(

+                            (value - minValue)

+                            / (maxValue - minValue)

+                            * (_location.height - 10)

+                        )

+                    ]);

+                }

+                else {

+                    pointList.push([

+                        _location.x + 5 + Math.round(

+                            (value - minValue)

+                            / (maxValue - minValue)

+                            * (_location.width - 10)

+                        ),

+                        _location.y + y * i

+                    ]);

+                }

+            }

+            if (zoomOption.orient == 'horizontal') {

+                 pointList.push([

+                    _location.x + _location.width,

+                    _location.y + _location.height

+                ]);

+                pointList.push([

+                    _location.x, _location.y + _location.height

+                ]);

+            }

+            else {

+                pointList.push([

+                    _location.x, _location.y + _location.height

+                ]);

+                pointList.push([

+                    _location.x, _location.y

+                ]);

+            }

+

+            self.shapeList.push({

+                shape : 'polygon',

+                zlevel : _zlevelBase,

+                style : {

+                    pointList : pointList,

+                    color : zoomOption.dataBackgroundColor

+                },

+                hoverable : false

+            });

+        }

+

+        /**

+         * 构建填充物

+         */

+        function _buildFiller() {

+            _fillerShae = {

+                shape : 'rectangle',

+                zlevel : _zlevelBase,

+                draggable : true,

+                ondrift : _ondrift,

+                ondragend : _ondragend,

+                _type : 'filler'

+            };

+

+            if (zoomOption.orient == 'horizontal') {

+                // 横向

+                _fillerShae.style = {

+                    x : _location.x

+                        + Math.round(_zoom.start / 100 * _location.width)

+                        + _handleSize,

+                    y : _location.y + 3,

+                    width : _zoom.size - _handleSize * 2,

+                    height : _location.height - 6,

+                    color : zoomOption.fillerColor,

+                    text : ':::',

+                    textPosition : 'inside'

+                };

+            }

+            else {

+                _fillerShae.style ={

+                    x : _location.x + 3,

+                    y : _location.y

+                        + Math.round(_zoom.start / 100 * _location.height)

+                        + _handleSize,

+                    width :  _location.width - 6,

+                    height : _zoom.size - _handleSize * 2,

+                    color : zoomOption.fillerColor,

+                    text : '=',

+                    textPosition : 'inside'

+                };

+            }

+

+            self.shapeList.push(_fillerShae);

+        }

+

+        /**

+         * 构建拖拽手柄

+         */

+        function _bulidHandle() {

+            _startShape = {

+                shape : 'rectangle',

+                zlevel : _zlevelBase

+            };

+            _endShape = {

+                shape : 'rectangle',

+                zlevel : _zlevelBase

+            };

+

+            if (!zoomOption.zoomLock) {

+                _startShape.draggable = true;

+                _startShape.ondrift = _ondrift;

+                _startShape.ondragend = _ondragend;

+                _endShape.draggable = true;

+                _endShape.ondrift = _ondrift;

+                _endShape.ondragend = _ondragend;

+            }

+

+            if (zoomOption.orient == 'horizontal') {

+                // 头

+                _startShape.style = {

+                    x : _fillerShae.style.x - _handleSize,

+                    y : _location.y,

+                    width : _handleSize,

+                    height : _location.height,

+                    color : zoomOption.handleColor,

+                    text : '|',

+                    textPosition : 'inside'

+                };

+                // 尾

+                _endShape.style = {

+                    x : _fillerShae.style.x + _fillerShae.style.width,

+                    y : _location.y,

+                    width : _handleSize,

+                    height : _location.height,

+                    color : zoomOption.handleColor,

+                    text : '|',

+                    textPosition : 'inside'

+                };

+            }

+            else {

+                // 头

+                _startShape.style = {

+                    x : _location.x,

+                    y : _fillerShae.style.y - _handleSize,

+                    width : _location.width,

+                    height : _handleSize,

+                    color : zoomOption.handleColor,

+                    text : '—',

+                    textPosition : 'inside'

+                };

+                // 尾

+                _endShape.style = {

+                    x : _location.x,

+                    y : _fillerShae.style.y + _fillerShae.style.height,

+                    width : _location.width,

+                    height : _handleSize,

+                    color : zoomOption.handleColor,

+                    text : '—',

+                    textPosition : 'inside'

+                };

+            }

+

+            self.shapeList.push(_startShape);

+            self.shapeList.push(_endShape);

+        }

+

+        /**

+         * 拖拽范围控制

+         */

+        function _ondrift(e, dx, dy) {

+            var detailSize = e._type == 'filler' ? _handleSize : 0;

+            if (zoomOption.orient == 'horizontal') {

+                if (e.style.x + dx - detailSize <= _location.x) {

+                    e.style.x = _location.x + detailSize;

+                }

+                else if (e.style.x + dx + e.style.width + detailSize

+                         >= _location.x + _location.width

+                ) {

+                    e.style.x = _location.x + _location.width

+                                - e.style.width - detailSize;

+                }

+                else {

+                    e.style.x += dx;

+                }

+            }

+            else {

+                if (e.style.y + dy - detailSize <= _location.y) {

+                    e.style.y = _location.y + detailSize;

+                }

+                else if (e.style.y + dy + e.style.height + detailSize

+                         >= _location.y + _location.height

+                ) {

+                    e.style.y = _location.y + _location.height

+                                - e.style.height - detailSize;

+                }

+                else {

+                    e.style.y += dy;

+                }

+            }

+

+            if (e._type == 'filler') {

+                _syncHandleShape();

+            }

+            else {

+                _syncFillerShape();

+            }

+

+            if (zoomOption.realtime) {

+                _syncData();

+            }

+            else {

+                clearTimeout(_syncTicket);

+                _syncTicket = setTimeout(_syncData, 200);

+            }

+

+            return true;

+        }

+

+        function _syncHandleShape() {

+            if (zoomOption.orient == 'horizontal') {

+                _startShape.style.x = _fillerShae.style.x - _handleSize;

+                _endShape.style.x = _fillerShae.style.x

+                                    + _fillerShae.style.width;

+                _zoom.start = Math.floor(

+                    (_startShape.style.x - _location.x)

+                    / _location.width * 100

+                );

+                _zoom.end = Math.ceil(

+                    (_endShape.style.x + _handleSize - _location.x)

+                    / _location.width * 100

+                );

+            }

+            else {

+                _startShape.style.y = _fillerShae.style.y - _handleSize;

+                _endShape.style.y = _fillerShae.style.y

+                                    + _fillerShae.style.height;

+                _zoom.start = Math.floor(

+                    (_startShape.style.y - _location.y)

+                    / _location.height * 100

+                );

+                _zoom.end = Math.ceil(

+                    (_endShape.style.y + _handleSize - _location.y)

+                    / _location.height * 100

+                );

+            }

+

+            zr.modShape(_startShape.id, _startShape);

+            zr.modShape(_endShape.id, _endShape);

+            zr.refresh();

+        }

+

+        function _syncFillerShape() {

+            var a;

+            var b;

+            if (zoomOption.orient == 'horizontal') {

+                a = _startShape.style.x;

+                b = _endShape.style.x;

+                _fillerShae.style.x = Math.min(a, b) + _handleSize;

+                _fillerShae.style.width = Math.abs(a - b) - _handleSize;

+                _zoom.start = Math.floor(

+                    (Math.min(a, b) - _location.x)

+                    / _location.width * 100

+                );

+                _zoom.end = Math.ceil(

+                    (Math.max(a, b) + _handleSize - _location.x)

+                    / _location.width * 100

+                );

+            }

+            else {

+                a = _startShape.style.y;

+                b = _endShape.style.y;

+                _fillerShae.style.y = Math.min(a, b) + _handleSize;

+                _fillerShae.style.height = Math.abs(a - b) - _handleSize;

+                _zoom.start = Math.floor(

+                    (Math.min(a, b) - _location.y)

+                    / _location.height * 100

+                );

+                _zoom.end = Math.ceil(

+                    (Math.max(a, b) + _handleSize - _location.y)

+                    / _location.height * 100

+                );

+            }

+

+            zr.modShape(_fillerShae.id, _fillerShae);

+            zr.refresh();

+        }

+

+        function  _syncData() {

+            var target;

+            var start;

+            var end;

+            var length;

+            var data;

+            for (var key in _originalData) {

+                target = _originalData[key];

+                for (var idx in target) {

+                    data = target[idx];

+                    length = data.length;

+                    start = Math.floor(_zoom.start / 100 * length);

+                    end = Math.ceil(_zoom.end / 100 * length);

+                    option[key][idx].data = data.slice(start, end);

+                }

+            }

+

+            if (zoomOption.realtime) {

+                messageCenter.dispatch(ecConfig.EVENT.DATA_ZOOM);

+            }

+

+            zoomOption.start = _zoom.start;

+            zoomOption.end = _zoom.end;

+        }

+

+        function _ondragend() {

+            self.isDragend = true;

+        }

+

+        /**

+         * 数据项被拖拽出去

+         */

+        function ondragend(param, status) {

+            if (!self.isDragend || !param.target) {

+                // 没有在当前实例上发生拖拽行为则直接返回

+                return;

+            }

+

+             _syncData();

+

+            // 别status = {}赋值啊!!

+            status.dragOut = true;

+            status.dragIn = true;

+            if (!zoomOption.realtime) {

+                messageCenter.dispatch(ecConfig.EVENT.DATA_ZOOM);

+            }

+            status.needRefresh = false; // 会有消息触发fresh,不用再刷一遍

+            // 处理完拖拽事件后复位

+            self.isDragend = false;

+

+            return;

+        }

+

+        function ondataZoom(param, status) {

+            status.needRefresh = true;

+            return;

+        }

+

+        function init(newOption) {

+            option = newOption;

+

+            option.dataZoom = self.reformOption(option.dataZoom);

+

+            zoomOption = option.dataZoom;

+

+            self.clear();

+

+            if (option.dataZoom.show) {

+                _buildShape();

+            }

+        }

+

+        self.init = init;

+        self.ondragend = ondragend;

+        self.ondataZoom = ondataZoom;

+

+        init(option);

+    }

+

+    return DataZoom;

+});
\ No newline at end of file
diff --git a/src/component/grid.js b/src/component/grid.js
new file mode 100644
index 0000000..f64caa0
--- /dev/null
+++ b/src/component/grid.js
@@ -0,0 +1,128 @@
+/**

+ * echarts组件: 网格

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function (require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} option 图表选项

+     *      @param {number=} option.grid.x 直角坐标系内绘图网格起始横坐标,数值单位px

+     *      @param {number=} option.grid.y 直角坐标系内绘图网格起始纵坐标,数值单位px

+     *      @param {number=} option.grid.width 直角坐标系内绘图网格宽度,数值单位px

+     *      @param {number=} option.grid.height 直角坐标系内绘图网格高度,数值单位px

+     */

+    function Grid(messageCenter, zr, option) {

+        var Base = require('./base');

+        Base.call(this, zr);

+

+        var ecConfig = require('../config');

+

+        var self = this;

+        self.type = ecConfig.COMPONENT_TYPE_GRID;

+

+        var _zlevelBase = self.getZlevelBase();

+

+        var _x;

+        var _y;

+        var _width;

+        var _height;

+

+        /**

+         * 构造函数默认执行的初始化方法,也用于创建实例后动态修改

+         * @param {Object} newZr

+         * @param {Object} newOption

+         */

+        function init(newOption) {

+            option = newOption;

+

+            option.grid = self.reformOption(option.grid);

+

+            var gridOption = option.grid;

+            _x = gridOption.x;

+            _y = gridOption.y;

+

+            if (typeof gridOption.width == 'undefined') {

+                _width = zr.getWidth() - (_x * 2);

+            }

+            else {

+                _width = gridOption.width;

+            }

+

+            if (typeof gridOption.height == 'undefined') {

+                _height = zr.getHeight() - (_y * 2);

+            }

+            else {

+                _height = gridOption.height;

+            }

+

+            zr.addShape({

+                shape : 'rectangle',

+                id : zr.newShapeId('grid'),

+                zlevel : _zlevelBase,

+                hoverable : false,

+                style : {

+                    x : _x,

+                    y : _y,

+                    width : _width,

+                    height : _height,

+                    brushType : 'both',

+                    color : gridOption.backgroundColor,

+                    strokeColor: gridOption.borderColor,

+                    lineWidth : gridOption.borderWidth

+                    // type : option.splitArea.areaStyle.type,

+                }

+            });

+        }

+

+        function getX() {

+            return _x;

+        }

+

+        function getY() {

+            return _y;

+        }

+

+        function getWidth() {

+            return _width;

+        }

+

+        function getHeight() {

+            return _height;

+        }

+

+        function getXend() {

+            return _x + _width;

+        }

+

+        function getYend() {

+            return _y + _height;

+        }

+

+        function getArea() {

+            return {

+                x : _x,

+                y : _y,

+                width : _width,

+                height : _height

+            };

+        }

+        self.init = init;

+        self.getX = getX;

+        self.getY = getY;

+        self.getWidth = getWidth;

+        self.getHeight = getHeight;

+        self.getXend = getXend;

+        self.getYend = getYend;

+        self.getArea = getArea;

+

+        init(option);

+    }

+

+    return Grid;

+});
\ No newline at end of file
diff --git a/src/component/legend.js b/src/component/legend.js
new file mode 100644
index 0000000..b03473f
--- /dev/null
+++ b/src/component/legend.js
@@ -0,0 +1,493 @@
+/**

+ * echarts组件:图例

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function (require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} option 图表参数

+     * @param {Object=} selected 用于状态保持

+     */

+    function Legend(messageCenter, zr, option, selected) {

+        var Base = require('./base');

+        Base.call(this, zr);

+

+        var ecConfig = require('../config');

+        var zrArea = require('zrender/tool/area');

+

+        var self = this;

+        self.type = ecConfig.COMPONENT_TYPE_LEGEND;

+

+        var legendOption;                       // 图例选项,共享数据源

+        var _zlevelBase = self.getZlevelBase();

+

+        var _itemGroupLocation = {};    // 图例元素组的位置参数,通过计算所得x, y, width, height

+

+        var _colorIndex = 0;

+        var _colorMap = {};

+        var _selectedMap = {};

+

+

+        function _buildShape() {

+            _itemGroupLocation = _getItemGroupLocation();

+

+            _buildBackground();

+            _buildItem();

+

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                self.shapeList[i].id = zr.newShapeId(self.type);

+                zr.addShape(self.shapeList[i]);

+            }

+        }

+

+        /**

+         * 构建所有图例元素

+         */

+        function _buildItem() {

+            var data = legendOption.data;

+            var dataLength = data.length;

+            var itemName;

+            var itemType;

+            var itemShape;

+            var textShape;

+            var font = self.getFont(legendOption.textStyle);

+

+            var zrWidth = zr.getWidth();

+            var lastX = _itemGroupLocation.x;

+            var lastY = _itemGroupLocation.y;

+            var itemWidth = legendOption.itemWidth;

+            var itemHeight = legendOption.itemHeight;

+            var itemGap = legendOption.itemGap;

+            var color;

+

+            if (legendOption.orient == 'vertical'

+                && legendOption.x == 'right'

+            ) {

+                lastX = _itemGroupLocation.x

+                        + _itemGroupLocation.width

+                        - itemWidth;

+            }

+

+            for (var i = 0; i < dataLength; i++) {

+                itemName = data[i];

+                itemType = _getSeriesByName(itemName);

+                if (itemType) {

+                    itemType = itemType.type;

+                } else {

+                    itemType = '';

+                }

+                color = getColor(itemName);

+

+                if (legendOption.orient == 'horizontal') {

+                    if (zrWidth - lastX < 200   // 最后200px做分行预判

+                        && (itemWidth + 5

+                         + zrArea.getTextWidth(itemName, font)

+                         + itemGap)

+                        >= zrWidth - lastX

+                    ) {

+                        lastX = 0;

+                        lastY += itemHeight + itemGap;

+                    }

+                }

+

+                // 图形

+                itemShape = _getItemShapeByType(

+                    lastX, lastY,

+                    itemWidth, itemHeight,

+                    (_selectedMap[itemName]

+                     ? color : '#ccc'),

+                    itemType,

+                    _selectedMap[itemName]

+                );

+                itemShape._name = itemName;

+                itemShape.onclick = _legendSelected;

+                self.shapeList.push(itemShape);

+

+                // 文字

+                textShape = {

+                    shape : 'text',

+                    zlevel : _zlevelBase,

+                    style : {

+                        x : lastX + itemWidth + 5,

+                        y : lastY,

+                        color : _selectedMap[itemName]

+                                ? legendOption.textStyle.color

+                                : '#ccc',

+                        text: itemName,

+                        textFont: font,

+                        textBaseline: 'top'

+                    },

+                    clickable : true

+                };

+

+                if (legendOption.orient == 'vertical'

+                    && legendOption.x == 'right'

+                ) {

+                    textShape.style.x -= (itemWidth + 10);

+                    textShape.style.textAlign = 'right';

+                }

+

+                textShape._name = itemName;

+                textShape.onclick = _legendSelected;

+                self.shapeList.push(textShape);

+

+                if (legendOption.orient == 'horizontal') {

+                    lastX += itemWidth + 5

+                             + zrArea.getTextWidth(itemName, font)

+                             + itemGap;

+                }

+                else {

+                    lastY += itemHeight + itemGap;

+                }

+            }

+        }

+

+        function _buildBackground() {

+            var pTop = legendOption.padding[0];

+            var pRight = legendOption.padding[1];

+            var pBottom = legendOption.padding[2];

+            var pLeft = legendOption.padding[3];

+

+            self.shapeList.push({

+                shape : 'rectangle',

+                zlevel : _zlevelBase,

+                hoverable :false,

+                style : {

+                    x : _itemGroupLocation.x - pLeft,

+                    y : _itemGroupLocation.y - pTop,

+                    width : _itemGroupLocation.width + pLeft + pRight,

+                    height : _itemGroupLocation.height + pTop + pBottom,

+                    brushType : legendOption.borderWidth === 0

+                                ? 'fill' : 'both',

+                    color : legendOption.backgroundColor,

+                    strokeColor : legendOption.borderColor,

+                    lineWidth : legendOption.borderWidth

+                }

+            });

+        }

+

+        /**

+         * 根据选项计算图例实体的位置坐标

+         */

+        function _getItemGroupLocation() {

+            var data = legendOption.data;

+            var dataLength = data.length;

+            var itemGap = legendOption.itemGap;

+            var itemWidth = legendOption.itemWidth + 5; // 5px是图形和文字的间隔,不可配

+            var itemHeight = legendOption.itemHeight;

+            var totalWidth = 0;

+            var totalHeight = 0;

+

+            if (legendOption.orient == 'horizontal') {

+                // 水平布局,计算总宽度

+                for (var i = 0; i < dataLength; i++) {

+                    totalWidth += itemWidth

+                                  + zrArea.getTextWidth(

+                                        data[i],

+                                        self.getFont()

+                                    )

+                                  + itemGap;

+                }

+                totalWidth -= itemGap;      // 减去最后一个的itemGap

+                totalHeight = itemHeight;

+            }

+            else {

+                // 垂直布局,计算总高度

+                totalHeight = (itemHeight + itemGap) * dataLength;

+                totalHeight -= itemGap;     // 减去最后一个的itemGap;

+                var maxWidth = 0;

+                for (var i = 0; i < dataLength; i++) {

+                    maxWidth = Math.max(

+                        maxWidth,

+                        zrArea.getTextWidth(

+                            data[i],

+                            self.getFont()

+                        )

+                    );

+                }

+                totalWidth = itemWidth + maxWidth;

+            }

+

+            var x;

+            var zrWidth = zr.getWidth();

+            switch (legendOption.x) {

+                case 'center' :

+                    x = Math.floor((zrWidth - totalWidth) / 2);

+                    break;

+                case 'left' :

+                    x = legendOption.padding[3] + legendOption.borderWidth;

+                    break;

+                case 'right' :

+                    x = zrWidth

+                        - totalWidth

+                        - legendOption.padding[1]

+                        - legendOption.borderWidth;

+                    break;

+                default :

+                    x = legendOption.x - 0;

+                    break;

+            }

+

+            var y;

+            var zrHeight = zr.getHeight();

+            switch (legendOption.y) {

+                case 'top' :

+                    y = legendOption.padding[0] + legendOption.borderWidth;

+                    break;

+                case 'bottom' :

+                    y = zrHeight

+                        - totalHeight

+                        - legendOption.padding[2]

+                        - legendOption.borderWidth;

+                    break;

+                case 'center' :

+                    y = Math.floor((zrHeight - totalHeight) / 2);

+                    break;

+                default :

+                    y = legendOption.y - 0;

+                    break;

+            }

+

+            // 水平布局的横向超长自动分行,纵布局超长不考虑

+            if (legendOption.orient == 'horizontal' && totalWidth > zrWidth) {

+                totalWidth = zrWidth;

+                if (x < 0) {

+                    x = 0;

+                }

+                totalHeight += totalHeight + 10;

+            }

+

+

+            return {

+                x : x,

+                y : y,

+                width : totalWidth,

+                height : totalHeight

+            };

+        }

+

+        /**

+         * 根据名称返回series数据

+         */

+        function _getSeriesByName(name) {

+            var series = option.series;

+            for (var i = 0, l = series.length; i < l; i++) {

+                if (series[i].name == name) {

+                    // 系列名称优先

+                    return series[i];

+                }

+

+                if (series[i].type == ecConfig.CHART_TYPE_PIE) {

+                    // 饼图得查找里面的数据名字

+                    var hasFind = false;

+                    var data = series[i].data;

+                    for (var j = 0, k = data.length; j < k; j++) {

+                        if (data[j].name == name) {

+                            hasFind = true;

+                            break;

+                        }

+                    }

+                    if (hasFind) {

+                        return series[i];

+                    }

+                }

+            }

+            return;

+        }

+

+        function _getItemShapeByType(x, y, width, height, color, itemType) {

+            switch (itemType) {

+                case 'line' :

+                    return {

+                        shape : 'line',

+                        zlevel : _zlevelBase,

+                        style : {

+                            xStart : x,

+                            yStart : y + height / 2,

+                            xEnd : x + width,

+                            yEnd : y + height / 2,

+                            strokeColor : color,

+                            lineWidth : 5

+                        },

+                        clickable : true

+                    };

+                case 'pie' :

+                    return {

+                        shape : 'sector',

+                        zlevel : _zlevelBase,

+                        style : {

+                            x : x + width / 2,

+                            y : y + height + 2,

+                            r : height + 2,

+                            r0 : 6,

+                            startAngle : 45,

+                            endAngle : 135,

+                            color : color

+                        },

+                        clickable : true

+                    };

+                default :

+                    return {

+                        shape : 'rectangle',

+                        zlevel : _zlevelBase,

+                        style : {

+                            x : x,

+                            y : y,

+                            width : width,

+                            height : height - 2,

+                            color : color

+                        },

+                        clickable : true

+                    };

+            }

+        }

+

+        function _legendSelected(param) {

+            var itemName = param.target._name;

+            _selectedMap[itemName] = !_selectedMap[itemName];

+            messageCenter.dispatch(

+                ecConfig.EVENT.LEGEND_SELECTED,

+                param.event,

+                {selected : _selectedMap}

+            );

+        }

+

+        /**

+         * 清除图形数据,实例仍可用,重载基类方法

+         */

+        function clear() {

+            //_colorIndex = 0;

+            //_colorMap = {};

+

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                zr.delShape(self.shapeList[i].id);

+            }

+            self.shapeList = [];

+        }

+

+        function init(newOption) {

+            if (!self.deepQuery([newOption], 'legend.data')) {

+                return;

+            }

+

+            option = newOption;

+

+            option.legend = self.reformOption(option.legend);

+            // 补全padding属性

+            option.legend.padding = self.reformCssArray(

+                option.legend.padding

+            );

+

+            legendOption = option.legend;

+

+            self.clear();

+

+            _selectedMap = {};

+

+            var data = legendOption.data || [];

+            var finalData = [];

+            var itemName;

+            var serie;

+            var color;

+            for (var i = 0, dataLength = data.length; i < dataLength; i++) {

+                itemName = data[i];

+                serie = _getSeriesByName(itemName);

+                if (!serie) {

+                    continue;

+                } else {

+                    finalData.push(data[i]);

+                    color = self.deepQuery(

+                        [serie], 'itemStyle.normal.color'

+                    );

+                    if (color) {

+                        setColor(itemName, color);

+                    }

+                    _selectedMap[itemName] = true;

+                }

+            }

+            if (finalData.length > 0) {

+                legendOption.data = finalData;

+                if (selected) {

+                    for (var k in selected) {

+                        _selectedMap[k] = selected[k];

+                    }

+                }

+                _buildShape();

+            }

+        }

+

+        /**

+         * 刷新

+         */

+        function refresh() {

+            legendOption = option.legend;

+            self.clear();

+            _buildShape();

+        }

+

+        function setColor(legendName, color) {

+            _colorMap[legendName] = color;

+        }

+

+        function getColor(legendName) {

+            if (!_colorMap[legendName]) {

+                _colorMap[legendName] = zr.getColor(_colorIndex++);

+            }

+            return _colorMap[legendName];

+        }

+

+        function add(name,color){

+            legendOption.data.push(name);

+            setColor(name,color);

+            _selectedMap[name] = true;

+        }

+

+        function del(name){

+            var data = legendOption.data;

+            var finalData = [];

+            var found = false;

+            for (var i = 0, dataLength = data.length; i < dataLength; i++) {

+                if (found || data[i] != name) {

+                    finalData.push(data[i]);

+                } else {

+                    found = true;

+                    continue;

+                }

+            }

+            legendOption.data = finalData;

+        }

+

+        function isSelected(itemName) {

+            if (typeof _selectedMap[itemName] != 'undefined') {

+                return _selectedMap[itemName];

+            }

+            else {

+                // 没在legend里定义的都为true啊~

+                return true;

+            }

+        }

+

+        // 重载基类方法

+        self.clear = clear;

+

+        self.init = init;

+        self.refresh = refresh;

+        self.setColor = setColor;

+        self.getColor = getColor;

+        self.add = add;

+        self.del = del;

+        self.isSelected = isSelected;

+

+        init(option);

+    }

+

+    return Legend;

+});

+

+

diff --git a/src/component/toolbox.js b/src/component/toolbox.js
new file mode 100644
index 0000000..dd87d1a
--- /dev/null
+++ b/src/component/toolbox.js
@@ -0,0 +1,623 @@
+/**

+ * echarts组件:工具箱

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function (require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {HtmlElement} dom 目标对象

+     */

+    function Toolbox(messageCenter, zr, dom) {

+        var Base = require('./base');

+        Base.call(this, zr);

+

+        var ecConfig = require('../config');

+        var zrConfig = require('zrender/config');

+        var zrEvent = require('zrender/tool/event');

+

+        var option;

+        var self = this;

+        self.type = ecConfig.COMPONENT_TYPE_TOOLBOX;

+

+        var _zlevelBase = self.getZlevelBase();

+        var _magicType;

+        var _magicMap;

+        var _iconList;

+        var _iconShapeMap = {};

+        var _itemGroupLocation;

+        var _enableColor = 'red';

+        var _disableColor = '#ccc';

+        var _markColor;

+        var _markStart;

+        var _marking;

+        var _markShape;

+

+        var _markPencil;

+        var _dataView;

+

+        function _buildShape() {

+            _iconList = [];

+            var feature = option.toolbox.feature;

+            for (var key in feature){

+                if (feature[key]) {

+                    if (key == 'mark') {

+                        _iconList.push('mark');

+                        _iconList.push('markUndo');

+                        _iconList.push('markClear');

+                    }

+                    else if (key == 'magicType') {

+                        for (var i = 0, l = feature[key].length; i < l; i++) {

+                            _iconList.push(feature[key][i] + 'Chart');

+                        }

+                    }

+                    else {

+                        _iconList.push(key);

+                    }

+                }

+            }

+            if (_iconList.length > 0) {

+                _itemGroupLocation = _getItemGroupLocation();

+

+                _buildBackground();

+                _buildItem();

+

+                for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                    self.shapeList[i].id = zr.newShapeId(self.type);

+                    zr.addShape(self.shapeList[i]);

+                }

+                _iconDisable(_iconShapeMap['markUndo']);

+                _iconDisable(_iconShapeMap['markClear']);

+            }

+        }

+

+        /**

+         * 构建所有图例元素

+         */

+        function _buildItem() {

+            var toolboxOption = option.toolbox;

+            var iconLength = _iconList.length;

+            var lastX = _itemGroupLocation.x;

+            var lastY = _itemGroupLocation.y;

+            var itemSize = toolboxOption.itemSize;

+            var itemGap = toolboxOption.itemGap;

+            var itemShape;

+

+            var color = toolboxOption.color instanceof Array

+                        ? toolboxOption.color : [toolboxOption.color];

+            /*

+            var textPosition;

+            if (toolboxOption.orient == 'horizontal') {

+                textPosition = toolboxOption.y != 'bottom'

+                               ? 'bottom' : 'top';

+            }

+            else {

+                textPosition = toolboxOption.x != 'left'

+                               ? 'left' : 'right';

+            }

+            */

+           _iconShapeMap = {};

+

+            for (var i = 0; i < iconLength; i++) {

+                // 图形

+                itemShape = {

+                    shape : 'icon',

+                    zlevel : _zlevelBase,

+                    style : {

+                        x : lastX,

+                        y : lastY,

+                        width : itemSize,

+                        height : itemSize,

+                        iconType : _iconList[i],

+                        strokeColor : color[i % color.length],

+                        shadowColor: '#ccc',

+                        shadowBlur : 2,

+                        shadowOffsetX : 2,

+                        shadowOffsetY : 2

+                    },

+                    highlightStyle : {

+                        lineWidth : 2,

+                        shadowBlur: 5,

+                        strokeColor : color[i % color.length]

+                    },

+                    hoverable : true,

+                    clickable : true

+                };

+

+                switch(_iconList[i]) {

+                    case 'mark':

+                        itemShape.onclick = _onMark;

+                        _markPencil = itemShape;

+                        _markColor = itemShape.style.strokeColor;

+                        break;

+                    case 'markUndo':

+                        itemShape.onclick = _onMarkUndo;

+                        break;

+                    case 'markClear':

+                        itemShape.onclick = _onMarkClear;

+                        break;

+                    case 'dataView' :

+                        if (!_dataView) {

+                            var componentLibrary = require('../component');

+                            var DataView = componentLibrary.get('dataView');

+                            _dataView = new DataView(

+                                messageCenter, zr, option, dom

+                            );

+                        }

+                        itemShape.onclick = _onDataView;

+                        break;

+                    case 'refresh':

+                        itemShape.onclick = _onRefresh;

+                        break;

+                    default:

+                        if (_iconList[i].match('Chart')) {

+                            itemShape._name = _iconList[i].replace('Chart', '');

+                            if (itemShape._name == _magicType) {

+                                itemShape.style.strokeColor = _enableColor;

+                            }

+                            itemShape.onclick = _onMagicType;

+                        }

+                        break;

+                }

+

+                self.shapeList.push(itemShape);

+                _iconShapeMap[_iconList[i]] = itemShape;

+

+                if (toolboxOption.orient == 'horizontal') {

+                    lastX += itemSize + itemGap;

+                }

+                else {

+                    lastY += itemSize + itemGap;

+                }

+            }

+        }

+

+        function _buildBackground() {

+            var toolboxOption = option.toolbox;

+            var pTop = toolboxOption.padding[0];

+            var pRight = toolboxOption.padding[1];

+            var pBottom = toolboxOption.padding[2];

+            var pLeft = toolboxOption.padding[3];

+

+            self.shapeList.push({

+                shape : 'rectangle',

+                zlevel : _zlevelBase,

+                hoverable :false,

+                style : {

+                    x : _itemGroupLocation.x - pLeft,

+                    y : _itemGroupLocation.y - pTop,

+                    width : _itemGroupLocation.width + pLeft + pRight,

+                    height : _itemGroupLocation.height + pTop + pBottom,

+                    brushType : toolboxOption.borderWidth === 0

+                                ? 'fill' : 'both',

+                    color : toolboxOption.backgroundColor,

+                    strokeColor : toolboxOption.borderColor,

+                    lineWidth : toolboxOption.borderWidth

+                }

+            });

+        }

+

+        /**

+         * 根据选项计算图例实体的位置坐标

+         */

+        function _getItemGroupLocation() {

+            var toolboxOption = option.toolbox;

+            var iconLength = _iconList.length;

+            var itemGap = toolboxOption.itemGap;

+            var itemSize = toolboxOption.itemSize;

+            var totalWidth = 0;

+            var totalHeight = 0;

+

+            if (toolboxOption.orient == 'horizontal') {

+                // 水平布局,计算总宽度,别忘减去最后一个的itemGap

+                totalWidth = (itemSize + itemGap) * iconLength - itemGap;

+                totalHeight = itemSize;

+            }

+            else {

+                // 垂直布局,计算总高度

+                totalHeight = (itemSize + itemGap) * iconLength - itemGap;

+                totalWidth = itemSize;

+            }

+

+            var x;

+            var zrWidth = zr.getWidth();

+            switch (toolboxOption.x) {

+                case 'center' :

+                    x = Math.floor((zrWidth - totalWidth) / 2);

+                    break;

+                case 'left' :

+                    x = toolboxOption.padding[3] + toolboxOption.borderWidth;

+                    break;

+                case 'right' :

+                    x = zrWidth

+                        - totalWidth

+                        - toolboxOption.padding[1]

+                        - toolboxOption.borderWidth;

+                    break;

+                default :

+                    x = toolboxOption.x - 0;

+                    break;

+            }

+

+            var y;

+            var zrHeight = zr.getHeight();

+            switch (toolboxOption.y) {

+                case 'top' :

+                    y = toolboxOption.padding[0] + toolboxOption.borderWidth;

+                    break;

+                case 'bottom' :

+                    y = zrHeight

+                        - totalHeight

+                        - toolboxOption.padding[2]

+                        - toolboxOption.borderWidth;

+                    break;

+                case 'center' :

+                    y = Math.floor((zrHeight - totalHeight) / 2);

+                    break;

+                default :

+                    y = toolboxOption.y - 0;

+                    break;

+            }

+

+            return {

+                x : x,

+                y : y,

+                width : totalWidth,

+                height : totalHeight

+            };

+        }

+

+        function _onMark(param) {

+            var target = param.target;

+            if (_marking || _markStart) {

+                // 取消

+                _resetMark();

+                zr.modShape(

+                    target.id,

+                    {style: {strokeColor: target.highlightStyle.strokeColor}}

+                );

+                zr.refresh();

+                return true; // 阻塞全局事件

+            }

+            else {

+                // 启用

+                zr.modShape(target.id, {style: {strokeColor: _enableColor}});

+                zr.refresh();

+                _markStart = true;

+                setTimeout(function(){

+                    zr

+                    && zr.on(zrConfig.EVENT.CLICK, _onclick)

+                    && zr.on(zrConfig.EVENT.MOUSEMOVE, _onmousemove);

+                }, 10);

+            }

+        }

+

+        function _onmousemove(param) {

+            if (_marking) {

+               _markShape.style.xEnd = zrEvent.getX(param.event);

+               _markShape.style.yEnd = zrEvent.getY(param.event);

+               zr.addHoverShape(_markShape);

+            }

+        }

+

+        function _onclick(param) {

+            if (_marking) {

+                _marking = false;

+                self.shapeList.push(_markShape);

+                _iconEnable(_iconShapeMap['markUndo']);

+                _iconEnable(_iconShapeMap['markClear']);

+                zr.addShape(_markShape);

+                zr.refresh();

+            } else if (_markStart) {

+                _marking = true;

+                var x = zrEvent.getX(param.event);

+                var y = zrEvent.getY(param.event);

+                _markShape = {

+                    shape : 'line',

+                    id : zr.newShapeId('mark'),

+                    zlevel : _zlevelBase,

+                    style : {

+                        xStart : x,

+                        yStart : y,

+                        xEnd : x,

+                        yEnd : y,

+                        lineWidth : self.deepQuery(

+                                        [option],

+                                        'toolbox.feature.mark.lineStyle.width'

+                                    ) || 2,

+                        strokeColor : self.deepQuery(

+                                          [option],

+                                          'toolbox.feature.mark.lineStyle.color'

+                                      ) || _markColor,

+                        lineType : self.deepQuery(

+                                       [option],

+                                       'toolbox.feature.mark.lineStyle.type'

+                                   ) || 'dashed'

+                    }

+                };

+                zr.addHoverShape(_markShape);

+            }

+        }

+

+        function _onMarkUndo() {

+            if (_marking) {

+                _marking = false;

+            } else {

+                var len = self.shapeList.length - 1;    // 有一个是背景shape

+                if (_iconList.length == len - 1) {

+                    _iconDisable(_iconShapeMap['markUndo']);

+                    _iconDisable(_iconShapeMap['markClear']);

+                }

+                if (_iconList.length < len) {

+                    var target = self.shapeList[self.shapeList.length - 1];

+                    zr.delShape(target.id);

+                    zr.refresh();

+                    self.shapeList.pop();

+                }

+            }

+            return true;

+        }

+

+        function _onMarkClear() {

+            if (_marking) {

+                _marking = false;

+            }

+            // 有一个是背景shape

+            var len = self.shapeList.length - _iconList.length - 1;

+            var hasClear = false;

+            while(len--) {

+                zr.delShape(self.shapeList.pop().id);

+                hasClear = true;

+            }

+            if (hasClear) {

+                _iconDisable(_iconShapeMap['markUndo']);

+                _iconDisable(_iconShapeMap['markClear']);

+                zr.refresh();

+            }

+            return true;

+        }

+

+        function _resetMark() {

+            _marking = false;

+            if (_markStart) {

+                _markStart = false;

+                zr.un(zrConfig.EVENT.CLICK, _onclick);

+                zr.un(zrConfig.EVENT.MOUSEMOVE, _onmousemove);

+            }

+        }

+

+        function _iconDisable(target) {

+            zr.modShape(target.id, {

+                hoverable : false,

+                clickable : false,

+                style : {

+                    strokeColor : _disableColor

+                }

+            });

+        }

+

+        function _iconEnable(target) {

+            zr.modShape(target.id, {

+                hoverable : true,

+                clickable : true,

+                style : {

+                    strokeColor : target.highlightStyle.strokeColor

+                }

+            });

+        }

+

+        function _onDataView() {

+            _dataView.show(option);

+            return true;

+        }

+

+        function _onRefresh(){

+            _resetMark();

+            messageCenter.dispatch(ecConfig.EVENT.REFRESH);

+            return true;

+        }

+

+        function _onMagicType(param) {

+            _resetMark();

+            var itemName = param.target._name;

+            if (itemName == _magicType) {

+                // 取消

+                _magicType = false;

+            }

+            else {

+                // 启用

+                _magicType = itemName;

+            }

+            messageCenter.dispatch(

+                ecConfig.EVENT.MAGIC_TYPE_CHANGED,

+                param.event,

+                {magicType : _magicType}

+            );

+            return true;

+        }

+

+        function resetMagicType(newOption) {

+            if (newOption.toolbox

+                && newOption.toolbox.show

+                && newOption.toolbox.feature.magicType

+                && newOption.toolbox.feature.magicType.length > 0

+            ) {

+                var magicType = newOption.toolbox.feature.magicType;

+                var len = magicType.length;

+                _magicMap = {};     // 标识可控类型

+                while (len--) {

+                    _magicMap[magicType[len]] = true;

+                }

+

+                len = newOption.series.length;

+                var oriType;        // 备份还原可控类型

+                var axis;

+                while (len--) {

+                    oriType = newOption.series[len].type;

+                    if (_magicMap[oriType]) {

+                        axis = newOption.xAxis instanceof Array

+                               ? newOption.xAxis[

+                                     newOption.series[len].xAxisIndex || 0

+                                 ]

+                               : newOption.xAxis;

+                        if (axis && axis.type == 'category') {

+                            axis.__boundaryGap =

+                                typeof axis.boundaryGap != 'undefined'

+                                ? axis.boundaryGap : true;

+                        }

+                        axis = newOption.yAxis instanceof Array

+                               ? newOption.yAxis[

+                                     newOption.series[len].yAxisIndex || 0

+                                 ]

+                               : newOption.yAxis;

+                        if (axis && axis.type == 'category') {

+                            axis.__boundaryGap =

+                                typeof axis.boundaryGap != 'undefined'

+                                ? axis.boundaryGap : true;

+                        }

+                        newOption.series[len].__type = oriType;

+                    }

+                }

+            }

+            _magicType = false;

+        }

+

+        function getMagicOption(){

+            if (_magicType) {

+                // 启动

+                for (var i = 0, l = option.series.length; i < l; i++) {

+                    if (_magicMap[option.series[i].type]) {

+                        option.series[i].type = _magicType;

+                    }

+                }

+                var boundaryGap = _magicType == ecConfig.CHART_TYPE_LINE

+                                  ? false : true;

+                var len;

+                if (option.xAxis instanceof Array) {

+                    len = option.xAxis.length;

+                    while (len--) {

+                        // 横纵默认为类目

+                        if ((option.xAxis[len].type || 'category')

+                             == 'category'

+                         ) {

+                            option.xAxis[len].boundaryGap = boundaryGap;

+                        }

+                    }

+                }

+                else {

+                    if (option.xAxis

+                        && (option.xAxis.type || 'category') == 'category'

+                    ) {

+                        option.xAxis.boundaryGap = boundaryGap;

+                    }

+                }

+

+                if (option.yAxis instanceof Array) {

+                    len = option.yAxis.length;

+                    while (len--) {

+                        if ((option.yAxis[len].type) == 'category') {

+                            option.yAxis[len].boundaryGap = boundaryGap;

+                        }

+                    }

+                }

+                else {

+                    if (option.yAxis && option.yAxis.type == 'category') {

+                        option.yAxis.boundaryGap = boundaryGap;

+                    }

+                }

+            }

+            else {

+                // 还原

+                var axis;

+                for (var i = 0, l = option.series.length; i < l; i++) {

+                    if (_magicMap[option.series[i].type]) {

+                        option.series[i].type = option.series[i].__type;

+                        if (option.xAxis instanceof Array) {

+                            axis = option.xAxis[

+                                       option.series[i].xAxisIndex || 0

+                                   ];

+                            if (axis.type == 'category') {

+                                axis.boundaryGap = axis.__boundaryGap;

+                            }

+                        }

+                        else {

+                            axis = option.xAxis;

+                            if (axis && axis.type == 'category') {

+                                axis.boundaryGap = axis.__boundaryGap;

+                            }

+                        }

+

+                        if (option.yAxis instanceof Array) {

+                            axis = option.yAxis[

+                                       option.series[i].yAxisIndex || 0

+                                   ];

+                            if (axis.type == 'category') {

+                                axis.boundaryGap = axis.__boundaryGap;

+                            }

+                        }

+                        else {

+                            axis = option.yAxis;

+                            if (axis && axis.type == 'category') {

+                                axis.boundaryGap = axis.__boundaryGap;

+                            }

+                        }

+                    }

+                }

+            }

+

+            return option;

+        }

+

+        function render(newOption){

+            _resetMark();

+            newOption.toolbox = self.reformOption(newOption.toolbox);

+            // 补全padding属性

+            newOption.toolbox.padding = self.reformCssArray(

+                newOption.toolbox.padding

+            );

+            option = newOption;

+

+            self.shapeList = [];

+

+            if (newOption.toolbox.show) {

+                _buildShape();

+            }

+

+            hideDataView();

+        }

+

+        function hideDataView() {

+            if (_dataView) {

+                _dataView.hide();

+            }

+        }

+

+        /**

+         * 释放后实例不可用

+         */

+        function dispose() {

+            if (_dataView) {

+                _dataView.dispose();

+            }

+

+            self.clear();

+            self.shapeList = null;

+            self = null;

+        }

+

+        // 重载基类方法

+        self.dispose = dispose;

+

+        self.render = render;

+        self.hideDataView = hideDataView;

+        self.getMagicOption = getMagicOption;

+        self.resetMagicType = resetMagicType;

+    }

+

+    return Toolbox;

+});
\ No newline at end of file
diff --git a/src/component/tooltip.js b/src/component/tooltip.js
new file mode 100644
index 0000000..98542b1
--- /dev/null
+++ b/src/component/tooltip.js
@@ -0,0 +1,741 @@
+/**

+ * echarts组件:提示框

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function (require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} option 提示框参数

+     * @param {HtmlElement} dom 目标对象

+     */

+    function Tooltip(messageCenter, zr, option, dom) {

+        var Base = require('./base');

+        Base.call(this, zr);

+

+        var ecConfig = require('../config');

+        var ecData = require('../util/ecData');

+

+        var zrConfig = require('zrender/config');

+        var zrShape = require('zrender/shape');

+        var zrEvent = require('zrender/tool/event');

+        var zrArea = require('zrender/tool/area');

+        var zrColor = require('zrender/tool/color');

+        var zrUtil = require('zrender/tool/util');

+

+        var rectangle = zrShape.get('rectangle');

+        var self = this;

+        self.type = ecConfig.COMPONENT_TYPE_TOOLTIP;

+

+        var _zlevelBase = self.getZlevelBase();

+

+        var component = {};                     // 组件索引

+        var grid;

+        var xAxis;

+        var yAxis;

+

+        // tooltip dom & css

+        var _tDom = document.createElement('div');

+        // 通用样式

+        var _gCssText = 'position:absolute;'

+                        + 'display:block;'

+                        + 'transition:left 1s,top 1s;'

+                        + '-moz-transition:left 1s,top 1s;'

+                        + '-webkit-transition:left 1s,top 1s;'

+                        + '-o-transition:left 1s,top 1s;'

+                        + 'border-style:solid;';

+        // 默认样式

+        var _defaultCssText;                    // css样式缓存

+

+        var _needAxisTrigger;                   // 坐标轴触发

+        var _hidingTicket;

+        var _hideDelay = 100;                   // 隐藏延迟

+        var _showingTicket;

+        var _showDelay = 30;                    // 显示延迟

+        var _curTarget;

+        var _event;

+

+        var _curTicket;                         // 异步回调标识,用来区分多个请求

+

+        // 缓存一些高宽数据

+        var _zrHeight = zr.getHeight();

+        var _zrWidth = zr.getWidth();

+

+        var _axisLineShape = {

+            shape : 'line',

+            id : zr.newShapeId('tooltip'),

+            zlevel: _zlevelBase,

+            invisible : true,

+            hoverable: false,

+            style : {

+                lineWidth : 2,

+                strokeColor : ecConfig.categoryAxis.axisLine.lineStyle.color

+            }

+        };

+        zr.addShape(_axisLineShape);

+

+        /**

+         * 根据配置设置dom样式

+         */

+        function _style(opt) {

+            if (!opt) {

+                return '';

+            }

+            cssText = [];

+

+            if (opt.backgroundColor) {

+                // for sb ie~

+                cssText.push(

+                    'background-Color:' + zrColor.toHex(

+                        opt.backgroundColor

+                    )

+                );

+                cssText.push('filter:alpha(opacity=70)');

+                cssText.push('background-Color:' + opt.backgroundColor);

+            }

+

+            if (typeof opt.borderWidth != 'undefined') {

+                cssText.push('border-width:' + opt.borderWidth + 'px');

+            }

+

+            if (typeof opt.borderColor != 'undefined') {

+                cssText.push('border-color:' + opt.borderColor + 'px');

+            }

+

+            if (typeof opt.borderRadius != 'undefined') {

+                cssText.push(

+                    'border-radius:' + opt.borderRadius + 'px'

+                );

+                cssText.push(

+                    '-moz-border-radius:' + opt.borderRadius + 'px'

+                );

+                cssText.push(

+                    '-webkit-border-radius:' + opt.borderRadius + 'px'

+                );

+                cssText.push(

+                    '-o-border-radius:' + opt.borderRadius + 'px'

+                );

+            }

+

+            var textStyle = opt.textStyle;

+            if (textStyle) {

+                textStyle.color && cssText.push('color:' + textStyle.color);

+                textStyle.decoration && cssText.push(

+                    'text-decoration:' + textStyle.decoration

+                );

+                textStyle.align && cssText.push(

+                    'text-align:' + textStyle.align

+                );

+                textStyle.fontFamily && cssText.push(

+                    'font-family:' + textStyle.fontFamily

+                );

+                textStyle.fontSize && cssText.push(

+                    'font-size:' + textStyle.fontSize + 'px'

+                );

+                textStyle.fontSize && cssText.push(

+                    'line-height:' + Math.round(textStyle.fontSize*3/2) + 'px'

+                );

+                textStyle.fontStyle && cssText.push(

+                    'font-style:' + textStyle.fontStyle

+                );

+                textStyle.fontWeight && cssText.push(

+                    'font-weight:' + textStyle.fontWeight

+                );

+            }

+

+

+            var padding = opt.padding;

+            if (typeof padding != 'undefined') {

+                padding = self.reformCssArray(padding);

+                cssText.push(

+                    'padding:' + padding[0] + 'px '

+                               + padding[1] + 'px '

+                               + padding[2] + 'px '

+                               + padding[3] + 'px'

+                );

+            }

+

+            cssText = cssText.join(';') + ';';

+

+            return cssText;

+        }

+

+        function _hide() {

+            if (_tDom) {

+                _tDom.style.display = 'none';

+            }

+            if (!_axisLineShape.invisible) {

+                _axisLineShape.invisible = true;

+                zr.modShape(_axisLineShape.id, _axisLineShape);

+                zr.refresh();

+            }

+        }

+

+        function _show(x, y, specialCssText) {

+            var domHeight = _tDom.offsetHeight;

+            var domWidth = _tDom.offsetWidth;

+            if (x + domWidth > _zrWidth) {

+                x = _zrWidth - domWidth;

+            }

+            if (y + domHeight > _zrHeight) {

+                y = _zrHeight - domHeight;

+            }

+            _tDom.style.cssText = _gCssText

+                                  + _defaultCssText

+                                  + (specialCssText ? specialCssText : '')

+                                  + 'left:' + x + 'px;top:' + y + 'px;';

+        }

+

+        function _tryShow() {

+            var needShow;

+            var trigger;

+            if (!_curTarget) {

+                // 坐标轴事件

+                _findAxisTrigger();

+            }

+            else {

+                // 数据项事件

+                if (_curTarget._type == 'island'

+                    && self.deepQuery([option], 'tooltip.show')

+                ) {

+                    _showItemTrigger();

+                    return;

+                }

+                var serie = ecData.get(_curTarget, 'series');

+                var data = ecData.get(_curTarget, 'data');

+                needShow = self.deepQuery(

+                    [data, serie, option],

+                    'tooltip.show'

+                );

+                if (typeof serie == 'undefined'

+                    || typeof data == 'undefined'

+                    || needShow === false

+                ) {

+                    // 不响应tooltip的数据对象延时隐藏

+                    clearTimeout(_hidingTicket);

+                    clearTimeout(_showingTicket);

+                    _hidingTicket = setTimeout(_hide, _hideDelay);

+                }

+                else {

+                    trigger = self.deepQuery(

+                        [data, serie, option],

+                        'tooltip.trigger'

+                    );

+                    trigger == 'axis'

+                               ? _showAxisTrigger(

+                                     serie.xAxisIndex, serie.yAxisIndex,

+                                     ecData.get(_curTarget, 'dataIndex')

+                                 )

+                               : _showItemTrigger();

+                }

+            }

+        }

+

+        function _findAxisTrigger() {

+            var series = option.series;

+            var xAxisIndex;

+            var yAxisIndex;

+            for (var i = 0, l = series.length; i < l; i++) {

+                // 找到第一个axis触发tooltip的系列

+                if (self.deepQuery(

+                        [series[i], option], 'tooltip.trigger'

+                    ) == 'axis'

+                ) {

+                    xAxisIndex = series[i].xAxisIndex || 0;

+                    yAxisIndex = series[i].yAxisIndex || 0;

+                    if (xAxis.getAxis(xAxisIndex)

+                        && xAxis.getAxis(xAxisIndex).type

+                           == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY

+                    ) {

+                        // 横轴为类目轴

+                        _showAxisTrigger(xAxisIndex, yAxisIndex,

+                            _getNearestDataIndex('x', xAxis.getAxis(xAxisIndex))

+                        );

+                        return;

+                    } else if (yAxis.getAxis(yAxisIndex)

+                               && yAxis.getAxis(yAxisIndex).type

+                                  == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY

+                    ) {

+                        // 纵轴为类目轴

+                        _showAxisTrigger(xAxisIndex, yAxisIndex,

+                            _getNearestDataIndex('y', yAxis.getAxis(yAxisIndex))

+                        );

+                        return;

+                    }

+                }

+            }

+        }

+        /**

+         * 根据坐标轴事件带的属性获取最近的axisDataIndex

+         */

+        function _getNearestDataIndex(direction, categoryAxis) {

+            var dataIndex = -1;

+            var x = zrEvent.getX(_event);

+            var y = zrEvent.getY(_event);

+            if (direction == 'x') {

+                // 横轴为类目轴

+                var left;

+                var right;

+                var xEnd = grid.getXend();

+                var curCoord = categoryAxis.getCoordByIndex(dataIndex);

+                while (curCoord < xEnd) {

+                    if (curCoord <= x) {

+                        left = curCoord;

+                    }

+                    if (curCoord >= x) {

+                        break;

+                    }

+                    curCoord = categoryAxis.getCoordByIndex(++dataIndex);

+                    right = curCoord;

+                }

+                if (x - left < right - x) {

+                    dataIndex -= 1;

+                }

+                else {

+                    // 离右边近,看是否为最后一个

+                    if (typeof categoryAxis.getNameByIndex(dataIndex)

+                        == 'undefined'

+                    ) {

+                        dataIndex = -1;

+                    }

+                }

+                return dataIndex;

+            }

+            else {

+                // 纵轴为类目轴

+                var top;

+                var bottom;

+                var yStart = grid.getY();

+                var curCoord = categoryAxis.getCoordByIndex(dataIndex);

+                while (curCoord > yStart) {

+                    if (curCoord >= y) {

+                        bottom = curCoord;

+                    }

+                    if (curCoord <= y) {

+                        break;

+                    }

+                    curCoord = categoryAxis.getCoordByIndex(++dataIndex);

+                    top = curCoord;

+                }

+

+                if (y - top > bottom - y) {

+                    dataIndex -= 1;

+                }

+                else {

+                    // 离上方边近,看是否为最后一个

+                    if (typeof categoryAxis.getNameByIndex(dataIndex)

+                        == 'undefined'

+                    ) {

+                        dataIndex = -1;

+                    }

+                }

+                return dataIndex;

+            }

+            return -1;

+        }

+

+        function _showAxisTrigger(xAxisIndex, yAxisIndex, dataIndex) {

+            if (typeof xAxis == 'undefined'

+                || typeof yAxis == 'undefined'

+                || typeof xAxisIndex == 'undefined'

+                || typeof yAxisIndex == 'undefined'

+                || dataIndex < 0

+            ) {

+                // 不响应tooltip的数据对象延时隐藏

+                clearTimeout(_hidingTicket);

+                clearTimeout(_showingTicket);

+                _hidingTicket = setTimeout(_hide, _hideDelay);

+                return;

+            }

+            var series = option.series;

+            var seriesArray = [];

+            var categoryAxis;

+            var x;

+            var y;

+

+            var formatter;

+            var specialCssText = '';

+            if (self.deepQuery([option], 'tooltip.trigger') == 'axis') {

+                if (self.deepQuery([option], 'tooltip.show') === false) {

+                    return;

+                }

+                formatter = self.deepQuery([option],'tooltip.formatter');

+            }

+

+            if (xAxisIndex != -1

+                && xAxis.getAxis(xAxisIndex).type

+                   == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY

+            ) {

+                // 横轴为类目轴,找到所有用这条横轴并且axis触发的系列数据

+                categoryAxis = xAxis.getAxis(xAxisIndex);

+                for (var i = 0, l = series.length; i < l; i++) {

+                    if (series[i].xAxisIndex == xAxisIndex

+                        && self.deepQuery(

+                               [series[i], option], 'tooltip.trigger'

+                           ) == 'axis'

+                    ) {

+                        formatter = self.deepQuery(

+                            [series[i]],

+                            'tooltip.formatter'

+                        ) || formatter;

+                        specialCssText += _style(self.deepQuery(

+                                              [series[i]], 'tooltip'

+                                          ));

+                        seriesArray.push(series[i]);

+                    }

+                }

+                y = zrEvent.getY(_event) + 10;

+                x = categoryAxis.getCoordByIndex(dataIndex);

+                _axisLineShape.style.xStart = x;

+                _axisLineShape.style.yStart = component.grid.getY();

+                _axisLineShape.style.xEnd = x;

+                _axisLineShape.style.yEnd = component.grid.getYend();

+                x += 10;

+            }

+            else if (yAxisIndex != -1

+                       && yAxis.getAxis(yAxisIndex).type

+                          == ecConfig.COMPONENT_TYPE_AXIS_CATEGORY

+            ) {

+                // 纵轴为类目轴,找到所有用这条纵轴并且axis触发的系列数据

+                categoryAxis = yAxis.getAxis(yAxisIndex);

+                for (var i = 0, l = series.length; i < l; i++) {

+                    if (series[i].yAxisIndex == yAxisIndex

+                        && self.deepQuery(

+                               [series[i], option], 'tooltip.trigger'

+                           ) == 'axis'

+                    ) {

+                        formatter = self.deepQuery(

+                            [series[i]],

+                            'tooltip.formatter'

+                        ) || formatter;

+                        specialCssText += _style(self.deepQuery(

+                                              [series[i]], 'tooltip'

+                                          ));

+                        seriesArray.push(series[i]);

+                    }

+                }

+                x = zrEvent.getX(_event) + 10;

+                y = categoryAxis.getCoordByIndex(dataIndex);

+                _axisLineShape.style.xStart = component.grid.getX();

+                _axisLineShape.style.yStart = y;

+                _axisLineShape.style.xEnd = component.grid.getXend();

+                _axisLineShape.style.yEnd = y;

+                y += 10;

+            }

+

+            if (seriesArray.length > 0) {

+                var data;

+                if (typeof formatter == 'function') {

+                    var params = [];

+                    for (var i = 0, l = seriesArray.length; i < l; i++) {

+                        data = seriesArray[i].data[dataIndex] || '-';

+                        data = typeof data.value != 'undefined'

+                               ? data.value : data;

+                        params.push([

+                            seriesArray[i].name,

+                            categoryAxis.getNameByIndex(dataIndex),

+                            data

+                        ]);

+                    }

+                    _curTicket = 'axis:' + dataIndex;

+                    _tDom.innerHTML = formatter(

+                        params, _curTicket, _setContent

+                    );

+                }

+                else if (typeof formatter == 'string') {

+                    formatter = formatter.replace('{a}','{a0}')

+                                         .replace('{b}','{b0}')

+                                         .replace('{c}','{c0}');

+                    for (var i = 0, l = seriesArray.length; i < l; i++) {

+                        formatter = formatter.replace(

+                            '{a' + i + '}',

+                            seriesArray[i].name

+                        );

+                        formatter = formatter.replace(

+                            '{b' + i + '}',

+                            categoryAxis.getNameByIndex(dataIndex)

+                        );

+                        data = seriesArray[i].data[dataIndex] || '-';

+                        data = typeof data.value != 'undefined'

+                               ? data.value : data;

+                        formatter = formatter.replace(

+                            '{c' + i + '}',

+                            data

+                        );

+                    }

+                    _tDom.innerHTML = formatter;

+                }

+                else {

+                    formatter = categoryAxis.getNameByIndex(dataIndex);

+                    for (var i = 0, l = seriesArray.length; i < l; i++) {

+                        formatter += '<br/>' + seriesArray[i].name + ' : ';

+                        data = seriesArray[i].data[dataIndex] || '-';

+                        data = typeof data.value != 'undefined'

+                               ? data.value : data;

+                        formatter += data;

+                    }

+                    _tDom.innerHTML = formatter;

+                }

+

+                if (!self.hasAppend) {

+                    _tDom.style.left = _zrWidth / 2 + 'px';

+                    _tDom.style.top = _zrHeight / 2 + 'px';

+                    dom.firstChild.appendChild(_tDom);

+                    self.hasAppend = true;

+                }

+                _show(x, y, specialCssText);

+

+                _axisLineShape.invisible = false;

+                zr.modShape(_axisLineShape.id, _axisLineShape);

+                zr.refresh();

+            }

+        }

+

+        function _showItemTrigger() {

+            var serie = ecData.get(_curTarget, 'series');

+            var data = ecData.get(_curTarget, 'data');

+            var name = ecData.get(_curTarget, 'name');

+            var value = ecData.get(_curTarget, 'value');

+            var speical = ecData.get(_curTarget, 'special');

+

+            // 从低优先级往上找到trigger为item的formatter和样式

+            var formatter;

+            var specialCssText = '';

+            if (_curTarget._type != 'island') {

+                // 全局

+                if (self.deepQuery([option], 'tooltip.trigger') == 'item'

+                ) {

+                    formatter = self.deepQuery(

+                                    [option], 'tooltip.formatter'

+                                ) || formatter;

+                }

+                // 系列

+                if (self.deepQuery([serie],  'tooltip.trigger') == 'item'

+                ) {

+                    formatter = self.deepQuery(

+                                    [serie], 'tooltip.formatter'

+                                ) || formatter;

+                    specialCssText += _style(self.deepQuery(

+                                          [serie], 'tooltip'

+                                      ));

+                }

+                // 数据项

+                formatter = self.deepQuery(

+                                [data], 'tooltip.formatter'

+                            ) || formatter;

+                specialCssText += _style(self.deepQuery([data], 'tooltip'));

+            } else {

+                formatter = self.deepQuery(

+                    [data, serie, option],

+                    'tooltip.islandFormatter'

+                );

+            }

+

+            if (typeof formatter == 'function') {

+                _curTicket = serie.name

+                             + ':'

+                             + ecData.get(_curTarget, 'dataIndex');

+                _tDom.innerHTML = formatter(

+                    [

+                        serie.name,

+                        name,

+                        value,

+                        speical

+                    ],

+                    _curTicket,

+                    _setContent

+                );

+            }

+            else if (typeof formatter == 'string') {

+                formatter = formatter.replace('{a}','{a0}')

+                                     .replace('{b}','{b0}')

+                                     .replace('{c}','{c0}')

+                                     .replace('{d}','{d0}');

+                formatter = formatter.replace('{a0}', serie.name)

+                                     .replace('{b0}', name)

+                                     .replace('{c0}', value);

+

+                if (typeof speical != 'undefined') {

+                    formatter = formatter.replace('{d0}', speical);

+                }

+

+                _tDom.innerHTML = formatter;

+            }

+            else {

+                _tDom.innerHTML = serie.name + '<br/>' +

+                                  name + ' : ' + value +

+                                  (typeof speical == 'undefined'

+                                  ? ''

+                                  : (' (' + speical + ')'));

+            }

+

+            if (!self.hasAppend) {

+                _tDom.style.left = _zrWidth / 2 + 'px';

+                _tDom.style.top = _zrHeight / 2 + 'px';

+                dom.firstChild.appendChild(_tDom);

+                self.hasAppend = true;

+            }

+

+            _show(

+                zrEvent.getX(_event) + 20,

+                zrEvent.getY(_event) - 20,

+                specialCssText

+            );

+

+            if (!_axisLineShape.invisible) {

+                _axisLineShape.invisible = true;

+                zr.modShape(_axisLineShape.id, _axisLineShape);

+                zr.refresh();

+            }

+        }

+

+        /**

+         * zrender事件响应:窗口大小改变

+         */

+        function _onresize() {

+            _zrHeight = zr.getHeight();

+            _zrWidth = zr.getWidth();

+        }

+

+        /**

+         * zrender事件响应:鼠标移动

+         */

+        function _onmousemove(param) {

+            clearTimeout(_hidingTicket);

+            clearTimeout(_showingTicket);

+            var target = param.target;

+            if (!target) {

+                // 判断是否落到直角系里,axis触发的tooltip

+                if (_needAxisTrigger

+                    && zrArea.isInside(

+                           rectangle,

+                           grid.getArea(),

+                           zrEvent.getX(param.event),

+                           zrEvent.getY(param.event)

+                       )

+                ) {

+                    _curTarget = false;

+                    _event = param.event;

+                    _event._target = _event.target || _event.toElement;

+                    _event.zrenderX = zrEvent.getX(_event);

+                    _event.zrenderY = zrEvent.getY(_event);

+                    _showingTicket = setTimeout(_tryShow, _showDelay);

+                }

+                else {

+                    _hidingTicket = setTimeout(_hide, _hideDelay);

+                }

+            }

+            else {

+                _curTarget = target;

+                _event = param.event;

+                _event._target = _event.target || _event.toElement;

+                _event.zrenderX = zrEvent.getX(_event);

+                _event.zrenderY = zrEvent.getY(_event);

+                _showingTicket = setTimeout(_tryShow, _showDelay);

+            }

+        }

+

+        /**

+         * 异步回调填充内容

+         */

+        function _setContent(ticket, content) {

+            if (ticket == _curTicket) {

+                _tDom.innerHTML = content;

+            }

+            var cssText = '';

+            var domHeight = _tDom.offsetHeight;

+            var domWidth = _tDom.offsetWidth;

+

+            if (_tDom.offsetLeft + domWidth > _zrWidth) {

+                cssText += 'left:' + (_zrWidth - domWidth) + 'px;';

+            }

+            if (_tDom.offsetTop + domHeight > _zrHeight) {

+                cssText += 'top:' + (_zrHeight - domHeight) + 'px;';

+            }

+            if (cssText !== '') {

+                _tDom.style.cssText += cssText;

+            }

+        }

+

+        function setComponent(newComponent) {

+            component = newComponent;

+            grid = component.grid;

+            xAxis = component.xAxis;

+            yAxis = component.yAxis;

+        }

+

+        function init(newOption, newDom) {

+            option = newOption;

+            dom = newDom;

+

+            option.tooltip = self.reformOption(option.tooltip);

+            option.tooltip.textStyle = zrUtil.merge(

+                option.tooltip.textStyle,

+                ecConfig.textStyle,

+                {

+                    'overwrite': false,

+                    'recursive': true

+                }

+            );

+            // 补全padding属性

+            option.tooltip.padding = self.reformCssArray(

+                option.tooltip.padding

+            );

+

+            _needAxisTrigger = false;

+            if (option.tooltip.trigger == 'axis') {

+                _needAxisTrigger = true;

+            }

+

+            var series = option.series;

+            for (var i = 0, l = series.length; i < l; i++) {

+                if (self.deepQuery([series[i]], 'tooltip.trigger')

+                    == 'axis'

+                ) {

+                    _needAxisTrigger = true;

+                    break;

+                }

+            }

+

+            _defaultCssText = _style(option.tooltip);

+            _tDom.style.position = 'absolute';  // 不是多余的,别删!

+            self.hasAppend = false;

+        }

+

+        /**

+         * 释放后实例不可用,重载基类方法

+         */

+        function dispose() {

+            clearTimeout(_hidingTicket);

+            clearTimeout(_showingTicket);

+            zr.un(zrConfig.EVENT.RESIZE, _onresize);

+            zr.un(zrConfig.EVENT.MOUSEMOVE, _onmousemove);

+

+            if (self.hasAppend) {

+                dom.firstChild.removeChild(_tDom);

+            }

+            _tDom = null;

+

+            // self.clear();

+            self.shapeList = null;

+            self = null;

+        }

+

+        zr.on(zrConfig.EVENT.RESIZE, _onresize);

+        zr.on(zrConfig.EVENT.MOUSEMOVE, _onmousemove);

+

+        // 重载基类方法

+        self.dispose = dispose;

+

+        self.init = init;

+        self.setComponent = setComponent;

+        init(option, dom);

+    }

+

+    return Tooltip;

+});
\ No newline at end of file
diff --git a/src/component/valueAxis.js b/src/component/valueAxis.js
new file mode 100644
index 0000000..2f0c821
--- /dev/null
+++ b/src/component/valueAxis.js
@@ -0,0 +1,749 @@
+/**

+ * echarts组件: 数值轴

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function (require) {

+    /**

+     * 构造函数

+     * @param {Object} messageCenter echart消息中心

+     * @param {ZRender} zr zrender实例

+     * @param {Object} option 类目轴参数

+     * @param {Grid} grid 网格对象

+     * @param {Array} series 数据对象

+     */

+    function ValueAxis(messageCenter, zr, option, component, series) {

+        var Base = require('./base');

+        Base.call(this, zr);

+

+        var ecConfig = require('../config');

+

+        var zrUtil = require('zrender/tool/util');

+

+        var self = this;

+        self.type = ecConfig.COMPONENT_TYPE_AXIS_VALUE;

+

+        var grid = component.grid;

+

+        var _zlevelBase = self.getZlevelBase();

+        var _min;

+        var _max;

+        var _valueList;

+        var _valueLabel;

+

+        function _buildShape() {

+            _calculateValue();

+            option.splitArea.show && _buildSplitArea();

+            option.splitLine.show && _buildSplitLine();

+            option.axisLine.show && _buildAxisLine();

+            option.axisTick.show && _buildAxisTick();

+            option.axisLabel.show && _buildAxisLabel();

+

+            for (var i = 0, l = self.shapeList.length; i < l; i++) {

+                self.shapeList[i].id = zr.newShapeId(self.type);

+                zr.addShape(self.shapeList[i]);

+            }

+        }

+

+        // 轴线

+        function _buildAxisLine() {

+            var axShape = {

+                shape : 'line',

+                zlevel : _zlevelBase + 1,

+                hoverable : false

+            };

+            switch (option.position) {

+                case 'left' :

+                    axShape.style = {

+                        xStart : grid.getX(),

+                        yStart : grid.getY(),

+                        xEnd : grid.getX(),

+                        yEnd : grid.getYend()

+                    };

+                    break;

+                case 'right' :

+                    axShape.style = {

+                        xStart : grid.getXend(),

+                        yStart : grid.getY(),

+                        xEnd : grid.getXend(),

+                        yEnd : grid.getYend()

+                    };

+                    break;

+                case 'bottom' :

+                    axShape.style = {

+                        xStart : grid.getX(),

+                        yStart : grid.getYend(),

+                        xEnd : grid.getXend(),

+                        yEnd : grid.getYend()

+                    };

+                    break;

+                case 'top' :

+                    axShape.style = {

+                        xStart : grid.getX(),

+                        yStart : grid.getY(),

+                        xEnd : grid.getXend(),

+                        yEnd : grid.getY()

+                    };

+                    break;

+            }

+

+            axShape.style.strokeColor = option.axisLine.lineStyle.color;

+            axShape.style.lineWidth = option.axisLine.lineStyle.width;

+            axShape.style.lineType = option.axisLine.lineStyle.type;

+

+            self.shapeList.push(axShape);

+        }

+

+        // 小标记

+        function _buildAxisTick() {

+            var axShape;

+            var data       = _valueList;

+            var dataLength = _valueList.length;

+            var length     = option.axisTick.length;

+            var color      = option.axisTick.lineStyle.color;

+            var lineWidth  = option.axisTick.lineStyle.width;

+

+            if (option.position == 'bottom' || option.position == 'top') {

+                // 横向

+                var yPosition = option.position == 'bottom'

+                                ? grid.getYend()

+                                : (grid.getY() - length);

+                for (var i = 0; i < dataLength; i++) {

+                    axShape = {

+                        shape : 'line',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            xStart : getCoord(data[i]),

+                            yStart : yPosition,

+                            xEnd : getCoord(data[i]),

+                            yEnd : yPosition + length,

+                            strokeColor : color,

+                            lineWidth : lineWidth

+                        }

+                    };

+                    self.shapeList.push(axShape);

+                }

+            }

+            else {

+                // 纵向

+                var xPosition = option.position == 'left'

+                                ? (grid.getX() - length)

+                                : grid.getXend();

+                for (var i = 0; i < dataLength; i++) {

+                    axShape = {

+                        shape : 'line',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            xStart : xPosition,

+                            yStart : getCoord(data[i]),

+                            xEnd : xPosition + length,

+                            yEnd : getCoord(data[i]),

+                            strokeColor : color,

+                            lineWidth : lineWidth

+                        }

+                    };

+                    self.shapeList.push(axShape);

+                }

+            }

+        }

+

+        // 坐标轴文本

+        function _buildAxisLabel() {

+            var axShape;

+            var data       = _valueList;

+            var dataLength = _valueList.length;

+            var rotate     = option.axisLabel.rotate;

+            var margin     = option.axisLabel.margin;

+            var textStyle  = option.axisLabel.textStyle;

+

+            if (option.position == 'bottom' || option.position == 'top') {

+                // 横向

+                var yPosition;

+                var baseLine;

+                if (option.position == 'bottom') {

+                    yPosition = grid.getYend() + margin;

+                    baseLine = 'top';

+                }

+                else {

+                    yPosition = grid.getY() - margin;

+                    baseLine = 'bottom';

+                }

+

+                for (var i = 0; i < dataLength; i++) {

+                    axShape = {

+                        shape : 'text',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            x : getCoord(data[i]),

+                            y : yPosition,

+                            color : textStyle.color,

+                            text : _valueLabel[i],

+                            textFont : self.getFont(textStyle),

+                            textAlign : 'center',

+                            textBaseline : baseLine

+                        }

+                    };

+                    if (rotate) {

+                        axShape.style.textAlign = rotate > 0

+                                                  ? (option.position == 'bottom'

+                                                    ? 'right' : 'left')

+                                                  : (option.position == 'bottom'

+                                                    ? 'left' : 'right');

+                        axShape.rotation = [

+                            rotate * Math.PI / 180,

+                            axShape.style.x,

+                            axShape.style.y

+                        ];

+                    }

+                    self.shapeList.push(axShape);

+                }

+            }

+            else {

+                // 纵向

+                var xPosition;

+                var align;

+                if (option.position == 'left') {

+                    xPosition = grid.getX() - margin;

+                    align = 'right';

+                }

+                else {

+                    xPosition = grid.getXend() + margin;

+                    align = 'left';

+                }

+

+                for (var i = 0; i < dataLength; i++) {

+                    axShape = {

+                        shape : 'text',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            x : xPosition,

+                            y : getCoord(data[i]),

+                            color : textStyle.color,

+                            text : _valueLabel[i],

+                            textFont : self.getFont(textStyle),

+                            textAlign : align,

+                            textBaseline : 'middle'

+                        }

+                    };

+                    if (rotate) {

+                        axShape.rotation = [

+                            rotate * Math.PI / 180,

+                            axShape.style.x,

+                            axShape.style.y

+                        ];

+                    }

+                    self.shapeList.push(axShape);

+                }

+            }

+        }

+

+        function _buildSplitLine() {

+            var axShape;

+            var data       = _valueList;

+            var dataLength = _valueList.length;

+

+            if (option.position == 'bottom' || option.position == 'top') {

+                // 横向

+                var sy = grid.getY();

+                var ey = grid.getYend();

+                var x;

+

+                for (var i = 0; i < dataLength; i++) {

+                    x = getCoord(data[i]);

+                    axShape = {

+                        shape : 'line',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            xStart : x,

+                            yStart : sy,

+                            xEnd : x,

+                            yEnd : ey,

+                            strokeColor : option.splitLine.lineStyle.color,

+                            lineType : option.splitLine.lineStyle.type,

+                            lineWidth : option.splitLine.lineStyle.width

+                        }

+                    };

+                    self.shapeList.push(axShape);

+                }

+

+            }

+            else {

+                // 纵向

+                var sx = grid.getX();

+                var ex = grid.getXend();

+                var y;

+

+                for (var i = 0; i < dataLength; i++) {

+                    y = getCoord(data[i]);

+                    axShape = {

+                        shape : 'line',

+                        zlevel : _zlevelBase,

+                        hoverable : false,

+                        style : {

+                            xStart : sx,

+                            yStart : y,

+                            xEnd : ex,

+                            yEnd : y,

+                            strokeColor : option.splitLine.lineStyle.color,

+                            lineType : option.splitLine.lineStyle.type,

+                            lineWidth : option.splitLine.lineStyle.width

+                        }

+                    };

+                    self.shapeList.push(axShape);

+                }

+            }

+        }

+

+        function _buildSplitArea() {

+            var axShape;

+            var color = option.splitArea.areaStyle.color;

+

+            if (!(color instanceof Array)) {

+                // 非数组一律认为是单一颜色的字符串,单一颜色则用一个背景,颜色错误不负责啊!!!

+                axShape = {

+                    shape : 'rectangle',

+                    zlevel : _zlevelBase,

+                    hoverable : false,

+                    style : {

+                        x : grid.getX(),

+                        y : grid.getY(),

+                        width : grid.getWidth(),

+                        height : grid.getHeight(),

+                        color : color

+                        // type : option.splitArea.areaStyle.type,

+                    }

+                };

+                self.shapeList.push(axShape);

+            }

+            else {

+                // 多颜色

+                var colorLength = color.length;

+                var data        = _valueList;

+                var dataLength  = _valueList.length;

+

+                if (option.position == 'bottom' || option.position == 'top') {

+                    // 横向

+                    var y = grid.getY();

+                    var height = grid.getHeight();

+                    var lastX = grid.getX();

+                    var curX;

+

+                    for (var i = 0; i <= dataLength; i++) {

+                        curX = i < dataLength

+                               ? getCoord(data[i])

+                               : grid.getXend();

+                        axShape = {

+                            shape : 'rectangle',

+                            zlevel : _zlevelBase,

+                            hoverable : false,

+                            style : {

+                                x : lastX,

+                                y : y,

+                                width : curX - lastX,

+                                height : height,

+                                color : color[i % colorLength]

+                                // type : option.splitArea.areaStyle.type,

+                            }

+                        };

+                        self.shapeList.push(axShape);

+                        lastX = curX;

+                    }

+                }

+                else {

+                    // 纵向

+                    var x = grid.getX();

+                    var width = grid.getWidth();

+                    var lastYend = grid.getYend();

+                    var curY;

+

+                    for (var i = 0; i <= dataLength; i++) {

+                        curY = i < dataLength

+                               ? getCoord(data[i])

+                               : grid.getY();

+                        axShape = {

+                            shape : 'rectangle',

+                            zlevel : _zlevelBase,

+                            hoverable : false,

+                            style : {

+                                x : x,

+                                y : curY,

+                                width : width,

+                                height : lastYend - curY,

+                                color : color[i % colorLength]

+                                // type : option.splitArea.areaStyle.type

+                            }

+                        };

+                        self.shapeList.push(axShape);

+                        lastYend = curY;

+                    }

+                }

+            }

+        }

+

+        /**

+         * 极值计算

+         */

+        function _calculateValue() {

+            if (isNaN(option.min) || isNaN(option.max)) {

+                // 有一个没指定都得算

+                // 数据整形

+                var oriData;            // 原始数据

+                var data = {};          // 整形后数据抽取

+                var value;

+                var xIdx;

+                var yIdx;

+                var legend = component.legend;

+                for (var i = 0, l = series.length; i < l; i++) {

+                    if (series[i].type != ecConfig.CHART_TYPE_LINE

+                        && series[i].type != ecConfig.CHART_TYPE_BAR

+                        && series[i].type != ecConfig.CHART_TYPE_SCATTER

+                    ) {

+                        // 非坐标轴支持的不算极值

+                        continue;

+                    }

+                    // 请允许我写开,跟上面一个不是一样东西

+                    if (legend && !legend.isSelected(series[i].name)){

+                        continue;

+                    }

+

+                    // 不指定默认为第一轴线

+                    xIdx = series[i].xAxisIndex || 0;

+                    yIdx = series[i].yAxisIndex || 0;

+                    if ((option.xAxisIndex != xIdx)

+                        && (option.yAxisIndex != yIdx)

+                    ) {

+                        // 不是自己的数据不计算极值

+                        continue;

+                    }

+

+                    if (!series[i].stack) {

+                        data[series[i].name || ''] = [];

+                        oriData = series[i].data;

+                        for (var j = 0, k = oriData.length; j < k; j++) {

+                            value = typeof oriData[j].value != 'undefined'

+                                    ? oriData[j].value

+                                    : oriData[j];

+                            data[series[i].name || ''].push(value);

+                        }

+                    }

+                    else {

+                        // 堆叠数据,需要区分正负向堆叠

+                        var keyP = '__Magic_Key_Positive__' + series[i].stack;

+                        var keyN = '__Magic_Key_Negative__' + series[i].stack;

+                        data[keyP] = data[keyP] || [];

+                        data[keyN] = data[keyN] || [];

+                        oriData = series[i].data;

+                        for (var j = 0, k = oriData.length; j < k; j++) {

+                            value = typeof oriData[j].value != 'undefined'

+                                    ? oriData[j].value

+                                    : oriData[j];

+                            if (value == '-') {

+                                continue;

+                            }

+                            value = value - 0;

+                            if (value >= 0) {

+                                if (typeof data[keyP][j] != 'undefined') {

+                                    data[keyP][j] += value;

+                                }

+                                else {

+                                    data[keyP][j] = value;

+                                }

+                            }

+                            else {

+                                if (typeof data[keyN][j] != 'undefined') {

+                                    data[keyN][j] += value;

+                                }

+                                else {

+                                    data[keyN][j] = value;

+                                }

+                            }

+                        }

+                    }

+                }

+                // 找极值

+                _min = Number.MAX_VALUE;

+                _max = Number.MIN_VALUE;

+                for (var i in data){

+                    oriData = data[i];

+                    for (var j = 0, k = oriData.length; j < k; j++) {

+                        if (!isNaN(oriData[j])){

+                            _min = Math.min(_min, oriData[j]);

+                            _max = Math.max(_max, oriData[j]);

+                        }

+                    }

+                }

+            }

+

+            _min = isNaN(option.min)

+                   ? (_min - Math.abs(_min * option.boundaryGap[0]))

+                   : option.min;    // 指定min忽略boundaryGay[0]

+

+            _max = isNaN(option.max)

+                   ? (_max + Math.abs(_max * option.boundaryGap[1]))

+                   : option.max;    // 指定max忽略boundaryGay[1]

+            _reformValue();

+        }

+

+        /**

+         * 找到原始数据的极值后根据选项整形最终 _min / _max / _valueList

+         * 如果你不知道这个“整形”的用义,请不要试图去理解和修改这个方法!找我也没用,我相信我已经记不起来!

+         * 如果你有更简洁的数学推导欢迎重写,后果自负~

+         * 一旦你不得不遇到了需要修改或重写的厄运,希望下面的脚手架能帮助你

+         * ps:其实我是想说别搞砸了!升级后至少得保证这些case通过!!

+         *

+         * by linzhifeng@baidu.com 2013-1-8

+         * --------

+             _valueList = [];

+             option = {splitNumber:5,power:100,precision:0};

+             _min = 1; _max = 123; console.log(_min, _max); _reformValue();

+             console.log('result is :', _min, _max, _valueList);

+             console.log('should be : 0 150 [0, 30, 60, 90, 120, 150]',

+                        (_min == 0 && _max == 150) ? 'success' : 'failed');

+

+             _min = 10; _max = 1923; console.log(_min, _max); _reformValue();

+             console.log('result is :', _min, _max, _valueList);

+             console.log('should be : 0 2000 [0, 400, 800, 1200, 1600, 2000]',

+                        (_min == 0 && _max == 2000) ? 'success' : 'failed');

+

+             _min = 10; _max = 78; console.log(_min, _max); _reformValue();

+             console.log('result is :', _min, _max, _valueList);

+             console.log('should be : 0 100 [0, 20, 40, 60, 80, 100]',

+                        (_min == 0 && _max == 100) ? 'success' : 'failed');

+

+             _min = -31; _max = -3; console.log(_min, _max); _reformValue();

+             console.log('result is :', _min, _max, _valueList);

+             console.log('should be : -35 0 [-35, -28, -21, -14, -7, 0]',

+                        (_min == -35 && _max == 0) ? 'success' : 'failed');

+

+             _min = -51; _max = 203; console.log(_min, _max); _reformValue();

+             console.log('result is :', _min, _max, _valueList);

+             console.log('should be : -60 240 [-60, 0, 60, 120, 180, 240]',

+                        (_min == -60 && _max == 240) ? 'success' : 'failed');

+

+             _min = -251; _max = 23; console.log(_min, _max); _reformValue();

+             console.log('result is :', _min, _max, _valueList);

+             console.log('should be : -280 70 [-280, -210, -140, -70, 0, 70]',

+                        (_min == -280 && _max == 70) ? 'success' : 'failed');

+

+             option.precision = 2;

+             _min = 0.23; _max = 0.78; console.log(_min, _max); _reformValue();

+             console.log('result is :', _min, _max, _valueList);

+             console.log('should be : 0.00 1.00'

+                 + '["0.00", "0.20", "0.40", "0.60", "0.80", "1.00"]',

+                (_min == 0.00 && _max == 1.00) ? 'success' : 'failed');

+

+             _min = -12.23; _max = -0.78; console.log(_min, _max);

+             _reformValue();

+             console.log('result is :', _min, _max, _valueList);

+             console.log('should be : -15.00 0.00'

+                 + '["-15.00", "-12.00", "-9.00", "-6.00", "-3.00", "0.00"]',

+                (_min == -15.00 && _max == 0.00) ? 'success' : 'failed');

+

+             _min = -0.23; _max = 0.78; console.log(_min, _max); _reformValue();

+             console.log('result is :', _min, _max, _valueList);

+             console.log('should be : -0.30 1.20'

+                 + '["-0.30", "0.00", "0.30", "0.60", "0.90", "1.20"]',

+                (_min == -0.30 && _max == 1.20) ? 'success' : 'failed');

+

+             _min = -1.23; _max = 0.78; console.log(_min, _max); _reformValue();

+             console.log('result is :', _min, _max, _valueList);

+             console.log('should be : -1.50 1.00'

+                 + '["-1.50", "-1.00", "-0.50", "0.00", "0.50", "1.00"]',

+                (_min == -1.50 && _max == 1.00) ? 'success' : 'failed');

+

+             option.precision = 1;

+             _min = -2.3; _max = 0.5; console.log(_min, _max); _reformValue();

+             console.log('result is :', _min, _max, _valueList);

+             console.log('should be : -2.4 0.6'

+                 + '["-2.4", "-1.8", "-1.2", "-0.6", "0.0", "0.6"]',

+                (_min == -2.4 && _max == 0.6) ? 'success' : 'failed');

+         * --------

+         */

+        function _reformValue() {

+            var splitNumber = option.splitNumber;

+            var precision = option.precision;

+            var splitGap;

+            var power;

+            if (precision === 0) {    // 整数

+                 power = option.power;

+            }

+            else {                          // 小数

+                // 放大倍数后复用整数逻辑,最后再缩小回去

+                power = Math.pow(10, precision);

+                _min *= power;

+                _max *= power;

+            }

+

+            if (_min >= 0 && _max >= 0) {

+                // 双正

+                _min = 0;

+                // power自动降级

+                while ((_max / power < splitNumber) && power != 1) {

+                    power = power / 10;

+                }

+                splitGap = Math.ceil((_max / splitNumber) / power) * power;

+                _max = splitGap * splitNumber;

+            }

+            else if (_min <= 0 && _max <= 0) {

+                // 双负

+                _max = 0;

+                power = -power;

+                // power自动降级

+                while ((_min / power < splitNumber) && power != -1) {

+                    power = power / 10;

+                }

+                splitGap = -Math.ceil((_min / splitNumber) / power) * power;

+                _min = -splitGap * splitNumber;

+            }

+            else {

+                // 一正一负,确保0被选中

+                var total = _max - _min;

+                // power自动降级

+                while ((total / power < splitNumber) && power != 1) {

+                    power = power/10;

+                }

+                // 正数部分的分隔数

+                var partSplitNumber = Math.round(_max / total * splitNumber);

+                // 修正数据范围极度偏正向,留给负数一个

+                partSplitNumber -= (partSplitNumber == splitNumber ? 1 : 0);

+                // 修正数据范围极度偏负向,留给正数一个

+                partSplitNumber += partSplitNumber === 0 ? 1 : 0;

+                splitGap = (Math.ceil(Math.max(

+                                          _max / partSplitNumber,

+                                          _min / (partSplitNumber - splitNumber)

+                                      )

+                           / power))

+                           * power;

+

+                _max = splitGap * partSplitNumber;

+                _min = splitGap * (partSplitNumber - splitNumber);

+            }

+

+            _valueList = [];

+            for (var i = 0; i <= splitNumber; i++) {

+                _valueList.push(_min + splitGap * i);

+            }

+

+            if (precision !== 0) {    // 小数

+                 // 放大倍数后复用整数逻辑,最后再缩小回去

+                power = Math.pow(10, precision);

+                _min = (_min / power).toFixed(precision) - 0;

+                _max = (_max / power).toFixed(precision) - 0;

+                for (var i = 0; i <= splitNumber; i++) {

+                    _valueList[i] = (_valueList[i] / power).toFixed(precision);

+                }

+            }

+

+            _reformLabelData();

+        }

+

+        function _reformLabelData() {

+            _valueLabel = [];

+            var formatter = option.axisLabel.formatter;

+            if (formatter) {

+                for (var i = 0, l = _valueList.length; i < l; i++) {

+                    if (typeof formatter == 'function') {

+                        _valueLabel.push(formatter(_valueList[i]));

+                    }

+                    else if (typeof formatter == 'string') {

+                        _valueLabel.push(

+                            formatter.replace('{value}',_valueList[i])

+                        );

+                    }

+                }

+            }

+            else {

+                _valueLabel = _valueList;

+            }

+

+        }

+

+        /**

+         * 构造函数默认执行的初始化方法,也用于创建实例后动态修改

+         * @param {Object} newZr

+         * @param {Object} newOption

+         * @param {Object} newGrid

+         */

+        function init(newOption, newGrid, newSeries) {

+            if (!newSeries || newSeries.length === 0) {

+                return;

+            }

+            option = self.reformOption(newOption);

+            // 通用字体设置

+            option.axisLabel.textStyle = zrUtil.merge(

+                option.axisLabel.textStyle || {},

+                ecConfig.textStyle,

+                {

+                    'overwrite' : false,

+                    'recursive' : true

+                }

+            );

+            option.axisLabel.textStyle = zrUtil.merge(

+                option.axisLabel.textStyle || {},

+                ecConfig.textStyle,

+                {

+                    'overwrite' : false,

+                    'recursive' : true

+                }

+            );

+            grid = newGrid;

+            series = newSeries;

+

+            self.clear();

+            _buildShape();

+        }

+

+        /**

+         * 刷新

+         */

+        function refresh() {

+            self.clear();

+            _buildShape();

+        }

+

+        // 根据值换算位置

+        function getCoord(value) {

+            value = value < _min ? _min : value;

+            value = value > _max ? _max : value;

+

+            var valueRange = _max - _min;

+            var total;

+            var result;

+            if (option.position == 'left' || option.position == 'right') {

+                // 纵向

+                total = grid.getHeight();

+                result = grid.getYend() - (value - _min) / valueRange * total;

+            }

+            else {

+                // 横向

+                total = grid.getWidth();

+                result = (value - _min) / valueRange * total + grid.getX();

+            }

+

+            // Math.floor可能引起一些偏差,但性能会更好

+            return Math.floor(result);

+        }

+

+        function getPosition() {

+            return option.position;

+        }

+

+        self.init = init;

+        self.refresh = refresh;

+        self.getCoord = getCoord;

+        self.getPosition = getPosition;

+

+        init(option, grid, series);

+    }

+

+    return ValueAxis;

+});

+

diff --git a/src/config.js b/src/config.js
new file mode 100644
index 0000000..6b41ff9
--- /dev/null
+++ b/src/config.js
@@ -0,0 +1,349 @@
+/**

+ * echarts默认配置项

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function() {

+    // 请原谅我这样写,这显然可以直接返回个对象,但那样的话outline就显示不出来了~~

+    var config = {

+        // 图表类型

+        CHART_TYPE_LINE: 'line',

+        CHART_TYPE_BAR: 'bar',

+        CHART_TYPE_SCATTER: 'scatter',

+        CHART_TYPE_PIE: 'pie',

+        CHART_TYPE_RADAR: 'radar',

+        CHART_TYPE_ISLAND: 'island',

+

+        // 组件类型

+        COMPONENT_TYPE_LEGEND: 'legend',

+        COMPONENT_TYPE_DATAVIEW: 'dataView',

+        COMPONENT_TYPE_DATAZOOM: 'dataZoom',

+        COMPONENT_TYPE_TOOLBOX: 'toolbox',

+        COMPONENT_TYPE_TOOLTIP: 'tooltip',

+        COMPONENT_TYPE_GRID: 'grid',

+        COMPONENT_TYPE_AXIS: 'axis',

+        COMPONENT_TYPE_X_AXIS: 'xAxis',

+        COMPONENT_TYPE_Y_AXIS: 'yAxis',

+        COMPONENT_TYPE_AXIS_CATEGORY: 'categoryAxis',

+        COMPONENT_TYPE_AXIS_VALUE: 'valueAxis',

+

+        // 默认色板

+        color: ['#ff7f50','#87cefa','#da70d6','#32cd32','#6495ed',

+                '#ff69b4','#ba55d3','#cd5c5c','#ffa500','#40e0d0',

+                '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',

+                '#6b8e23','#ff00ff','#3cb371','#b8860b','#30e0e0'],

+

+        // 图例

+        legend: {

+            orient: 'horizontal',      // 布局方式,默认为水平布局,可选为:

+                                       // 'horizontal' ¦ 'vertical'

+            x: 'center',               // 水平安放位置,默认为全图居中,可选为:

+                                       // 'center' ¦ 'left' ¦ 'right'

+                                       // ¦ {number}(x坐标,单位px)

+            y: 'top',                  // 垂直安放位置,默认为全图顶端,可选为:

+                                       // 'top' ¦ 'bottom' ¦ 'center'

+                                       // ¦ {number}(y坐标,单位px)

+            backgroundColor: 'rgba(0,0,0,0)',

+            borderColor: '#ccc',       // 图例边框颜色

+            borderWidth: 0,            // 图例边框线宽,单位px,默认为0(无边框)

+            padding: 5,                // 图例内边距,单位px,默认各方向内边距为5,

+                                       // 接受数组分别设定上右下左边距,同css

+            itemGap: 10,               // 各个item之间的间隔,单位px,默认为10,

+                                       // 横向布局时为水平间隔,纵向布局时为纵向间隔

+            // data: []                // 图例内容(详见legend.data,数组中每一项代表一个item

+            itemWidth: 20,             // 图例图形宽度,非标准参数

+            itemHeight: 14,            // 图例图形高度,非标准参数

+            textStyle: {

+                color: '#333'          // 图例文字颜色

+            }

+        },

+

+        toolbox: {

+            show : false,

+            orient: 'horizontal',      // 布局方式,默认为水平布局,可选为:

+                                       // 'horizontal' ¦ 'vertical'

+            x: 'right',                // 水平安放位置,默认为全图右对齐,可选为:

+                                       // 'center' ¦ 'left' ¦ 'right'

+                                       // ¦ {number}(x坐标,单位px)

+            y: 'top',                  // 垂直安放位置,默认为全图顶端,可选为:

+                                       // 'top' ¦ 'bottom' ¦ 'center'

+                                       // ¦ {number}(y坐标,单位px)

+            color : ['#1e90ff','#22bb22','#4b0082','#d2691e'],

+            backgroundColor: 'rgba(0,0,0,0)', // 工具箱背景颜色

+            borderColor: '#ccc',       // 工具箱边框颜色

+            borderWidth: 0,            // 工具箱边框线宽,单位px,默认为0(无边框)

+            padding: 5,                // 工具箱内边距,单位px,默认各方向内边距为5,

+                                       // 接受数组分别设定上右下左边距,同css

+            itemGap: 10,               // 各个item之间的间隔,单位px,默认为10,

+                                       // 横向布局时为水平间隔,纵向布局时为纵向间隔

+            itemSize: 16,             // 工具箱图形宽度,非标准参数

+            feature : {

+                //mark : false,

+                //refresh : false,

+                //magicType: []

+            }

+        },

+

+        // 提示框

+        tooltip: {

+            show: true,

+            trigger: 'item',           // 触发类型,默认数据触发,见下图,可选为:'item' ¦ 'axis'

+            // formatter: null         // 内容格式器:{string}(Template) ¦ {Function}

+            islandFormatter: '{a} <br/>{b} : {c}',  // 数据孤岛内容格式器,非标准参数

+            backgroundColor: 'rgba(0,0,0,0.7)',     // 提示背景颜色,默认为透明度为0.7的黑色

+            borderColor: '#333',       // 提示边框颜色

+            borderRadius: 4,           // 提示边框圆角,单位px,默认为4

+            borderWidth: 0,            // 提示边框线宽,单位px,默认为0(无边框)

+            padding: 5,                // 提示内边距,单位px,默认各方向内边距为5,

+                                       // 接受数组分别设定上右下左边距,同css

+            textStyle: {

+                color: '#fff'

+            }

+        },

+

+        // 区域缩放控制器

+        dataZoom: {

+            show: false,

+            realtime: false,

+            orient: 'horizontal',          // 布局方式,默认为水平布局,可选为:

+                                           // 'horizontal' ¦ 'vertical'

+            backgroundColor: '#eee',       // 背景颜色

+            dataBackgroundColor: '#ccc',   // 数据背景颜色

+            fillerColor: 'rgba(50,205,50,0.4)',        // 填充颜色

+            handleColor: 'rgba(70,130,180,0.8)'         // 手柄颜色

+

+            // x: {number},            // 水平安放位置,默认为根据grid参数适配,可选为:

+                                       // {number}(x坐标,单位px)

+            // y: {number},            // 垂直安放位置,默认为根据grid参数适配,可选为:

+                                       // {number}(y坐标,单位px)

+            // width: {number},        // 指定宽度,横向布局时默认为根据grid参数适配

+            // height: {number},       // 指定高度,纵向布局时默认为根据grid参数适配

+            // xAxisIndex: [],         // 默认控制所有横向类目

+            // yAxisIndex: [],         // 默认控制所有横向类目

+            // start: 0,               // 默认为0

+            // end: 100,               // 默认为全部 100%

+            // zoomLock: false         // 是否锁定选择区域大小

+        },

+

+        // 网格

+        grid: {

+            x: 80,

+            y: 60,

+            // width: {totalWidth} - (2 * x),

+            // height: {totalHeight} - (2 * y)

+            backgroundColor: '#fff',

+            borderWidth: 1,

+            borderColor: '#ccc'

+        },

+

+        // 类目轴

+        categoryAxis: {

+            position: 'bottom',    // 位置

+            boundaryGap: true,     // 类目起始和结束两端空白策略

+            axisLine: {            // 坐标轴线

+                show: true,        // 默认显示,属性show控制显示与否

+                lineStyle: {       // 属性lineStyle控制线条样式

+                    color: '#48b',

+                    width: 2,

+                    style: 'solid'

+                }

+            },

+            axisTick: {            // 坐标轴小标记

+                show: false,       // 属性show控制显示与否,默认不显示

+                length :4,         // 属性length控制线长

+                lineStyle: {       // 属性lineStyle控制线条样式

+                    color: '#ccc',

+                    width: 1

+                }

+            },

+            axisLabel: {           // 坐标轴文本标签,详见axis.axisLabel

+                show: true,

+                interval: 'auto',

+                rotate: 0,

+                margin: 8,

+                // formatter: null,

+                textStyle: {       // 其余属性默认使用全局文本样式,详见TEXTSTYLE

+                    color: '#333'

+                }

+            },

+            splitLine: {           // 分隔线

+                show: true,        // 默认显示,属性show控制显示与否

+                lineStyle: {       // 属性lineStyle(详见lineStyle)控制线条样式

+                    color: '#ccc',

+                    width: 1,

+                    style: 'solid'

+                }

+            },

+            splitArea: {           // 分隔区域

+                show: false,       // 默认不显示,属性show控制显示与否

+                areaStyle: {       // 属性areaStyle(详见areaStyle)控制区域样式

+                    color: ['rgba(250,250,250,0.3)','rgba(200,200,200,0.3)'],

+                    type: 'default'

+                }

+            }

+        },

+

+        // 数值型坐标轴默认参数

+        valueAxis: {

+            position: 'left',      // 位置

+            boundaryGap: [0, 0],   // 数值起始和结束两端空白策略

+            // min: null,          // 最小值

+            // max: null,          // 最大值

+            precision: 0,          // 小数精度,默认为0,无小数点

+            power: 100,            // 整数精度,默认为100,个位和百位为0

+            splitNumber: 5,        // 分割段数,默认为5

+            axisLine: {            // 坐标轴线

+                show: true,        // 默认显示,属性show控制显示与否

+                lineStyle: {       // 属性lineStyle控制线条样式

+                    color: '#48b',

+                    width: 2,

+                    style: 'solid'

+                }

+            },

+            axisTick: {            // 坐标轴小标记

+                show: false,       // 属性show控制显示与否,默认不显示

+                length :4,         // 属性length控制线长

+                lineStyle: {       // 属性lineStyle控制线条样式

+                    color: '#ccc',

+                    width: 1

+                }

+            },

+            axisLabel: {           // 坐标轴文本标签,详见axis.axisLabel

+                show: true,

+                rotate: 0,

+                margin: 8,

+                // formatter: null,

+                textStyle: {       // 其余属性默认使用全局文本样式,详见TEXTSTYLE

+                    color: '#333'

+                }

+            },

+            splitLine: {           // 分隔线

+                show: true,        // 默认显示,属性show控制显示与否

+                lineStyle: {       // 属性lineStyle(详见lineStyle)控制线条样式

+                    color: '#ccc',

+                    width: 1,

+                    style: 'solid'

+                }

+            },

+            splitArea: {           // 分隔区域

+                show: false,       // 默认不显示,属性show控制显示与否

+                areaStyle: {       // 属性areaStyle(详见areaStyle)控制区域样式

+                    color: ['rgba(250,250,250,0.3)','rgba(200,200,200,0.3)'],

+                    type: 'default'

+                }

+            }

+        },

+

+        // 柱形图默认参数

+        bar: {

+            // stack: null

+            xAxisIndex: 0,

+            yAxisIndex: 0,

+            barMinHeight: 20

+            // barWidth: null        // 默认自适应

+        },

+

+        // 折线图默认参数

+        line: {

+            // stack: null

+            xAxisIndex: 0,

+            yAxisIndex: 0,

+            itemStyle: {

+                normal: {

+                    // color: 各异,

+                    lineStyle: {

+                        width: 1,

+                        style: 'solid'

+                    }

+                },

+                emphasis: {

+                    // color: 各异,

+                }

+            },

+            //brokenPoint: null,     // 拐点图形类型,非标准参数

+            brokenPointSize: 4           // 可计算特性参数,空数据拖拽提示图形大小

+        },

+

+        // 饼图默认参数

+        pie: {

+            // center: null,                   // 默认全局居中

+            // radius: [0, min(width,height) - 50],

+            startAngle: 0,

+            minAngle: 5,

+            itemStyle: {

+                normal: {

+                    label: {

+                        show: true,

+                        position: 'outer'

+                        // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE

+                    },

+                    labelLine: {

+                        show: true,

+                        length: 30,

+                        lineStyle: {

+                            // color: 各异,

+                            width: 1,

+                            style: 'solid'

+                        }

+                    }

+                },

+                emphasis: {

+                    label: {

+                        show: false,

+                        position: 'outer'

+                        // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE

+                    },

+                    labelLine: {

+                        show: false,

+                        length: 40,

+                        lineStyle: {

+                            // color: 各异,

+                            width: 1,

+                            style: 'solid'

+                        }

+                    }

+                }

+            }

+        },

+

+        island: {

+            r: 15,

+            calculateStep: 0.1  // 滚轮可计算步长 0.1 = 10%

+        },

+

+        textStyle: {

+            decoration: 'none',

+            fontFamily: 'Arial, Verdana, sans-serif',

+            fontSize: 12,

+            fontStyle: 'normal',

+            fontWeight: 'normal'

+        },

+

+        EVENT: {

+            REFRESH: 'refresh',

+            CLICK: 'click',

+            HOVER: 'hover',

+            // -------

+            DATA_CHANGED: 'dataChanged',

+            DATA_ZOOM: 'dataZoom',

+            LEGEND_SELECTED: 'legendSelected',

+            MAGIC_TYPE_CHANGED: 'magicTypeChanged',

+            DATA_VIEW_CHANGED: 'dataViewChanged'

+        },

+

+        // 可计算特性配置,孤岛,提示颜色

+        calculable: false,              // 默认开启可计算特性

+        calculableColor: 'rgba(255,165,0,0.6)',       // 拖拽提示边框颜色

+        calculableHolderColor: '#ccc', // 可计算占位提示颜色

+        nameConnector: ' & ',

+        valueConnector: ' : ',

+        animation: true,

+        animationDuration: 2000,

+        animationEasing: 'BounceOut'    //ExponentialOut

+    };

+

+    return config;

+});
\ No newline at end of file
diff --git a/src/echarts.js b/src/echarts.js
new file mode 100644
index 0000000..2eaec66
--- /dev/null
+++ b/src/echarts.js
@@ -0,0 +1,663 @@
+/**

+ * echarts

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function(require) {

+    var self = {};

+    self.init = function(dom, libOption) {

+        libOption = libOption || {type : 'canvas'};

+        if (libOption.type == 'canvas') {

+            return new Echarts(dom);

+        }

+        else if (libOption.type == 'flash') {

+            alert('未配置');

+        }

+    };

+

+    /**

+     * 基于zrender实现Echarts接口层

+     * @param {HtmlElement} dom 必要

+     * @param {Object} option 可选参数,同setOption

+     */

+    function Echarts(dom, option) {

+        var ecConfig = require('./config');

+

+        var self = this;

+        var _zr;

+        var _option;

+        var _optionBackup;

+        var _chartList;             // 图表实例

+        var _messageCenter;         // Echarts层的消息中心,做zrender原始事件转换

+

+        var _status = {         // 用于图表间通信

+            dragIn : false,

+            dragOut : false,

+            needRefresh : false

+        };

+

+        var _selectedMap;

+        var _island;

+        var _toolbox;

+

+        // 初始化::构造函数

+        _init();

+        function _init() {

+            var zrender = require('zrender');

+            _zr = zrender.init(dom);

+

+            var zrUtil = require('zrender/tool/util');

+            _option = zrUtil.clone(option || {});

+

+            _chartList = [];            // 图表实例

+

+            _messageCenter = {};        // Echarts层的消息中心,做zrender原始事件转换

+            // 添加消息中心的事件分发器特性

+            var zrEvent = require('zrender/tool/event');

+            zrEvent.Dispatcher.call(_messageCenter);

+            _messageCenter.bind(

+                ecConfig.EVENT.LEGEND_SELECTED, _onlegendSelected

+            );

+            _messageCenter.bind(

+                ecConfig.EVENT.DATA_ZOOM, _ondataZoom

+            );

+            _messageCenter.bind(

+                ecConfig.EVENT.MAGIC_TYPE_CHANGED, _onmagicTypeChanged

+            );

+            _messageCenter.bind(

+                ecConfig.EVENT.DATA_VIEW_CHANGED, _ondataViewChanged

+            );

+            _messageCenter.bind(

+                ecConfig.EVENT.REFRESH, _onrefresh

+            );

+

+            var zrConfig = require('zrender/config');

+            _zr.on(zrConfig.EVENT.CLICK, _onclick);

+            _zr.on(zrConfig.EVENT.MOUSEOVER, _onhover);

+            _zr.on(zrConfig.EVENT.MOUSEWHEEL, _onmousewheel);

+            _zr.on(zrConfig.EVENT.DRAGSTART, _ondragstart);

+            _zr.on(zrConfig.EVENT.DRAGEND, _ondragend);

+            _zr.on(zrConfig.EVENT.DRAGENTER, _ondragenter);

+            _zr.on(zrConfig.EVENT.DRAGOVER, _ondragover);

+            _zr.on(zrConfig.EVENT.DRAGLEAVE, _ondragleave);

+            _zr.on(zrConfig.EVENT.DROP, _ondrop);

+

+

+            var shape = require('zrender/shape');

+            var Icon = require('./util/icon');

+            shape.define('icon', new Icon());

+

+            // 孤岛

+            var chartLibrary = require('./chart');

+            var Island = chartLibrary.get('island');

+            _island = new Island(_messageCenter, _zr);

+

+            // 工具箱

+            var componentLibrary = require('./component');

+            var Toolbox = componentLibrary.get('toolbox');

+            _toolbox = new Toolbox(_messageCenter, _zr, dom);

+        }

+

+        /**

+         * 点击事件,响应zrender事件,包装后分发到Echarts层

+         */

+        function _onclick(param) {

+            var len = _chartList.length;

+            while (len--) {

+                if (_chartList[len].onclick) {

+                    _chartList[len].onclick(param);

+                }

+            }

+            if (param.target) {

+                var ecData = _eventPackage(param.target);

+                if (ecData && typeof ecData.seriesIndex != 'undefined') {

+                    _messageCenter.dispatch(

+                        ecConfig.EVENT.CLICK,

+                        param.event,

+                        ecData

+                    );

+                }

+            }

+        }

+

+         /**

+         * 悬浮事件,响应zrender事件,包装后分发到Echarts层

+         */

+        function _onhover(param) {

+            if (param.target) {

+                var ecData = _eventPackage(param.target);

+                if (ecData && typeof ecData.seriesIndex != 'undefined') {

+                    _messageCenter.dispatch(

+                        ecConfig.EVENT.HOVER,

+                        param.event,

+                        ecData

+                    );

+                }

+            }

+        }

+

+        /**

+         * 滚轮回调,孤岛可计算特性

+         */

+        function _onmousewheel(param) {

+            _messageCenter.dispatch(

+                ecConfig.EVENT.MOUSEWHEEL,

+                param.event,

+                _eventPackage(param.target)

+            );

+        }

+

+        /**

+         * dragstart回调,可计算特性实现

+         */

+        function _ondragstart(param) {

+            // 复位用于图表间通信拖拽标识

+            _status = {

+                dragIn : false,

+                dragOut : false,

+                needRefresh : false

+            };

+            var len = _chartList.length;

+            while (len--) {

+                if (_chartList[len].ondragstart) {

+                    _chartList[len].ondragstart(param);

+                }

+            }

+

+        }

+

+        /**

+         * dragging回调,可计算特性实现

+         */

+        function _ondragenter(param) {

+            var len = _chartList.length;

+            while (len--) {

+                if (_chartList[len].ondragenter) {

+                    _chartList[len].ondragenter(param);

+                }

+            }

+        }

+

+        /**

+         * dragstart回调,可计算特性实现

+         */

+        function _ondragover(param) {

+            var len = _chartList.length;

+            while (len--) {

+                if (_chartList[len].ondragover) {

+                    _chartList[len].ondragover(param);

+                }

+            }

+        }

+        /**

+         * dragstart回调,可计算特性实现

+         */

+        function _ondragleave(param) {

+            var len = _chartList.length;

+            while (len--) {

+                if (_chartList[len].ondragleave) {

+                    _chartList[len].ondragleave(param);

+                }

+            }

+        }

+

+        /**

+         * dragstart回调,可计算特性实现

+         */

+        function _ondrop(param) {

+            var len = _chartList.length;

+            while (len--) {

+                if (_chartList[len].ondrop) {

+                    _chartList[len].ondrop(param, _status);

+                }

+            }

+            _island.ondrop(param, _status);

+        }

+

+        /**

+         * dragdone回调 ,可计算特性实现

+         */

+        function _ondragend(param) {

+            var len = _chartList.length;

+            while (len--) {

+                if (_chartList[len].ondragend) {

+                    _chartList[len].ondragend(param, _status);

+                }

+            }

+            _island.ondragend(param, _status);

+

+            // 发生过重计算

+            if (_status.needRefresh) {

+                _messageCenter.dispatch(

+                    ecConfig.EVENT.DATA_CHANGED,

+                    param.event,

+                    _eventPackage(param.target)

+                );

+                // 先来后到,不能仅刷新自己,也不能在上一个循环中刷新,如坐标系数据改变会影响其他图表的大小

+                // 所以安顺序刷新各种图表,图表内部refresh优化无需更新则不更新~

+                for (var i = 0, l = _chartList.length; i < l; i++) {

+                    _chartList[i].refresh && _chartList[i].refresh();

+                }

+                _zr.refresh();

+            }

+        }

+

+

+        function _onlegendSelected(param) {

+            // 用于图表间通信

+            _status.needRefresh = false;

+            for (var l = _chartList.length - 1; l >= 0; l--) {

+                if (_chartList[l].onlegendSelected) {

+                    _chartList[l].onlegendSelected(param, _status);

+                }

+            }

+            _selectedMap = param.selected;

+

+            if (_status.needRefresh) {

+                for (var i = 0, l = _chartList.length; i < l; i++) {

+                    _chartList[i].refresh && _chartList[i].refresh();

+                }

+                _zr.refresh();

+            }

+        }

+

+        function _ondataZoom(param) {

+            // 用于图表间通信

+            _status.needRefresh = false;

+            for (var l = _chartList.length - 1; l >= 0; l--) {

+                if (_chartList[l].ondataZoom) {

+                    _chartList[l].ondataZoom(param, _status);

+                }

+            }

+

+            if (_status.needRefresh) {

+                for (var i = 0, l = _chartList.length; i < l; i++) {

+                    _chartList[i].refresh && _chartList[i].refresh();

+                }

+                _zr.refresh();

+            }

+        }

+

+        function _onmagicTypeChanged() {

+            var magicOption = _toolbox.getMagicOption();

+            var len;

+            if (_optionBackup.xAxis) {

+                if (_optionBackup.xAxis instanceof Array) {

+                    len = _optionBackup.xAxis.length;

+                    while (len--) {

+                        magicOption.xAxis[len].data =

+                            _optionBackup.xAxis[len].data;

+                    }

+                }

+                else {

+                    magicOption.xAxis.data = _optionBackup.xAxis.data;

+                }

+            }

+            if (_optionBackup.yAxis) {

+                if (_optionBackup.yAxis instanceof Array) {

+                    len = _optionBackup.yAxis.length;

+                    while (len--) {

+                        magicOption.yAxis[len].data =

+                            _optionBackup.yAxis[len].data;

+                    }

+                }

+                else {

+                    magicOption.yAxis.data = _optionBackup.yAxis.data;

+                }

+            }

+

+            len = magicOption.series.length;

+            while (len--) {

+                magicOption.series[len].data = _optionBackup.series[len].data;

+            }

+

+            _render(magicOption);

+        }

+

+        function _ondataViewChanged() {

+            _messageCenter.dispatch(

+                ecConfig.EVENT.DATA_CHANGED

+            );

+            for (var i = 0, l = _chartList.length; i < l; i++) {

+                _chartList[i].refresh && _chartList[i].refresh();

+            }

+            _zr.refresh();

+        }

+

+        function _onrefresh() {

+            _refresh();

+        }

+

+        /**

+         * 打包Echarts层的事件附件

+         */

+        function _eventPackage(target) {

+            if (target) {

+                var ecData = require('./util/ecData');

+                return {

+                    seriesIndex : ecData.get(target, 'seriesIndex'),

+                    dataIndex : ecData.get(target, 'dataIndex')

+                };

+            }

+            return;

+        }

+

+        function _render(magicOption) {

+            _disposeChartList();

+            _zr.clear();

+

+            var chartLibrary = require('./chart');

+            var componentLibrary = require('./component');

+

+            // 提示

+            var tooltip;

+            if (magicOption.tooltip) {

+                var Tooltip = componentLibrary.get('tooltip');

+                tooltip = new Tooltip(_messageCenter, _zr, magicOption, dom);

+                _chartList.push(tooltip);

+            }

+

+            // 图例

+            var legend;

+            if (magicOption.legend) {

+                var Legend = new componentLibrary.get('legend');

+                legend = new Legend(

+                    _messageCenter, _zr, magicOption, _selectedMap

+                );

+                _chartList.push(legend);

+            }

+

+            var grid;

+            var xAxis;

+            var yAxis;

+            if (magicOption.grid || magicOption.xAxis || magicOption.yAxis) {

+                var Grid = componentLibrary.get('grid');

+                grid = new Grid(_messageCenter, _zr, magicOption);

+                _chartList.push(grid);

+

+                var DataZoom = componentLibrary.get('dataZoom');

+                _chartList.push(new DataZoom(

+                    _messageCenter,

+                    _zr,

+                    magicOption,

+                    {

+                        'grid' : grid

+                    }

+                ));

+

+                var Axis = componentLibrary.get('axis');

+                xAxis = new Axis(

+                    _messageCenter,

+                    _zr,

+                    magicOption,

+                    {

+                        'legend' : legend,

+                        'grid' : grid

+                    },

+                    'xAxis'

+                );

+                _chartList.push(xAxis);

+

+                yAxis = new Axis(

+                    _messageCenter,

+                    _zr,

+                    magicOption,

+                    {

+                        'legend' : legend,

+                        'grid' : grid

+                    },

+                    'yAxis'

+                );

+                _chartList.push(yAxis);

+                tooltip && tooltip.setComponent({

+                    'grid' : grid,

+                    'xAxis' : xAxis,

+                    'yAxis' : yAxis

+                });

+            }

+

+            var ChartClass;

+            var chartType;

+            var chart;

+            var chartMap = {};      // 记录已经初始化的图表

+            for (var i = 0, l = magicOption.series.length; i < l; i++) {

+                chartType = magicOption.series[i].type;

+                if (!chartType) {

+                    continue;

+                }

+                if (!chartMap[chartType]) {

+                    chartMap[chartType] = true;

+                    ChartClass = chartLibrary.get(chartType);

+                    if (ChartClass) {

+                        chart = new ChartClass(

+                            _messageCenter,

+                            _zr,

+                            magicOption,

+                            {

+                                'tooltip' : tooltip,

+                                'legend' : legend,

+                                'grid' : grid,

+                                'xAxis' : xAxis,

+                                'yAxis' : yAxis

+                            }

+                        );

+                        _chartList.push(chart);

+                    }

+                }

+            }

+

+            _island.render(magicOption);

+

+            _toolbox.render(magicOption);

+

+            if (magicOption.animation) {

+                var len = _chartList.length;

+                while (len--) {

+                    _chartList[len].animation && _chartList[len].animation();

+                }

+            }

+

+            _zr.render();

+        }

+

+        function _refresh() {

+            var zrUtil = require('zrender/tool/util');

+            _selectedMap = {};

+            _option = zrUtil.clone(_optionBackup);

+            _island.clear();

+            _toolbox.resetMagicType(_option);

+            _render(_option);

+        }

+        /**

+         * 释放图表实例

+         */

+        function _disposeChartList() {

+            var len = _chartList.length;

+            while (len--) {

+                _chartList[len].dispose && _chartList[len].dispose();

+            }

+            _chartList = [];

+        }

+

+        /**

+         * 万能接口,配置图表实例任何可配置选项,多次调用时option选项做merge处理

+         * @param {Object} option

+         * @param {boolean=} notMerge 多次调用时option选项是默认是合并(merge)的,

+         *                   如果不需求,可以通过notMerger参数为true阻止与上次option的合并

+         */

+        function setOption(option, notMerge) {

+            var zrUtil = require('zrender/tool/util');

+            if (!notMerge) {

+                zrUtil.merge(

+                    _option,

+                    zrUtil.clone(option),

+                    {

+                        'overwrite': true,

+                        'recursive': true

+                    }

+                );

+            }

+            else {

+                _option = zrUtil.clone(option);

+            }

+

+            if (!option.series || option.series.length === 0) {

+                return;

+            }

+

+            // 非图表全局属性merge~~

+            if (typeof _option.calculable == 'undefined') {

+                _option.calculable = ecConfig.calculable;

+            }

+            if (typeof _option.nameConnector == 'undefined') {

+                _option.nameConnector = ecConfig.nameConnector;

+            }

+            if (typeof _option.valueConnector == 'undefined') {

+                _option.valueConnector = ecConfig.valueConnector;

+            }

+            if (typeof _option.animation == 'undefined') {

+                _option.animation = ecConfig.animation;

+            }

+            if (typeof _option.animationDuration == 'undefined') {

+                _option.animationDuration = ecConfig.animationDuration;

+            }

+            if (typeof _option.animationEasing == 'undefined') {

+                _option.animationEasing = ecConfig.animationEasing;

+            }

+

+            var zrColor = require('zrender/tool/color');

+            // 数值系列的颜色列表,不传则采用内置颜色,可配数组

+            if (_option.color && _option.color.length > 0) {

+                _zr.getColor = function(idx) {

+                    return zrColor.getColor(idx, _option.color);

+                };

+            }

+            else {

+                _zr.getColor = function(idx) {

+                    return zrColor.getColor(idx, ecConfig.color);

+                };

+            }

+            // calculable可计算颜色提示

+            _zr.getCalculableColor = function () {

+                return _option.calculableColor || ecConfig.calculableColor;

+            };

+

+            _optionBackup = zrUtil.clone(_option);

+            _selectedMap = {};

+

+            _island.clear();

+            _toolbox.resetMagicType(_option);

+            _render(_option);

+            return self;

+        }

+

+        /**

+         * 数据设置快捷接口

+         * @param {Array} series

+         * @param {boolean=} notMerge 多次调用时option选项是默认是合并(merge)的,

+         *                   如果不需求,可以通过notMerger参数为true阻止与上次option的合并。

+         */

+        function setSeries(series, notMerge) {

+            if (!notMerge) {

+                self.setOption({series: series});

+            }

+            else {

+                _option.series = series;

+                self.setOption(_option, notMerge);

+            }

+

+            return self;

+        }

+

+        function getZrender() {

+            return _zr;

+        }

+

+        function on(eventName, eventListener) {

+            _messageCenter.bind(eventName, eventListener);

+            return self;

+        }

+

+        function un(eventName, eventListener) {

+            _messageCenter.unbind(eventName, eventListener);

+            return self;

+        }

+

+        function showLoading(loadingOption) {

+            _toolbox.hideDataView();

+

+            var zrUtil = require('zrender/tool/util');

+            loadingOption = loadingOption || {};

+            loadingOption.textStyle = loadingOption.textStyle || {};

+

+            var finalTextStyle = zrUtil.merge(

+                zrUtil.clone(loadingOption.textStyle),

+                ecConfig.textStyle,

+                { 'overwrite': false}

+            );

+            loadingOption.textStyle.textFont = finalTextStyle.fontStyle + ' '

+                                            + finalTextStyle.fontWeight + ' '

+                                            + finalTextStyle.fontSize + 'px '

+                                            + finalTextStyle.fontFamily;

+

+            loadingOption.textStyle.text = loadingOption.text || 'Loading...';

+

+            if (typeof loadingOption.x != 'undefined') {

+                loadingOption.textStyle.x = loadingOption.x;

+            }

+

+            if (typeof loadingOption.y != 'undefined') {

+                loadingOption.textStyle.y = loadingOption.y;

+            }

+            _zr.showLoading(loadingOption);

+

+            return self;

+        }

+

+        function hideLoading() {

+            _zr.hideLoading();

+            return self;

+        }

+

+        function resize() {

+            _zr.resize();

+            // 先来后到,不能仅刷新自己,也不能在上一个循环中刷新,如坐标系数据改变会影响其他图表的大小

+            // 所以安顺序刷新各种图表,图表内部refresh优化无需更新则不更新~

+            for (var i = 0, l = _chartList.length; i < l; i++) {

+                _chartList[i].refresh && _chartList[i].refresh();

+            }

+            _zr.refresh();

+        }

+

+        function clear() {

+            _zr.clear();

+            return self;

+        }

+

+        function dispose() {

+            _island.dispose();

+            _toolbox.dispose();

+            _disposeChartList();

+            _messageCenter.unbind();

+            _zr.dispose();

+            self = null;

+            return;

+        }

+

+        self.setOption = setOption;

+        self.setSeries = setSeries;

+        self.getZrender = getZrender;

+        self.on = on;

+        self.un = un;

+        self.showLoading = showLoading;

+        self.hideLoading = hideLoading;

+        self.resize = resize;

+        self.clear = clear;

+        self.dispose = dispose;

+    }

+

+    return self;

+});
\ No newline at end of file
diff --git a/src/util/ecData.js b/src/util/ecData.js
new file mode 100644
index 0000000..2b00a3d
--- /dev/null
+++ b/src/util/ecData.js
@@ -0,0 +1,117 @@
+/**

+ * echarts通用私有数据服务

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ */

+define(function() {

+    /**

+     * 打包私有数据

+     *

+     * @param {shape} shape 修改目标

+     * @param {Object} series

+     * @param {number} seriesIndex

+     * @param {number | Object} data

+     * @param {number} dataIndex

+     * @param {*=} special

+     */

+    function pack(shape, series, seriesIndex, data, dataIndex, name, special) {

+        var value;

+        if (typeof data != 'undefined') {

+            if (typeof data.value != 'undefined') {

+                if (data.value instanceof Array) {

+                    value = data.value[2];  // 散点图最后一个为数值

+                }

+                else {

+                    value = data.value;

+                }

+            }

+            else {

+                value = data;

+            }

+        }

+

+        shape._echartsData =  {

+            '_series' : series,

+            '_seriesIndex' : seriesIndex,

+            '_data' : data,

+            '_dataIndex' : dataIndex,

+            '_name' : name,

+            '_value' : value,

+            '_special' : special

+        };

+        return shape._echartsData;

+    }

+

+    /**

+     * 从私有数据中获取特定项

+     * @param {shape} shape

+     * @param {string} key

+     */

+    function get(shape, key) {

+        var data = shape._echartsData;

+        if (!key) {

+            return data;

+        }

+

+        switch (key) {

+            case 'series' :

+                return data && data._series;

+            case 'seriesIndex' :

+                return data && data._seriesIndex;

+            case 'data' :

+                return data && data._data;

+            case 'dataIndex' :

+                return data && data._dataIndex;

+            case 'name' :

+                return data && data._name;

+            case 'value' :

+                return data && data._value;

+            case 'special' :

+                return data && data._special;

+        }

+

+        return null;

+    }

+

+    /**

+     * 修改私有数据中获取特定项

+     * @param {shape} shape

+     * @param {string} key

+     * @param {*} value

+     */

+    function set(shape, key, value) {

+        shape._echartsData = shape._echartsData || {};

+        switch (key) {

+            case 'series' :             // 当前系列值

+                shape._echartsData._series = value;

+                break;

+            case 'seriesIndex' :        // 系列数组位置索引

+                shape._echartsData._seriesIndex = value;

+                break;

+            case 'data' :               // 当前数据值

+                shape._echartsData._data = value;

+                break;

+            case 'dataIndex' :          // 数据数组位置索引

+                shape._echartsData._dataIndex = value;

+                break;

+            case 'name' :

+                shape._echartsData._name = value;

+                break;

+            case 'value' :

+                shape._echartsData._value = value;

+                break;

+            case 'special' :

+                shape._echartsData._special = value;

+                break;

+        }

+    }

+

+    return {

+        pack : pack,

+        set : set,

+        get : get

+    };

+});
\ No newline at end of file
diff --git a/src/util/icon.js b/src/util/icon.js
new file mode 100644
index 0000000..d940350
--- /dev/null
+++ b/src/util/icon.js
@@ -0,0 +1,334 @@
+/**

+ * echarts扩展zrender shape

+ * Copyright 2013 Baidu Inc. All rights reserved.

+ *

+ * @author Kener (@Kener-林峰, linzhifeng@baidu.com)

+ *

+ * shape类:icon

+ * 可配图形属性:

+   {

+       // 基础属性

+       shape  : 'icon',       // 必须,shape类标识,需要显式指定

+       id     : {string},       // 必须,图形唯一标识,可通过zrender实例方法newShapeId生成

+       zlevel : {number},       // 默认为0,z层level,决定绘画在哪层canvas中

+       invisible : {boolean},   // 默认为false,是否可见

+

+       // 样式属性,默认状态样式样式属性

+       style  : {

+           x             : {number},  // 必须,左上角横坐标

+           y             : {number},  // 必须,左上角纵坐标

+           width         : {number},  // 必须,宽度

+           height        : {number},  // 必须,高度

+           iconType      : {string},  // 必须,icon类型

+           brushType     : {string},  // 默认为fill,绘画方式

+                                      // fill(填充) | stroke(描边) | both(填充+描边)

+           color         : {color},   // 默认为'#000',填充颜色,支持rgba

+           strokeColor   : {color},   // 默认为'#000',描边颜色(轮廓),支持rgba

+           lineWidth     : {number},  // 默认为1,线条宽度,描边下有效

+

+           opacity       : {number},  // 默认为1,透明度设置,如果color为rgba,则最终透明度效果叠加

+           shadowBlur    : {number},  // 默认为0,阴影模糊度,大于0有效

+           shadowColor   : {color},   // 默认为'#000',阴影色彩,支持rgba

+           shadowOffsetX : {number},  // 默认为0,阴影横向偏移,正值往右,负值往左

+           shadowOffsetY : {number},  // 默认为0,阴影纵向偏移,正值往下,负值往上

+

+           text          : {string},  // 默认为null,附加文本

+           textFont      : {string},  // 默认为null,附加文本样式,eg:'bold 18px verdana'

+           textPosition  : {string},  // 默认为top,附加文本位置。

+                                      // inside | left | right | top | bottom

+           textAlign     : {string},  // 默认根据textPosition自动设置,附加文本水平对齐。

+                                      // start | end | left | right | center

+           textBaseline  : {string},  // 默认根据textPosition自动设置,附加文本垂直对齐。

+                                      // top | bottom | middle |

+                                      // alphabetic | hanging | ideographic

+           textColor     : {color},   // 默认根据textPosition自动设置,默认策略如下,附加文本颜色

+                                      // 'inside' ? '#fff' : color

+       },

+

+       // 样式属性,高亮样式属性,当不存在highlightStyle时使用基于默认样式扩展显示

+       highlightStyle : {

+           // 同style

+       }

+

+       // 交互属性,详见shape.Base

+

+       // 事件属性,详见shape.Base

+   }

+         例子:

+   {

+       shape  : 'icon',

+       id     : '123456',

+       zlevel : 1,

+       style  : {

+           x : 200,

+           y : 100,

+           width : 150,

+           height : 50,

+           color : '#eee',

+           text : 'Baidu'

+       },

+       myName : 'kener',  // 可自带任何有效自定义属性

+

+       clickable : true,

+       onClick : function(eventPacket) {

+           alert(eventPacket.target.myName);

+       }

+   }

+ */

+define(

+    function(require) {

+        function Icon() {

+            this.type = 'icon';

+            this.brushTypeOnly = 'stroke';

+            this._iconLibrary = {

+                mark : _iconMark,

+                markUndo : _iconMarkUndo,

+                markClear : _iconMarkClear,

+                refresh : _iconRefresh,

+                lineChart : _iconLineChart,

+                barChart : _iconBarChart,

+                dataView : _iconDataView

+            };

+        }

+

+        function _iconMark(ctx, style) {

+            var dx = style.width / 16;

+            var dy = style.height / 16;

+            ctx.moveTo(style.x,                 style.y + style.height);

+            ctx.lineTo(style.x + 5 * dx,        style.y + 14 * dy);

+            ctx.lineTo(style.x + style.width,   style.y + 3 * dy);

+            ctx.lineTo(style.x + 13 * dx,       style.y);

+            ctx.lineTo(style.x + 2 * dx,        style.y + 11 * dy);

+            ctx.lineTo(style.x,                 style.y + style.height);

+

+            ctx.moveTo(style.x + 6 * dx,        style.y + 10 * dy);

+            ctx.lineTo(style.x + 14 * dx,       style.y + 2 * dy);

+

+            ctx.moveTo(style.x + 10 * dx,       style.y + 13 * dy);

+            ctx.lineTo(style.x + style.width,   style.y + 13 * dy);

+

+            ctx.moveTo(style.x + 13 * dx,       style.y + 10 * dy);

+            ctx.lineTo(style.x + 13 * dx,       style.y + style.height);

+        }

+

+        function _iconMarkUndo(ctx, style) {

+            var dx = style.width / 16;

+            var dy = style.height / 16;

+            ctx.moveTo(style.x,                 style.y + style.height);

+            ctx.lineTo(style.x + 5 * dx,        style.y + 14 * dy);

+            ctx.lineTo(style.x + style.width,   style.y + 3 * dy);

+            ctx.lineTo(style.x + 13 * dx,       style.y);

+            ctx.lineTo(style.x + 2 * dx,        style.y + 11 * dy);

+            ctx.lineTo(style.x,                 style.y + style.height);

+

+            ctx.moveTo(style.x + 6 * dx,        style.y + 10 * dy);

+            ctx.lineTo(style.x + 14 * dx,       style.y + 2 * dy);

+

+            ctx.moveTo(style.x + 10 * dx,       style.y + 13 * dy);

+            ctx.lineTo(style.x + style.width,   style.y + 13 * dy);

+        }

+

+        function _iconMarkClear(ctx, style) {

+            var dx = style.width / 16;

+            var dy = style.height / 16;

+

+            ctx.moveTo(style.x + 4 * dx,        style.y + 15 * dy);

+            ctx.lineTo(style.x + 9 * dx,        style.y + 13 * dy);

+            ctx.lineTo(style.x + 14 * dx,       style.y + 8 * dy);

+            ctx.lineTo(style.x + 11 * dx,       style.y + 5 * dy);

+            ctx.lineTo(style.x + 6 * dx,        style.y + 10 * dy);

+            ctx.lineTo(style.x + 4 * dx,        style.y + 15 * dy);

+

+            ctx.moveTo(style.x + 5 * dx,        style.y);

+            ctx.lineTo(style.x + 11 * dx,        style.y);

+            ctx.moveTo(style.x + 5 * dx,        style.y + dy);

+            ctx.lineTo(style.x + 11 * dx,        style.y + dy);

+            ctx.moveTo(style.x,        style.y + 2 * dy);

+            ctx.lineTo(style.x + style.width,        style.y + 2 * dy);

+

+            ctx.moveTo(style.x,        style.y + 5 * dy);

+            ctx.lineTo(style.x + 3 * dx,        style.y + style.height);

+            ctx.lineTo(style.x + 13 * dx,        style.y + style.height);

+            ctx.lineTo(style.x + style.width,        style.y + 5 * dy);

+        }

+

+        function _iconRefresh(ctx, style) {

+            var dx = style.width / 16;

+            var dy = style.height / 16;

+            var r = style.width / 2;

+

+            ctx.arc(style.x + r, style.y + r, r - dx, 0, Math.PI * 2 / 3);

+            ctx.moveTo(style.x + 3 * dx,        style.y + style.height);

+            ctx.lineTo(style.x + 0 * dx,        style.y + 12 * dy);

+            ctx.lineTo(style.x + 5 * dx,        style.y + 11 * dy);

+

+            ctx.moveTo(style.x, style.y + 8 * dy);

+            ctx.arc(style.x + r, style.y + r, r - dx, Math.PI, Math.PI * 5 / 3);

+            ctx.moveTo(style.x + 13 * dx,       style.y);

+            ctx.lineTo(style.x + style.width,   style.y + 4 * dy);

+            ctx.lineTo(style.x + 11 * dx,       style.y + 5 * dy);

+        }

+

+        function _iconLineChart(ctx, style) {

+            var dx = style.width / 16;

+            var dy = style.height / 16;

+

+            ctx.moveTo(style.x, style.y);

+            ctx.lineTo(style.x, style.y + style.height);

+            ctx.lineTo(style.x + style.width, style.y + style.height);

+

+            ctx.moveTo(style.x + 2 * dx,    style.y + 14 * dy);

+            ctx.lineTo(style.x + 7 * dx,    style.y + 6 * dy);

+            ctx.lineTo(style.x + 11 * dx,   style.y + 11 * dy);

+            ctx.lineTo(style.x + 15 * dx,   style.y + 2 * dy);

+        }

+

+        function _iconBarChart(ctx, style) {

+            var dx = style.width / 16;

+            var dy = style.height / 16;

+

+            ctx.moveTo(style.x, style.y);

+            ctx.lineTo(style.x, style.y + style.height);

+            ctx.lineTo(style.x + style.width, style.y + style.height);

+

+            ctx.moveTo(style.x + 3 * dx,        style.y + 14 * dy);

+            ctx.lineTo(style.x + 3 * dx,        style.y + 6 * dy);

+            ctx.lineTo(style.x + 4 * dx,        style.y + 6 * dy);

+            ctx.lineTo(style.x + 4 * dx,        style.y + 14 * dy);

+            ctx.moveTo(style.x + 7 * dx,        style.y + 14 * dy);

+            ctx.lineTo(style.x + 7 * dx,        style.y + 2 * dy);

+            ctx.lineTo(style.x + 8 * dx,        style.y + 2 * dy);

+            ctx.lineTo(style.x + 8 * dx,        style.y + 14 * dy);

+            ctx.moveTo(style.x + 11 * dx,       style.y + 14 * dy);

+            ctx.lineTo(style.x + 11 * dx,       style.y + 9 * dy);

+            ctx.lineTo(style.x + 12 * dx,       style.y + 9 * dy);

+            ctx.lineTo(style.x + 12 * dx,       style.y + 14 * dy);

+        }

+

+        function _iconDataView(ctx, style) {

+            var dx = style.width / 16;

+

+            ctx.moveTo(style.x + dx, style.y);

+            ctx.lineTo(style.x + dx, style.y + style.height);

+            ctx.lineTo(style.x + 15 * dx, style.y + style.height);

+            ctx.lineTo(style.x + 15 * dx, style.y);

+            ctx.lineTo(style.x + dx, style.y);

+

+            ctx.moveTo(style.x + 3 * dx, style.y + 3 * dx);

+            ctx.lineTo(style.x + 13 * dx, style.y + 3 * dx);

+

+            ctx.moveTo(style.x + 3 * dx, style.y + 6 * dx);

+            ctx.lineTo(style.x + 13 * dx, style.y + 6 * dx);

+

+            ctx.moveTo(style.x + 3 * dx, style.y + 9 * dx);

+            ctx.lineTo(style.x + 13 * dx, style.y + 9 * dx);

+

+            ctx.moveTo(style.x + 3 * dx, style.y + 12 * dx);

+            ctx.lineTo(style.x + 9 * dx, style.y + 12 * dx);

+

+        }

+

+        Icon.prototype =  {

+            /**

+             * 创建矩形路径

+             * @param {Context2D} ctx Canvas 2D上下文

+             * @param {Object} style 样式

+             */

+            buildPath : function(ctx, style) {

+                if (this._iconLibrary[style.iconType]) {

+                    this._iconLibrary[style.iconType](ctx, style);

+                }

+                else {

+                    ctx.moveTo(style.x, style.y);

+                    ctx.lineTo(style.x + style.width, style.y);

+                    ctx.lineTo(style.x + style.width, style.y + style.height);

+                    ctx.lineTo(style.x, style.y + style.height);

+                    ctx.lineTo(style.x, style.y);

+                }

+

+                return;

+            },

+

+            /**

+             * 返回矩形区域,用于局部刷新和文字定位

+             * @param {Object} style

+             */

+            getRect : function(style) {

+                return {

+                    x : Math.round(style.x),

+                    y : Math.round(style.y),

+                    width : style.width,

+                    height : style.height

+                };

+            },

+

+            isCover : function(e, x, y) {

+                //对鼠标的坐标也做相同的变换

+                if(e.__needTransform && e._transform){

+                    var inverseMatrix = [];

+                    matrix.invert(inverseMatrix, e._transform);

+

+                    var originPos = [x, y];

+                    matrix.mulVector(originPos, inverseMatrix, [x, y, 1]);

+

+                    if (x == originPos[0] && y == originPos[1]) {

+                        // 避免外部修改导致的__needTransform不准确

+                        if (Math.abs(e.rotation[0]) > 0.0001

+                            || Math.abs(e.position[0]) > 0.0001

+                            || Math.abs(e.position[1]) > 0.0001

+                            || Math.abs(e.scale[0] - 1) > 0.0001

+                            || Math.abs(e.scale[1] - 1) > 0.0001

+                        ) {

+                            e.__needTransform = true;

+                        } else {

+                            e.__needTransform = false;

+                        }

+                    }

+

+                    x = originPos[0];

+                    y = originPos[1];

+                }

+

+                // 快速预判并保留判断矩形

+                var rect;

+                if (e.style.__rect) {

+                    rect = e.style.__rect;

+                }

+                else {

+                    rect = this.getRect(e.style);

+                    rect = [

+                        rect.x,

+                        rect.x + rect.width,

+                        rect.y,

+                        rect.y + rect.height

+                    ];

+                    e.style.__rect = rect;

+                }

+                if (x >= rect[0]

+                    && x <= rect[1]

+                    && y >= rect[2]

+                    && y <= rect[3]

+                ) {

+                    // 矩形内

+                    return true;

+                }

+                else {

+                    return false;

+                }

+            },

+

+            define : function(iconType, pathMethod) {

+                _iconLibrary[iconType] = pathMethod;

+            },

+

+            get : function(iconType) {

+                return _iconLibrary[iconType];

+            }

+        };

+

+        var base = require('zrender/shape/base');

+            base.derive(Icon);

+

+        return Icon;

+    }

+);
\ No newline at end of file